进程控制二之waitpid,进程程序替换,bash的简单模拟实现

发布于:2022-12-04 ⋅ 阅读:(503) ⋅ 点赞:(0)

文章目录

1.1进程等待的必要性:

1.2、wait 函数(阻塞)

1.3、waitpid函数(可以有非阻塞的功能)

二、进程程序替换

2.0、为什么要进行程序替换

2.1、原理

2.2、exec函数簇

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

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

代码实现:

3、int”execle(const,char,*path,, const. char.*arg, ,... ,char。*const. envp[]);

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

 总结exec函数簇

三、bash的简单模拟,让子进程进行程序替换

3.1原理图

3.2实现

myreplace:

exec_fork_wait:

这里要注意,能执行程序替换的函数有很多种,为什么非要用execl呢?,用execlp不是更好吗?(不用加地址)

 执行./exec_fork_wait命令

总结


1.1进程等待的必要性:

解决僵尸进程有三种方法:

1、kill父进程 

                让子进程变成孤儿进程,被1号程序领养,就解决了问题。

但是这个方法有点

2、重启

              会重启所以程序,代价会很大

3、进程等待

            其中进程等待是最优的解法了,其他两种的代价有点大

1.2、wait 函数(阻塞)

上一个博客有详细解释。

1.3、waitpid函数(可以有非阻塞的功能)

 可以看到waitpid函数一共有三个参数。

其有阻塞和非阻塞两种属性:比较重要的是非阻塞属性

接下来就让我们来验证他的非阻塞属性吧:

 我们将其的参数设置为WNOHANG,这时候就是非阻塞功能了,

分析可知,假若非阻塞,那么子进程会变成僵尸进程。

结果:

 子进程确实变为了僵尸进程,结论成立

那么在非阻塞的前提下,给waitpid函数加上循环的话:

就会一直去进行调用,也可强行实现阻塞功能

小问题

可以发现,在调用wait和waitpid函数(阻塞情况下)的时候,当子进程还没有退出的时候,父进程好像就只干着这一件事情了,一直在等待着,那么在实际的业务进行的时候,如果是这样的那肯定是不行的,父进程肯定还要做其他更多的事情才行。

怎样解决呢?后续因该会学习,现在先在这里埋个点

二、进程程序替换

2.0、为什么要进行程序替换

因为父进程创建出来的子进程和父进程拥有相同的代码段,如果不进行操作,子进程的功能(代码)不就和父进程一样了吗

当我们想要让子进程执行不同的程序的时候,就需要让子进程调用程序替换的接口,从而让子进程执行不一样的代码

2.1、原理

替换进程都代码段和数据段,更新堆栈

2.2、exec函数簇

 (其实这些函数没必要每个都那么认真了解,会用顺手的就行)

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


参数:
        path:带路径的可执行程序(需要路径)
        arg:给程序传递命令参数的

                  1.第一个命令行参数是程序本身

                  2.最后一个参数以NULL函数结尾(这不就和环境变量一样一样了嘛
        如果需要传递多个参数,则用“,”进行间隔,末尾以NULL结尾

       ***最后的“ 。。。”表示的是参数列表

         返回值:

成功:没有返回值,这些函数如果调用成功则加载新的程序从启动代码开始执行,不再返回。

          可以这么理解:都成功了,那不就直接进行被替换掉程序了,咋可能还有有返回值。

失败:返回-1

~代码实现

替换成     ls

将代码运行起来

 可以看到确实是替换成功了。

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

可以不带路径是因为以“p”结尾了,会自动使用环境变量PATH去搜索。

代码实现:

可以看到没有带路径也照样实现了ls的功能

 

3、int”execle(const,char,*path,, const. char.*arg, ,... ,char。*const. envp[]);

 

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

 

 

 总结exec函数簇

  • 三、bash的简单模拟,让子进程进行程序替换

  • 3.1原理图

  • 3.2实现

首先肯定得分别创建两个文件:exec_fork_wait和myreplace

让exec_fork_wait创造出来的子进程去替换成为myreolace再去实现功能

myreplace:

 如果执行的话就会输出传入的指令    如  -a  -b  -c

exec_fork_wait:

这里要注意,能执行程序替换的函数有很多种,为什么非要用execl呢?,用execlp不是更好吗?(不用加地址

因为我们要替换的进程myreplace是自己写的在bash中是没有路径的,不能利用path去找到他的路径,

我们可以通过pwd命令去查找到他的路径

 

 然后在写个makefile文件

这时候要生成两个文件,可以在前面加一个all:【文件一】【文件二】

然后就能一次性生成两个文件

否则make永远只为生成第一个文件而服务,第二个一旦删除就不会再生成了

 

 执行./exec_fork_wait命令

可以看到执行成功(nice


总结

进程控制二