进击吧,linux(十三) 多进程编程
0赞
Linux是一个可以执行多进程的操作系统,因此是可以在程序中,创建多进程。来完成不同的功能。多进程的编程,也是通过几个函数来学习的。
4.1.1 函数名
fork
4.1.2 函数原形
pid_t fork(void)
4.1.3 函数功能
创建子进程
4.1.4 所属头文件
<unistd.h>
4.1.5 返回值
成功:父进程返回0 ,子进程返回pid
失败:-1
4.1.6 参数说明
无
4.1.7 示例代码
使用fork创建子进程,通过判断pid,得知是父进程还是子进程运行,然后再执行自己的程序。
使用fork创建的父进程,父子进程执行的顺序是不确定的。
4.2.1 函数名
vfork
4.2.2 函数原形
pid_t vfork(void)
4.2.3 函数功能
创建子进程,并阻塞父进程
4.2.4 所属头文件
<sys/types.h> <unistd.h>
4.2.5 返回值
成功:父进程返回子进程的pid ,子进程返回0
失败:-1
4.2.6 参数说明
无
4.2.7 示例代码
使用vfork创建子进程,子进程执行一定在父进程前,因为创建子进程后,就将父进程给阻塞掉了。
4.3.1 函数名
wait
4.3.2 函数原形
pid_t wait(int *status)
4.3.3 函数功能
阻塞父进程,直到有一个子进程结束,父进程才执行
4.3.4 所属头文件
<sys/types.h> <sys/wait.h>
4.3.5 返回值
成功:返回结束的子进程的pid
失败:-1
4.3.6 参数说明
status: 子进程结束的状态保存
4.3.7 示例代码
使用wait后,父进程就被阻塞掉了,要等待一个子进程结束。这里只有一个子进程,等待5s子进程执行完毕后,父进程就可以执行了。
4.4.1 函数名
execl
4.4.2 函数原形
Int execl(const char *path, const char *arg,….)
4.4.3 函数功能
执行path指定的程序
4.4.4 所属头文件
<unistd.h>
4.4.5 返回值
成功:没有返回值
失败:-1
4.4.6 参数说明
path:程序名(带路径)
arg: 命令的参数
。。。: 可选参数,看执行的命令需要的参数决定
4.4.7 示例代码
使用execl执行指定目录下的程序,就不会再返回了,所以就看不到打印children了。
对于系统自带的函数,使用有点不一样,按以下使用。
execl("/bin/ls","ls","..",NULL);
对于使用fork和vfork,创建出来的子进程执行的程序是父进程fork或vfork后的程序。
通过上面这个图,就可以知道子进程执行的代码是什么了。也就是父进程程序fork或者vfork之后的代码。
fork和vfork都可以创建子进程,但是也有一些不同:
1、 fork:子进程拥有独立的数据段,堆栈
vfork:子进程与父进程共享数据段,堆栈
2、 fork:父、子进程的执行次序不确定
vfork:子进程先运行,子进程运行结束后,才运行父进程
怎么理解第一个不同了,写一个代码测试一下就知道了
先定义一个变量count,然后分别使用fork和vfork函数创建进程执行看。
对于fork,执行效果
输出count两次,结果都是1。一个父进程打印的,一个是子进程打印的,但是要注意,不能确定执行谁先谁后。由于fork有自己的数据段和堆栈,所以父进程和子进程的count变量相互不影响。
对于vfork,执行效果
结果和fork的不一样了,也是打印两次,第一个是子进程打印的,第二个是父进程打印的,注意打印的顺序是确定的,因为vfork创建子进程后,是子进程先运行,运行结束后,父进程才运行,和fork就不一样了。
其次,打印的值也不一样。因为对于vfork创建的子进程,子进程与父进程共享数据段,堆栈,所以对于count变量,父子进程使用的都是同一个,所以结果就是如上了。