程序: 存储在磁盘上的可执行指令和数据的静态实体。
进程: 具有一定功能的程序关于一个数据集合的一次运行活动。
Linux中每创建一个进程,系统将从内存中创建一个task_struct 放入到 task 数组。
进程有两种运行模式: 用户模式 ,系统模式
进程不能被抢占。Linux采用了预加载调度策略,每个进程只允许运行很短的时间(200ms), 这段时间称之为时间片。
通过fork函数来创建子进程,它是单调用双返回函数,父进程中返回子进程标识号,子进程中返回0 代表 创建成功。在进程数超过系统限制或者进程请求的空间得不到满足的时候会出现创建失败的情况。如果父进程在创建子进程之前创建了共享内存,则子进程也拥有操作此共享内存的权利,因此要控制好同步操作。
vfork 创建的新进程主要目的在于用exec函数执行另外的程序。一般情况下,子进程用不到父进程的数据段,实际上在它还没有运行exec或exit 之前是与父进程共享数据段的。子进行先用运行,父进程挂起,直到子进程调用exec或exit后,父进程的执行次序不再受限制。
vfork()用法与fork()相似.但是也有区别,具体区别归结为以下3点:
1. fork():子进程拷贝父进程的数据段,代码段. vfork():子进程与父进程共享数据段.
2. fork():父子进程的执行次序不确定.
vfork():保证子进程先运行,在调用exec或exit之前与父进程数据是共享的,在它调用exec
或exit之后父进程才可能被调度运行。
3. vfork()保证子进程先运行,在她调用exec或exit之后父进程才可能被调度运行。如果在
调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。
进程等待
进程一旦调用了wait就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。
参数status用来保存被收集进程退出时的一些状态,它是一个指向int类型的指针。但如果我们对这个子进程是如何死掉毫不在意,只想把这个僵尸进程消灭掉,(事实上绝大多数情况下,我们都会这样想),我们就可以设定这个参数为NULL,就像下面这样: pid = wait(NULL); 如果成功,wait会返回被收集的子进程的进程ID,如果调用进程没有子进程,调用就会失败,此时wait返回-1,同时errno被置为ECHILD。
一个简单的c demo 实现子进程创建、进程等待等操作
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
int main()
{
int stat;
pid_t pid;
while((pid=fork())==-1);
if(pid==0)
{
execl("/bin/date","/bin/date",(char*)0);
return 0;
}
wait(&stat);
printf("stat:%d\n",stat);
return 0;
}