1. 引入
怎么创建新的进程呢?这里有一段代码:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void)
{
int pid;
/* fork another process */
pid = fork();
if (pid<0)
{
/* error occurred */
fprintf(stderr,"Fork Failed!");
exit(-1);
}
else if (pid==0)
{
/* child process */
printf("This is Child Process!\n");
}
else
{
/* parent process */
printf("This is Parent Process!\n");
/* parent will wait for the child to complete*/
wait(NULL);
printf("Child Complete!\n");
}
return 0;
}
这段代码的执行就能产生一个子进程,而证据就是条件语句中分支 else if (pid == 0) 和 else 都会被执行,这好像有悖我们对 C 语言的认知,因为条件语句是封死的,每个变量只能被划分到一个分支中去,换句话说就是只有一个分支会被执行。
这里涉及到进程的概念,什么叫做进程?进程是一段程序的执行体,换句话说进程是活的,程序是死的。而我们所能看到的代码就是程序的尸体;经过编译链接生成可执行二进制文件后,尸体死而复生变成了程序,而程序也是不动的,它是按兵不动的兵;只有要打仗了,程序会被装载到内存中去,才能变成骁勇善战的战士——进程。(好吧,这段是瞎扯的)进程可是我们看不到的哦,有些自大的程序员以为看到代码就能看到进程了,too young, too simple, somestime navie啊~(当然,我们可以让进程停一停,问一问你的变量现在是多少啊,堆栈里面内容是什么啊?题外话了)也就是说我们看到的跟实际执行的过程并不是完全一致。我这里提出自己对进程的一种理解方法:程序代码好像是一条干涸的河道,而一条条溪流漂浮在上面的就是一个个进程,进程之间有共性,相互之间共用相同的代码段;但进程之间也有个性,要不然怎么确定你是哪个进程呢?(后话)个性决定了,不同的进程在相同的河道上的执行流会不同。根据每个进程的个性判断来识别不同的进程,然后进行不同的执行过程。
回过头来看上面的代码就有了深刻的认识。fork 函数执行创建一个子进程后会返回所建立的子进程的 pid 值,当然如果是父进程运行到条件语句进行判断的话,fork 函数返回子进程的 pid;如果是子进程运行到条件语句进行判断的话,fork 函数会返回0,因为子进程下面没有子进程啊。所以根据不同情况进行了不同的执行流操作。
2. 进程创建的一个过程
上面的代码是从用户态的角度来看待一个进程是如何创建的,但是 fork 函数底下是如何创建的?一个进程创建完毕,然后执行的标志是什么?或者说,从哪里开始才算创建完毕,从哪条语句开始执行的呢?为什么从这里开始执行,会顺利地被执行下去呢?这一系列的问题困扰着我们。
我们寻求的是一个点的标识性意义(一个点的突破),但面对的却是一个创建的过程。进程如何被创建?从宏观的角度来看,