网络编程中对进程的理解(Linux + GCC)
来源:互联网 发布:php访问量 ip 编辑:程序博客网 时间:2024/06/11 16:22
理解进程(Process)
接下来了多进程服务器实现的重点内容——进程。其定义如下:
“占用内存空间的正在运行的程序”。
假如各位从网上下载了LBreakout游戏并安装到硬盘。此时的游戏并非进程,而是程序。因为游戏并未进入运行状态。下面开始运行程序。此时游戏被加载到主内存并进入运行状态,这时才可称为进程。如果同时运行多个LBreakout程序,则会生成相应数量的进程,也会占用相应进程数的内存空间。
再举个例子。假设各位需要进行文档相关操作,这是应打开文档编辑软件。如果工作的同时还想听音乐,应打开MP3播放器。另外,为了与朋友聊天,再打开MSN软件。此时共创建3个进程。从操作系统的角度看,进程是程序流的基本单位,若创建多个进程,则操作系统将同时进行。有时一个程序运行过程中也会产生多个进程。接下来要创建的多进程服务器就是其中的代表。编写服务器端前,先了解一下通过程序创建进程的方法。
提示: CPU核的个数与进程数
拥有2个运算设备的CPU称作双核(Daul)CPU,拥有4个运算器的CPU称作4核(Quad)CPU。也就是说1个CPU中可能包含多个运算设备(核)。核的个数与可同时运行的进程数相同。相反,若进程数超过核数,进程将分时使用CPU资源。但因为CPU运转速度极快,我们会感到所有进程同时运行。当然,核数越多,这种感觉越明显。
进程ID
讲解创建进程方法前,先简要说明进程ID。无论进程是如何创建的,所有进程都会从操作系统分配ID。此ID称为“进程ID”,其值为大于2的整数。1要分配给操作系统启动后的(用于协助操作系统)首个进程,因此用户进程无法得到ID值1。接下来观察Linux中正在运行的进程。
运行结果:ps命令语句
ycz@debian8470p:~$ ps au
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 3228 1.7 1.2 199308 105532 tty7 Ss+ 11:15 3:28 /usr/bin/X :0 v
root 3270 0.0 0.0 16468 944 tty1 Ss+ 11:15 0:00 /sbin/getty 384
root 3271 0.0 0.0 16468 944 tty2 Ss+ 11:15 0:00 /sbin/getty 384
root 3272 0.0 0.0 16468 948 tty3 Ss+ 11:15 0:00 /sbin/getty 384
root 3273 0.0 0.0 16468 952 tty4 Ss+ 11:15 0:00 /sbin/getty 384
root 3274 0.0 0.0 16468 952 tty5 Ss+ 11:15 0:00 /sbin/getty 384
root 3275 0.0 0.0 16468 956 tty6 Ss+ 11:15 0:00 /sbin/getty 384
ycz 5431 1.0 0.0 21304 3808 pts/0 Ss 14:29 0:00 bash
ycz 5477 0.0 0.0 17048 1284 pts/0 R+ 14:29 0:00 ps au
ycz@debian8470p:~$
可以看出,通过ps指令可以查看当前运行的所有进程。特别需要注意的是,该命令同时列出了PID(进程ID)。另外,上述示例通过指定a和u参数列出了所有进程详细信息。
通过调用fork函数创建进程
创建进程的方法很多,此处只介绍用于创建多进程服务器端的fork函数。
#include <unisd.h>
pid_t fork(void);
----->成功时返回进程ID,失败时返回-1
fork函数将创建调用的进程副本(概念上略难)。也就是说,并非根据完全不同的程序创建进程,而是复制正在运行的,调用fork函数的进程。另外,两个进程都将执行fork函数调用后的语句(准确地说是在fork函数返回后)。但因为通过同一个进程,复制相同的内存空间,之后的程序流要根据fork函数的返回值加以区分。即利用fork函数的如下特点区分程序执行流程。
父进程:fork函数返回子进程ID。
子进程:fork函数返回0
此处“父进程”(Parent Process)指原进程,即调用fork函数的主体,而“子进程”(Child Process)是通过父进程调用fork函数复制出的进程。接下来讲解调用fork函数后的程序运行流程,如下代码:
//父进程int gval = 10;int main(void){ int lval = 20; lval+=5; gval++; pid_t pid = fork(); //复制生成点,pid为子进程ID if(pid==0) gval++; else lval++; //运行 ......}
//子进程//gval复制为11int main(void){ //lval复制为25 .... pid_t pid = fork(); //pid为0! if(pid==0) gval++; //运行 else lval++; ......}
从以上代码中可以看到,父进程调用fork函数的同时复制出子进程,并分别得到fork函数的返回值。但复制前,父进程将全局变量gval增加到11,将局部变量lval的值增加到25,因此在这种状态下完成进程复制。复制完成后根据fork函数的返回类型区分父子进程。父进程将lval的值加1,但这不会影响子进程的lval值。同样,子进程将gval的值加1也不会影响到父进程的gval。因为fork函数调用后分成了完全不同的进程,只是二者共享同一代码而已。接下来给出示例验证之前的内容。
fork.c
#include<stdio.h>#include<unistd.h>int gval = 10;int main(int argc,char *argv[]){ pid_t pid; int lval = 20; gval++,lval+=5; pid = fork(); //创建子进程。父进程的pid中存有子进程的ID,子进程的pid是0. if(pid==0) //if Child Process,子进程执行这2行代码,因为pid为0 gval+=2,lval+=2; else //if Parent Process,父进程执行这2行代码,因为此时pid存有子进程ID gval-=2,lval-=2; if(pid==0) printf("Child Proc:[%d,%d] \n",gval,lval); else printf("Parent Proc:[%d,%d] \n",gval,lval); return 0;}
运行结果:fork.c
ycz@debian8470p:~/program/TCP&&IP/chapter10$ gcc fork.c -o fork
ycz@debian8470p:~/program/TCP&&IP/chapter10$ ./fork
Parent Proc:[9,23]
Child Proc:[13,27]
从运行结果可以看出,调用fork函数后,父子进程拥有完全独立的内存结构。我认为关于fork函数无需更多示例,希望各位通过该示例充分理解调用fork函数创建进程的方法。
- 网络编程中对进程的理解(Linux + GCC)
- 对linux进程的理解
- Java网络编程中对Socket的理解
- 对linux中进程创建的一点理解(1)
- 对linux中进程创建的一点理解(2)
- 对linux 0.11版本中进程调度源码的理解
- 对linux中多线程编程中pthread_join的理解
- 对linux中多线程编程中pthread_join的理解
- 对Linux中多线程编程中pthread_join的理解
- 对gcc的理解
- 对多线程网络编程的理解
- kill命令的使用和对linux进程中僵死进程的理解
- 网络编程(32)—— linux中销毁僵尸进程的四种方法
- linux中gcc编程
- Linux下的多进程编程(理解)
- 初学linux c编程 对select()自己的理解
- C#中进程的应用(网络编程)
- 从网络编程实践中加深对TCP协议三次握手的理解
- Leetcode 104. Maximum Depth of Binary Tree
- 飛飛(五十一)重载函数的应用
- 基数排序 原始java实现 时间复杂度O(n)
- 几种循环的区别
- 第14周-项目2-两个成员的类模板(2)
- 网络编程中对进程的理解(Linux + GCC)
- Android动画效果translate、scale、alpha、rotate
- FFmpeg之音视频相关概念
- Scala简明教程(2)
- 康托展开
- 第十三周项目二:分数类中的运算符重载(3)
- linux课堂笔记
- ceylon 学习4 set get 优化
- C++ using关键字作用总结