Linux进程-----父进程与子进程(详细篇)

接下来一个脱口而出的疑问是:好不容易生了个孩子,但是干的事情跟父进程是一样的, 那我们要这个孩子有何用呢?答案是:上述代码确实没有什么实际意义,事实上我们一般会 让孩子去执行一个预先准备好的 ELF 文件或者脚本,用以覆盖从父进程复制过来的代码, 先来介绍这个加载 ELF 文件或者脚本的接口函数:

功能

在进程中加载新的程序文件或者脚本,覆盖原有代码,重新运行

头文件

#include

原型

int execl(const char *path, const char *arg, ...);

int execv(const char *path, char *const argv[ ]);

int execle(const char *path, const char *arg, ..., char * const envp[ ]);

int execlp(const char *file, const char *arg, ...);

int execvp(const char *file, char *const argv[ ]);

int execvpe(const char *file, char *const argv[ ],char *const envp[ ]);

参数

path

即将被加载执行的 ELF 文件或脚本的路径

file

即将被加载执行的 ELF 文件或脚本的名字

arg

以列表方式罗列的 ELF 文件或脚本的参数

argv

以数组方式组织的 ELF 文件或脚本的参数

envp

用户自定义的环境变量数组

返回值

成功

不返回

失败

- 1

备注

1,函数名带字母 l 意味着其参数以列表 (list) 的方式提供。

2,函数名带字母 v 意味着其参数以矢量 (vector ) 数组的方式提供。

3,函数名带字母 p 意味着会利用环境变量 PATH 来找寻指定的执行文件。

4,函数名带字母 e 意味着用户提供自定义的环境变量。

表 函数族 exec( )的接口规范

使用exec函数注意事项

1,被加载的文件的参数列表必须以自身名字为开始,以 NULL 为结尾。比如要加载执 行当前目录下的一个叫做 a.out 的文件,需要一个参数”abcd”,那么正确的调用应该是:

execl(“ ./a.out”, “a.out”, “abcd”, NULL);

或者:

const char *argv[3] = {“a.out”, “abcd”, NULL};

execv(“ ./a.out”, argv);

2,exec 函数簇成功执行后,原有的程序代码都将被指定的文件或脚本覆盖,因此这些 函数一旦成功后面的代码是无法执行的,他们也是无法返回的。

示列代码如下:

#include

#include

#include

#include

#include

int main()

{

printf("hello\n");

pid_t pid = fork();

if(pid == 0)

{

execl("./son","./son","1.txt","2.txt","3.txt",NULL);//函数名带l 参数以列表的方式提供

//定义参数数组

// char *arg[] = {"./a.out","1.txt","2.txt","3.txt",NULL};

// execv("./a.out",arg);//函数名带v,将参数列表以数组的方式传入

//execl("/bin/ls","ls",NULL);//execl也可以直接使用shell命令替换子进程的代码,但是需要指定shell命令的路径

//execlp("ls","ls",NULL);//函数名带p,自动寻找环境变量,不需要指定路径

printf("[我是son]world,[自己的pid]%d,[父进程的pid]%d\n",getpid(),getppid());

//getpid(),getppid()

//给出一个退出值

exit(99);//exit可以自己指定退出值

}

if(pid > 0)

{

//wait(),等待子进程

int status;

wait(&status);

printf("[我嫩爹]world,[自己的pid]%d,[父进程的pid]%d\n",getpid(),getppid());//

printf("[退出状态值]%d\n",WEXITSTATUS(status));

//status是一个4个字节的状态值,其中最后一个字节才是退出值,用宏WEXITSTATUS()可以直接打印退出值

}

return 0;

}

上述代码注释部分解释了exec的多种用法!

上述程序中使用wait函数如下

功能

等待子进程

头文件

#include

原型

pid_t wait(int *stat_loc);

pid_t waitpid(pid_t pid, int *stat_loc, int options);

参数

pid

小于-1 :等待组 ID 的绝对值为 pid 的进程组中的任一子进程

-1:等待任一子进程

0:等待调用者所在进程组中的任一子进程

大于 0 :等待进程组 ID 为 pid 的子进程

stat_loc

子进程退出状态

option

WCONTINUED:报告任一从暂停态出来且从未报告过的子进程的状态

WNOHANG:非阻塞等待

WUNTRACED:报告任一当前处于暂停态且从未报告过的子进程的状态

返回值

wait( )

成功:退出的子进程 PID

失败:- 1

waitpid( )

成功:状态发生改变的子进程 PID (如果 WNOHANG 被设置,且由 pid 指 定的进程存在但状态尚未发生改变,则返回0) 。

失败:- 1

备注

如果不需要获取子进程的退出状态,stat_loc 可以设置为 NULL

表 5-4 函数 wait()和 waitpid()的接口规范

注意,所谓的退出状态不是退出值,退出状态包括了退出值。如果使用以上两个函数成 功获取了子进程的退出状态,则可以使用以下宏来进一步解析:

含义

WIFEXITED(status)

如果子进程正常退出,则该宏为真。

WEXITSTATUS(status)

如果子进程正常退出,则该宏将获取子进程的退出值。

WIFSIGNALED(status)

如果子进程被信号杀死,则该宏为真。

WTERMSIG(status)

如果子进程被信号杀死,则该宏将获取导致他死亡的信号值。

② WCOREDUMP(status)

如果子进程被信号杀死且生成核心转储文件 (core dump) , 则该宏为真。

WIFSTOPPED(status)

如果子进程的被信号暂停,且 option 中 WUNTRACED 已经被 设置时,则该宏为真。

WSTOPSIG(status)

如果 WIFSTOPPED(status)为真,则该宏将获取导致子进程暂 停的信号值。

WIFCONTINUED(status)

如果子进程被信号 SIGCONT 重新置为就绪态,该宏为真。

表 5-5 处理子进程退出状态值的宏

①正常退出指的是调用 exit( )/_exit( ),或者在主函数中调用 return,或者在最后一个 线程调用 pthread_exit( )。

②由于没有在 POSXI.1-2001 标准中定义,这个选项在某些 Unix 系统中无效,比如 AIX, 或者 sunOS 中。

集成运算放大器具有哪些特点及主要起到什么作用?
游聚游戏平台下载的游戏在哪-游聚游戏平台下载的游戏位置介绍