进程的函数

创建进程:fork

fork()函数用于从已存在的一个进程中创建一个新的进程,新进程称为子进程,而原进程称为父进程。

要点 说明
所需头文件 #include <sys/types.h>/提供类型pid_t的定义/
#include <unistd.h>
函数原型 pid_t fork(void)
函数返回值 0:子进程
子进程的pid:父进程
-1:出错

fork与vfork的区别

执行进程:exec簇函数

如果一个进程想执行另一个程序,那么它就可以调用 fork() 函数新建一个进程,然后调用 exec 函数族中的任意一个函数,这样看起来就像通过执行应用程序而产生了一个新进程

要点 说明
所需头文件 #include <unistd.h>
函数原型 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 execve(const char * file, char * const argv[],char * const envp[]);
返回值 -1:出错

从上面的表格中各个函数参数是不一样的:

l代表的是list:命令行参数列表
p代表的是path:搜索file时的使用的path变量
v代表的是vector:使用命令行参数数组
e代表的是environment:使用环境变量数组
这些参数必须以NULL结束
事实上,这6个函数中真正的系统调用只有execve(),其他5个都是库函数,它们最终都会调用execve()这个系统调用。在使用exec函数族时,一定要加上错误判断语句。exec 很容易执行失败,其中最常见的原因有:

①  找不到文件或路径,此时 errno 被设置为 ENOENT。

②  数组argv 和envp  忘记用NULL结束,此时,errno被设置为 EFAUL。

③  没有对应可执行文件的运行权限,此时 errno 被设置为EACCES。

终止进程:exit()和_exit()函数

_exit()函数的作用是:直接使进程停止运行,清除其使用的内存空间,并清除其在内核中的各种数据结构;

exit()函数和_exit()函数的最大区别就在于exit()函数在终止当前进程之前要检查该进程打开过哪些文件,把文件缓冲区中的内容写回文件,也就是图1中的“清理I/O缓冲”一项。
exit流程图

在Linux的标准函数库中,有一种被称作“缓冲I/O(buffered I/O)”的操作,其特征就是对应每一个打开的文件,在内存中都有一片缓冲区。

每次读文件时,会连续读出若干条记录,这样在下次读文件时就可以直接从内存的缓冲区中读取;同样,每次写文件时,也仅仅是写入内存中的缓冲区,等满足了一定的条件(如达到一定数量或遇到特定字符等,最典型的就是咱们的vim中使用的:w命令),再将缓冲区中的内容一次性写入文件。

这种技术大大增加了文件读写的速度,但也给咱们的编程带来了一些麻烦。比如有些数据你认为已经被写入到文件中,实际上因为没有满足特定的条件,它们还只是被保存在缓冲区内,这时用_exit()函数直接将进程关闭掉,缓冲区中的数据就会丢失。因此,若想保证数据的完整性,最好使用exit()函数。

要点 说明
所需头文件 _exit():#include <unistd.h>
exit():#include <stdlib.h>
函数原型 _exit():void _exit(int status)
exit(): void exit(int status)
参数说明 status是一个整型参数,可以利用这个参数传递进程结束时的状态:
①0:进程正常结束。
②  非0:表示进程出现错误。
在实际编程中,使用wait()来获取子进程的返回值。

wait()和waitpid()函数

1.wait()函数用于使父进程(也就是调用wait()的进程)阻塞,直到一个子进程结束或者该进程接收到了一个指定的信号为止。如果该父进程没有子进程或者它的子进程已经结束,则wait()就会立即返回。
2.waitpid()的作用和wait()一样,但它并不一定要等待第一个终止的子进程,它还有若干选项,如可提供一个非阻塞版本的wait()功能,也能支持作业控制。实际上,wait()函数只是waitpid()函数的一个特例,在Linux内部实现wait()函数时直接调用的就是waitpid()函数。

wait()函数语法要点

要点 说明
所需头文件 #include <sys/types.h>
#include <sys/wait.h>
函数原型 pid_t wait(int *status)
函数传入 这里的status是一个整型指针,是该子进程退出时的状态。若status不为空,则通过它可以获得子进程的结束状态。另外,子进程的结束状态可由Linux中一些特定的宏来测定
函数返回值 成功:已结束运行的子进程的进程号
失败:-1

waitpid()函数语法要点

要点 说明
所需头文 #include <sys/types.h>
#include <sys/wait.h>
函数原型 pid_t waitpid(pid_t pid, int *status, int options)
函数参数pid pid > 0:只等待进程ID等于pid的子进程,不管是否已经有其他子进程运行结束退出,只要指定的子进程还没有结束,waitpid()就会一直等下去
pid = -1:等待任何一个子进程退出,此时和wait()作用一样
pid = 0:等待其组ID等于调用进程的组ID的任一子进程
pid < -1:等待其组ID等于pid的绝对值的任一子进程
函数参数status 同wait()
函数参数options WNOHANG:若由pid指定的子进程没有结束,则waitpid()不阻塞而立即返回,此时返回值为0
WUNTRACED:为了实现某种操作,由pid指定的任一子进程已被暂停,且其状态自暂停以来还未报告过,则返回其状态

0:同wait(),阻塞父进程,等待子进程退出
函数返回 正常:已经结束运行的子进程的进程号
使用选项WNOHANG且没有子进程退出:0
调用出错:-1

参考资料:
Linux多任务编程(四)---exit()函数及其基础实验

posted @ 2019-07-23 11:06  独孤剑—宇枫  阅读(512)  评论(0编辑  收藏  举报