fork函数和exec函数族

总结关于 fork 函数族和 exec 函数族的知识。

前言

在 Linux 中,fork() 函数用来创建子进程,exec() 函数用来替换当前进程的执行文件。

当我们创建了一个进程之后,通常将子进程替换成新的进程映象,这可以用exec系列的函数来进行。当然,exec系列的函数也可以将当前进程替换掉。

exec只是用磁盘上的一个新程序替换了当前进程的正文段, 数据段, 堆段和栈段.并没有创建新进程,所以进程的ID是不变的。

而对于 fork 函数来说,其用来创建一个子进程,这个子进程继承父进程的一切关于程序方面的资源(而非属性上面的)。所以这两类函数实际上是可以共同合作使用的。

fork()函数

前面我们提到了这个函数的作用,现在我们来详细说明这个函数和exec族函数的具体区别。

exec()函数族

exec替换进程印象

在进程的创建上,Unix采用了一个独特的方法,它将进程创建与加载一个新进程映象分离。这样的好处是有更多的余地对两种操作进行管理。

当我们创建了一个进程之后,通常将子进程替换成新的进程映象,这可以用exec系列的函数来进行。当然,exec系列的函数也可以将当前进程替换掉。

exec只是用磁盘上的一个新程序替换了当前进程的正文段, 数据段, 堆段和栈段.并没有创建新进程,所以进程的ID是不变的。

下面是这个家族中的成员函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
int execve(const char *filename, char *const argv[],    
char *const envp[]);

#include <unistd.h>
extern char **environ;
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg,
..., char * const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],
char *const envp[]);

这六个函数的命令其实是有规律可言的:

  1. execl,execlp,execle(都带“l”, 代表list)的参数个数是可变的,参数以必须一个空指针结束。

  2. execv和execvp的第二个参数是一个字符串数组(“v”代表“vector”,字符串数组必须以NULL结尾),新程序在启动时会把在argv数组中给定的参数传递到main。

  3. 名字最后一个字母是“p”的函数会搜索PATH环境变量去查找新程序的可执行文件。如果可执行文件不在PATH定义的路径上,就必须把包括子目录在内的绝对文件名做为一个参数传递给这些函数;

总结:l代表可变参数列表,与v互斥;v表示该函数取一个argv[]矢量;p代表在path环境变量中搜索file文件;e表示该函数取envp[]数组,而不使用当前环境

下面是 fork()函数和exec()函数族共同使用的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int main (int argc, char *argv[])
{
int pid;
if((pdf =fork()) == 0)
execl("/bin/ls", "ls", "-l", NULL);//这里是使用可变参数的exec系列函数
else if (pid < 0)
printf("fork failed\n");
exit(1);
wait(NULL);

char *argv_execve[]={"/bin/data","+%F",NULL};
pid=fork();

if(pid==0)
{
if(execve("/bin/date",argv_execve,NULL)==-1)
ERR_EXIT("execve error");
}
wait(NULL);
return 0;
}

System()函数

这个函数和前面两个函数的区别在于,它会阻塞当前进程的执行,而去执行自己的进程。

返回值:

如果无法启动shell运行命令,system将返回127;出现不能执行system调用的其他错误时返回-1。如果system能够顺利执行,返回那个命令的退出码。
1
int system(const char *command);  

这个函数其实就是 fork() 和 exec() 两个函数的结合体,它会先 fork 出一个子进程,然后在子进程中执行命令,最后等待子进程结束,并返回子进程的退出码。


fork函数和exec函数族
https://ysc2.github.io/ysc2.github.io/2024/08/21/fork函数和exec函数族/
作者
Ysc
发布于
2024年8月21日
许可协议