自学内容网 自学内容网

进程的控制

 

目录

 

一、进程的创建

1.fork函数初识

2.fork函数返回值

3.写时拷贝

4.fork的常规用法 

5.fork调用失败的原因

二、进程终止 

1.进程退出场景

对于正常运行的这两种结果

 strerror

errno 

对于异常终止的情况

2.进程常见退出方法


一、进程的创建

1.fork函数初识

它从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。

#include <unistd.h>
pid_t fork(void);
返回值:自进程中返回0,父进程返回子进程id,出错返回-1

 进程调用fork,当控制转移到内核中的fork代码后,内核做:

1.分配新的内存块和内核数据结构给子进程
2.将父进程部分数据结构内容拷贝至子进程
3.添加子进程到系统进程列表当中
4.fork返回,开始调度器调度

当一个进程调用fork之后,就有两个二进制代码相同的进程。而且它们都运行到相同的地方。但每个进程都将可以通过if else分流执行各自的代码

在fork之前父进程独立执行,fork之后,父子两个执行流分别执行。注意,fork之后,谁先执行完全由调度器决定。

2.fork函数返回值

子进程返回0,
父进程返回的是子进程的pid 

3.写时拷贝

通常,父子代码共享,父子再不写入时,数据也是共享的,当任意一方试图写入,便以写时拷贝的方式拷贝一份副本。

在fork之后,页表中所有进程地址的标志位都变成只读,看后续谁先触发只读权限的错误就给谁进行写时拷贝,并且修改权限为可读可写

4.fork的常规用法 

1.一个父进程希望复制自己,使父子进程同时执行不同的代码段。
2.一个进程要执行一个不同的程序。例如子进程从fork返回后,调用exec函数。 

5.fork调用失败的原因

1.系统中有太多的进程
2.实际用户的进程数超过了限制 

二、进程终止 

1.进程退出场景


代码运行完毕,结果正确
代码运行完毕,结果不正确
代码异常终止

对于正常运行的这两种结果

我们这个main函数return的是进程的退出码,来表征进程的运行结果是否正确

一般而言谁会关心这个进程的运行情况呢?一般是父进程关心。因此进程的退出码可以被它的父进程拿到,可以通过 echo $? 查看最近一个进程的退出码

但是父进程为什么要关心呢?本质其实是用户在关心,用户在知道失败的原因之后,会根据失败的原因进行处理,实现交互

当代码运行结果正确时我们不作太多关注,当代码运行结果不正确时,我们想要知道为什么不正确

-->可以用return的不同的返回值数字来表征不同的原因---退出码

 strerror

可以通过错误码来打印错误原因 

每个数字对应一种错误描述,下面是部分的举例

 

例如在下面这个ls 指令产生的进程退出后会交给bash它的退出码

errno 

这是c语言给我们提供的一个全局变量 

 它会储存最近一次库函数调用失败时候的错误码,它会被覆盖

由此通过errno变量我们可以知道库函数调用失败的错误码,也可以通过strerror打印错误原因,还可以将错误码转化为进程的退出码

 

(但是在后续应用中我们多采取c与c++混编,所有一般不会采用c标准库给我们提供的错误码) 

对于异常终止的情况

 本质可能是代码并没有跑完

因此进程的退出码无意义,我们不关心退出码了

所有我们先看进程是不是正常终止,然后再看代码运行结果是否正确,即关系退出码

当出现异常这些异常会被转化为硬件信息,被操作系统识别从而向目标进程发信号,让我们的进程直接退出

进程出现异常本质是我们的进程收到了对应的信号

下面是一些信号

例如当我们代码中出现/0时,会出现浮点数异常,

解引用空指针会报段错误 

 

 

而即使进程本身没有异常,但是当我们主动向其发信号时,该进程也会终止 


2.进程常见退出方法


正常终止
1. 调用exit()

exit括号里面跟着的,就是该进程的退出码 

 

 

exit 在任意地方调用都表示调用进程直接退出,而return只表示当前函数返回

所以在main函数中exit和return是等价的 

 2. _exit()

它是一个系统调用接口

基本上和exit()是相同的,但是它是直接结束进程,而exit()会刷新缓冲区之后才退出

实际上

exit最后也会调用exit, 但在调用exit之前,还做了其他工作:

1. 执行用户通过 atexit或on_exit定义的清理函数。
2. 关闭所有打开的流,所有的缓存数据均被写入
3. 调用_exit

从而我们可以推得,缓冲区绝对不在内核区,因为如果在内核区,无论是exit还是_exit都是刷新缓冲区

3. 从main返回

return是一种更常见的退出进程方法。在main函数中执行return n等同于执行exit(n),因为调用main的运行时函数会将main的返回值当做 exit的参数。

异常退出:
ctrl + c,信号终止 


原文地址:https://blog.csdn.net/myhhhhhhhh/article/details/140304144

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!