进程控制(fork exec wait)

学习地址

几个函数

fork函数

返回值
子进程pid(父进程返回)
0 子进程
-1 错误

image

fork()
if()
elseif()
else

printf();    // 执行两次
getpid()
getppid()

创建n个进程?创建n个进程?

学习地址

  • 错误示例
    for()
    {
    fork()
    }

image

image

  • 正确做法
	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);

执行结果
image

image
几个子进程运行没有固定顺序

image
一个子进程比一个子进程多延时一会儿,这样执行顺序就有序了

进程共享什么

学习地址

image

既然子进程复制了父进程0-3g用户空间,以及父进程的pcb,父子进程两者内容几乎相同,没必要在物理内存中存在相同一份;
父子进程遵循 读时共享写时复制 原则

image
读时共享写时复制原则,父子进程都写var了,故输出var值不同;
如子进程只是读var,则var值为初始值100;

共享内容如下:
image

gdb调试

默认调试父进程

set follow-fork-mode child
set follow-fork-mode parent
**注意要在fork函数调用之前设置**

学习地址

exec函数族

fork创建子进程后,父子进程既可以执行不同的代码,又可以执行相同的代码;
子进程往往调用exec函数来执行另一个程序;
子进程还是那个子进程,只是干的事情变了;pid没变
调用exec后不会返回到此函数调用出;

下图是子进程执行exec后子进程空间内容为a.out
image

既然称之为族,故有哪些函数呢?
image

着重理解下面两个函数:

image
注意:两个函数第一个参数

execl函数

想执行自己编写的程序怎么办(不是说不能调用系统命令)?调用execl函数啊

image
如果a.out有参数的话,在NULL前面加上参数;

execlp函数

后面的p字母代表含义:借助PATH环境变量;故该函数通常调用系统函数,如ls;

image
注意exec正常执行不会有返回值;注意形参第二个参数;

好比,bash上执行./a.out语句,创建子进程执行a.out

execvp函数

exec族函数一般规律:
返回值问题;
后缀问题l v p e;
几个函数之间的关系;

image


学习地址

回收子进程

孤儿进程概念

验证概念,让子进程循环打印父进程pid,父进程等待几秒后推出;父进程推出前、后,子进程打印父进程pid不同;
ps ajx

这时ctrl c不能停止停止程序的运行,得用kill;原因:按下ctrl c发送给的是shell了,不是给此程序了(此程序成了后台程序了);

僵尸进程概念

子进程都会经历僵尸进程,父进程不可能马上回收,只有通知父进程后才会回收,通知之前就是僵尸进程;

验证概念
正好和孤儿进程相反,这次让父进程一直循环打印,让子进程过一会后推出,因父进程还在,子进程不会被孤儿院收养;

image

wait函数族

一个wait类函数调用,只能回收一个子进程;

wait函数

父进程调用wait函数可以回收子进程终止信息;
image

image
参数是传出参数(传出参数这个名字第一次听说,真好,顾名思义)

子进程的退出状态,需要借助宏函数
正常终止,return 73;
异常终止(都是信号终止的)
(kill -9 子进程pid)

示例代码如下
image

如果不关心子进程终止原因,形参为NULL即可;

waitpid函数

学习地址
可以指定回收哪个子进程;
可以不阻塞;

正确示例代码
image

错误代码
image

错误原因:子进程空间、父进程空间属于两个空间

想回收多个子进程怎么办?循环回收
image

两个函数什么时候等价
image


posted @ 2023-01-22 12:58  我爱茜茜公主  阅读(66)  评论(0)    收藏  举报