进程控制(fork exec wait)
几个函数
fork函数
返回值
子进程pid(父进程返回)
0 子进程
-1 错误
fork()
if()
elseif()
else
printf(); // 执行两次
getpid()
getppid()
创建n个进程?创建n个进程?
- 错误示例
for()
{
fork()
}
- 正确做法
int i;
for(i=0; i<2; i++)
{
pid_t pid = fork();
if(pid > 0)
{
printf("i= %d,parent pid=:%d, ppid=%d\n",i, getpid(),getppid());
}
else if(pid == 0)
{
//sleep(1);
//printf("i= %d,child, pid= %d, ppid=%d\n",i, getpid(), getppid());
break;
}
else
{
perror("fork");
}
//sleep(5);
}
//sleep(3);
printf("forked, i=%d\n", i);
执行结果
几个子进程运行没有固定顺序
一个子进程比一个子进程多延时一会儿,这样执行顺序就有序了
进程共享什么
既然子进程复制了父进程0-3g用户空间,以及父进程的pcb,父子进程两者内容几乎相同,没必要在物理内存中存在相同一份;
父子进程遵循 读时共享写时复制 原则
读时共享写时复制原则,父子进程都写var了,故输出var值不同;
如子进程只是读var,则var值为初始值100;
共享内容如下:
gdb调试
默认调试父进程
set follow-fork-mode child
set follow-fork-mode parent
**注意要在fork函数调用之前设置**
exec函数族
fork创建子进程后,父子进程既可以执行不同的代码,又可以执行相同的代码;
子进程往往调用exec函数来执行另一个程序;
子进程还是那个子进程,只是干的事情变了;pid没变
调用exec后不会返回到此函数调用出;
下图是子进程执行exec后子进程空间内容为a.out
既然称之为族,故有哪些函数呢?
着重理解下面两个函数:
注意:两个函数第一个参数
execl函数
想执行自己编写的程序怎么办(不是说不能调用系统命令)?调用execl函数啊
如果a.out有参数的话,在NULL前面加上参数;
execlp函数
后面的p字母代表含义:借助PATH环境变量;故该函数通常调用系统函数,如ls;
注意exec正常执行不会有返回值;注意形参第二个参数;
好比,bash上执行./a.out语句,创建子进程执行a.out
execvp函数
exec族函数一般规律:
返回值问题;
后缀问题l v p e;
几个函数之间的关系;
回收子进程
孤儿进程概念
略
验证概念,让子进程循环打印父进程pid,父进程等待几秒后推出;父进程推出前、后,子进程打印父进程pid不同;
ps ajx
这时ctrl c不能停止停止程序的运行,得用kill;原因:按下ctrl c发送给的是shell了,不是给此程序了(此程序成了后台程序了);
僵尸进程概念
子进程都会经历僵尸进程,父进程不可能马上回收,只有通知父进程后才会回收,通知之前就是僵尸进程;
验证概念
正好和孤儿进程相反,这次让父进程一直循环打印,让子进程过一会后推出,因父进程还在,子进程不会被孤儿院收养;
wait函数族
一个wait类函数调用,只能回收一个子进程;
wait函数
父进程调用wait函数可以回收子进程终止信息;
参数是传出参数(传出参数这个名字第一次听说,真好,顾名思义)
子进程的退出状态,需要借助宏函数
正常终止,return 73;
异常终止(都是信号终止的)
(kill -9 子进程pid)
示例代码如下
如果不关心子进程终止原因,形参为NULL即可;
waitpid函数
学习地址
可以指定回收哪个子进程;
可以不阻塞;
正确示例代码
错误代码
错误原因:子进程空间、父进程空间属于两个空间
想回收多个子进程怎么办?循环回收
两个函数什么时候等价