进程
是一种抽象概念,从来没有统一的标准定义:
fork()函数用来创建一个新的进程,新创建的这个进程的data数据段,stack堆栈段等进程基本的内容以及当前程序状态指针PC-point也完全和父进程相同!也就是说fork创建的子进程是父进程的副本,新创建的这个进程,Linux会为它分配对应的内存页来保存与父进程完全相同data、stack、进程运行到的目前的状态。但是对于程序段text,父进程与子进程是共享的!
fork()函数调用后有2个返回值,调用一次,返回两次。成功调用fork函数后,当前进程实际上已经分裂为两个进程,一个是原来的父进程,另一个是刚刚创建的子进程。fork()函数的2个返回值,一个是父进程调用fork函数后的返回值,该返回值是刚刚创建的子进程的ID;另一个是子进程中fork函数的返回值,该返回值是0。这样可以用返回值来区分父、子进程。
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
main()
{
pid_t pid;
char *msg;
int k;
pid=fork();
switch(pid){
//子进程执行部分
case 0:
msg="Child process is running.\n";
k=3;
break;
case -1:
perror("Process creation failed.\n");
break;
//父进程执行部分
default:
msg="Parent process is running.\n";
k=5;
break;
}
//父子进程共同执行部分
while(k>0){
puts(msg);
sleep(1);
k--;
}
}
上例中子进程输出3条消息,父进程输出5条消息。执行子进程和父进程时打印出的消息是不一样的。从输出可以看出父子进程交替进行。
注意:父子进程终止的先后顺序不同会产生不同的结果。
(1)在子进程退出前父进程先退出,则系统会让init进程接管子进程。
(2)当子进程先于父进程终止,而父进程又没有调用wait函数等待子进程结束,子进程进入僵尸状态,并且会一直保持下去除非系统重启。子进程处于僵尸状态时,内核只保存该进程的一些必要信息以备父进程所需。此时子进程始终占用着资源,同时也减少了系统可以创建的最大进程数。如果子进程先于父进程终止,且父进程调用了wait或waitpid函数,则父进程会等待子进程结束。
(3)在Linux下,可以简单地将SIGCHLD信号的操作设为SIG_IGN,这样当子进程结束时就不会称为僵尸进程。