在Windows世界,创建进程最常用的WIN 32 API 是 CreateProcess以及相关函数。这个函数需要一堆参数(Windows API 的特点),不过很多参数可以简单的用NULL, TRUE OR FALSE来表示。另外,你直接告诉它要执行的是哪个文件。
到了Linux世界,我模糊的知道fork是用来创建一个新进程的。但是当我看fork的函数说明的时候,呆住了。因为fork不需要任何参数。习惯了 CreateProcess 的10来个参数,突然换成一个不要任何参数的函数,感觉很奇妙。一方面觉得似乎事情简单了很多,不用去把10来个参数的每个意思都搞明白。另外一方面又很疑惑,我怎么告诉它我要执行某个文件呢?
后来才知道,Linux中的进程的含义和Windows中是不一样的。Linux中的进程本身是可以执行的。而Windows中,进程只是表示一个资源的拥有体,是不能执行的。要执行的话,一定需要一个线程。这也部分解释了为什么CreateProcess中为啥一定要传入要执行的文件的名字。
而fork的含义是把进程本身CLONE一个新的出来。也就是说,FORK之后,父进程和子进程都执行同样的一段代码。如果想区分的话,可以根据FORK的返回值来区分。引用一段fork的说明:
On success, the PID of the child process is returned in the parent's thread of execution, and a 0 is returned in the child's thread of execution.
同时在Linux程序中,常见的写法如下: int pid;
pid = fork();
switch (pid)
{
case 0: //I am the child
;
case -1: //failed.
;
default: //I am the parent
}
为什么要这样设计呢?因为Linux的设计目标之一就是应用于服务器。这种情况下,一个SERVICE可能会启动很多进程(线程)来服务不同的CLIENT. 所以FORK设计成快速复制父进程。子进程直接使用父亲的地址空间,只有子进程加载一个新的可执行文件的时候才创建自己的地址空间。
这样节省了创建地址空间这个庞大的开销,使得Linux的进程创建十分快。不过实际上,这里的进程相对于Windows中的线程,所以同Windows中的线程创建相比,二者的开销应该差不多。
那么如何才能让新的进程加载一个可执行文件呢,这时就要用execv以及相关函数了。所以Linux中,代替CreateProcess()的函数是fork+execv