说在前面
- 环境: WSL
- 参考: UNIX网络编程、linux manual page-fork、linux manual page-exec
数据类型说明
数据类型 | 说明 | 头文件 |
pid_t | 一般为int,见这里 | <unistd.h> |
fork
fork(包括各种变体)是Unix中派生新进程的唯一方法。
-
定义
返回值:#include <unistd.h> pid_t fork(void);
- 调用该函数一次,返回两次
- 在父进程(调用fork的进程)中,返回值为子进程(新派生进程)的进程ID;在子进程中,返回值为0。返回值本身可以告知当前进程是子进程还是父进程。
- fork在子进程中返回0而不是父进程ID(即父进程返回0,子进程返回父进程ID)的原因:任何子进程只有一个父进程,而且子进程可以通过getppid函数获取父进程ID。父进程可以拥有许多子进程,但是却无法获取各个子进程ID。
-
其他说明
父进程调用fork之前打开的所有描述符(fd)在fork之后由子进程共享。网络服务器利用了这个特性:父进程调用accept后调用fork,所接受的已连接套接字随后就在父进程与子进程之间共享;通常,子进程继续读写该已连接套接字,父进程则关闭该已连接套接字(套接字描述符引用计数-1) -
典型用法
- 一个进程创建一个自身的副本。每个副本都可以在另一个副本执行其他任务时处理各自的任务。这是网络服务器的典型用法。
- 一个进程想要执行另一个程序。首先调用fork创建一个自身的副本,然后其中一个副本(通常为子进程)调用exec把自身替换为新的程序。这时诸如shell(例如运行./client.out)之类程序的典型用法。
exec
放在硬盘上的可执行程序文件能被Unix执行的唯一方法:由一个现有进程调用六个exec函数中的某一个。 exec将当前进程映像替换为新的程序文件,而且该新程序通常从main函数开始执行,该进程ID不变。(调用exec的进程被称为调用进程;新执行的程序被称为新程序。)
-
定义
#include <unistd.h> extern char **environ; int execl(const char *pathname, const char *arg, ... /* (char *) NULL */); int execv(const char *pathname, char *const argv[]); int execle(const char *pathname, const char *arg, ... /*, (char *) NULL, char * const envp[] */); int execvpe(const char *file, char *const argv[], char *const envp[]); int execlp(const char *file, const char *arg, ... /* (char *) NULL */); int execvp(const char *file, char *const argv[]); // 注:在linux manual page中,上述六个函数被放在同一个条目中进行说明; // 它们在内核中调用execve // (The functions described in this manual page are front-ends for execve(2).) int execve(const char *pathname, char *const argv[], char *const envp[]);
参数说明:
- 这些函数之间的区别在于:
- 待执行的程序文件是由文件名(file)还是路径名(pathname)指定;
- 新程序的参数是一一列出还是由一个指针数组来引用;
- 把调用进程的环境传递给新进程还是给新程序指定环境。
- 对于函数名中的l、p、e、v
说明 l argument list,使用参数列表 p 使用环境变量PATH+文件名,若文件名中有斜杠‘/’,那么不添加PATH e environment,使用envp指定新的环境 v 参数使用指针数组(*const argv[],必须含有表示结尾的空指针)指定
返回值:
- 这些函数仅在出错时返回给调用进程;否则,控制(?)将被传递给新程序的起点,通常是main函数。
-
其他说明
- 上面三个函数(函数名均包含
l
l
l)把新程序的每个参数字符串均指定为exec的一个独立参数,并以一个空指针(即0)结束可变数量的参数列表。
- 下面四个函数(函数名均包含v)都有一个作为参数的argv数组,其中含有指向新程序各个参数字符串的所有指针。该数组必须包含一个表示结尾的空指针。
- 左列两个函数(函数名均包含p)指定一个file参数。exec将环境变量PATH把文件名转换为路径名。但是一旦file中含有斜杠‘/’,就不再使用PATH。而右边五个函数(函数名均不含p)则使用pathname作为参数。
- 左两列四个函数(函数名均不含e)不显示指定一个环境指针。它们使用外部环境变量environ的当前值(即fork后的进程的environ)来构造一个传递给新程序的环境列表。最右三个函数(函数名均包含v)显示指定环境列表,其中envp必须以空指针结束。
进程在调用exec之前打开的描述符通常跨exec继续保持打开。但是该默认行为可以通过fcntl设置FD_CLOEXEC。
- 上面三个函数(函数名均包含
l
l
l)把新程序的每个参数字符串均指定为exec的一个独立参数,并以一个空指针(即0)结束可变数量的参数列表。