进程(下):进程控制、终止、等待、替换

 --------------“美好的事总会如约而至”


(1)进程控制:

① 如何理解fork有两个返回值?

父:子  ==1:N;  父进程不需要表示,子进程需要标识。

多个子进程执行不同任务,父进程需要通过id 区分子进程。

 因此调用fork时候,内核会做:

1.分配新的内存块 和 内核数据 给子进程。

2.将父进程的代码 数据拷贝给子进程。

3.并把子进程添加到 系统进程调用列表当中。

4.fork返回,并执行调度。

②写时拷贝:

通常情况下,父子代码共享,数据也是(物理内存是一样的)。但是当一方试图写入时,为了保证各个进程的独立性,此时会发生写时拷贝

 

 为什么要写时拷贝?

①保证进程的独立性。

为什么不创建时就分开?

因为子进程不一定需要父进程的所有数据。

子进程不一定立马使用(按需分配);因此进行延时分配,本质是高效使用内存空间

fork调用失败原因?

1.系统中太多程序

2.用户进程超过限制(OS进行的限制)。


(2)进程终止:

①进程退出码:

main函数返回值给了谁?操作系统

main函数也是函数,所以一定会被调用。返回值会返回给操作系统。

为什么要有返回值? ------------运行加载,完成工作,需要知道完成度。

途径:

echo $?

 

退出码0 、!0:

#include<string.h>

strerror(size_t i); //错误码

 

 每种错误码,都有对应的错误含义。但这都是人为规定。

②进程退出: 

1.exit:进程终止;并释放缓冲区的数据

_exit:进程终止,不做其余工作

 

2.异常退出:此时退出码已经没有任何意义了

3.进程终止,操作系统会做什么?  一定要去管理!

释放内存 数据结构 调度队列移除。


(3)进程等待:父进程等待

①等待必要性:回收子进程、获取其退出信息。

②进程等待方法:

1.wait:等待接收子进程返回的pid

#include<sys/wait.h>

pid_t wait(int* status)

小结:父进程通过wait 读取子进程的信息,僵尸状态也就自动改变。 

在子进程运行期间(wait),父进程在做什么? 什么也没做------>     阻塞等待!!!

2.waitpid:指定等待进程

                    //记录子进程的状态
waitpid(pid_id pid,int* status,int options)
  

//有列表的监控脚本
while :; do ps ajx|head -1 && ps ajx | grep myproc |grep -v 'grep';echo "#########################" ; sleep 1 ;done;

等待成功!=子进程运行成功。

status:退出结果 ---------->查看子进程 运行状态

 注:进程异常终止,本质上是因为收到信号。其退出码也没有任何价值。

此进程发生异常,收到信号,此时退出码也没有任何意义。 

实际中一般用 宏检测:

WIFEXITED(status)    //进程信号 0 与 !0


WEXITSTATUS(status)  //进程退出码

多进程创建与等待:

 ​​​​​​​​

 


补充:阻塞与非阻塞

//若pid没有返回 也就是子进程没有执行结束,不再等待子进程 返回0 不予等待
// 若正常退出 则返回子进程pid

pid_t ret=waitpid(id,&status,WNOHANG);

 

 

所以对父进程而言,需要不断去等子进程执行完。

 

 


(4)进程替换:

子进程执行新的进程。

进程替换函数:

函数....
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 *path, char *const argv[], char *const envp[]);
数组+自定义路径

 

execl 其本质就是让程序加载到磁盘。

1.当前进程 再进行 程序替换,是否创建了新进程? 

这里根本没有 创建新进程。只是把磁盘代码进行替换了而已。  进程!=可执行程序。

2.被替换后,后续的代码,是否能被读到?

答案是不能。

3. 函数调用失败,程序不会受到影响。但调用成功则不会返回!

 

4.运行具有独立性父子之间不会因为程序替换函数而受到影响。


函数接口的理解: 

只需要理解 数组、列表 执行程序的参数的区别:

execv为例:

 

理解默认路径、自定义路径:

默认路径:

 

 自定义路径(execle):

 

打印出null;

 此时还不会打印出 这个未定义(MAVAL)的环境变量。

 

 


进程的相关内容也最后完结:希望对阅读的你有用。

祝你好运~

​​​​​​​

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值