Linux进程原语及功能:
- fork:创建一个新的子进程;
- exec族(execl、execlp、execle、execv、execvp、execve):
执行一个文件;
用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数以执行另一个程序。
当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。
调用exec并不创建新进程,所以调用exec前后该进程的pid并未改变。
- wait族(wait、wait3、wait4、waitpid):等待子进程终结,以使父进程回收其子进程.
进程从创建到最终被回收过程的简易图示:
父进程调用fork系统调用创建子进程 ;
-> 子进程调用exec系统调用来执行其他代码 ;
-> 子进程执行完代码后退出,等待父进程回收,此时的子进程处于僵死状态(使用ps命令依然可以查看得到,但是已经不能运行);
-> 父进程调用wait函数回收子进程,但是如果父进程在子进程结束前就结束了,则子进程在结束运行后将成为孤儿进程,并最终被init进程认领并回收。
代码示例 process.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
pid_t pid;
pid = fork();
if (pid > 0) { /* in parent */
printf("I am parent\n");
exit(0);
}
else if (pid == 0) { /* in child */
printf("I am child\n");
execl("/home/slot/print_args", "print_args", "haha", NULL);
}
else {
perror("fork error");
exit(-1);
}
printf("Hello world\n");
return 0;
}
其中 print_args.c
的功能是打印命令行参数,代码如下:
#include <stdio.h>
int main(int argc, char const *argv[])
{
int i = 0;
while (i < argc)
printf("%s\n", argv[i++]);
/* 此处故意将返回值设置为233以便于观察区别 */
return 233;
}
执行结果
$ gcc print_args.c -o print_args
$ gcc process.c -o process
$
$ ./process
I am parent
I am child
print_args
haha