【Linux从入门到放弃】探究进程如何退出以进程等待的前因后果

🧑‍💻作者: @情话0.0
📝专栏:《Linux从入门到放弃》
👦个人简介:一名双非编程菜鸟,在这里分享自己的编程学习笔记,欢迎大家的指正与点赞,谢谢!

在这里插入图片描述


前言

之前的几篇博客已经是对进程的相关概念做了详细了解,现阶段对进程的定义为内核数据结构加上该进程对应的代码和数据,操作系统对进程通过先描述再组织的方式做管理。有了这些预备知识,接下来就是要学习如何控制进程,也就是在操作上该怎么做。


一、进程创建

1.1 fork函数

  关于fork函数的知识,此篇博客有详细介绍:进程创建

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

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

在这里插入图片描述

在调用fork函数之后,系统会将父进程的代码拷贝一份给子进程,同时会有两个执行流分别执行父进程和子进程,要注意的是子进程不会去执行fork之前的代码。

1.2 写时拷贝

  父子进程代码共享,父子再不写入时,数据也是共享的,当任意一方试图写入,便以写时拷贝的方式各自一份副本。具体见下图:
在这里插入图片描述

在修改内容之前,父子进程的在物理内存页的数据、代码指向同一块位置,如子进程对数据进行修改,,那么此时就会发生写时拷贝,在物理内存页重新开辟一块空间将修改后的数据存入其中。
因为在操作系统是不允许空间的浪费,所以不会将父进程的所有代码数据都在物理内存中重新拷贝一份,而是通过写时拷贝的方式在子进程需要使用(修改)数据的时候才会重新开辟空间,它是一种按需申请资源的策略。

1.3 fork常规用法

  1. 一个父进程希望复制自己,使父子进程同时执行不同的代码段。例如,父进程等待客户端请求,生成子进程来处理请求。
  2. 一个进程要执行一个不同的程序。例如子进程从fork返回后,调用exec函数。

1.4 fork调用失败的原因

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

二、进程退出

2.1 进程退出场景

a. 正常运行完毕(1. 结果正确  2. 结果不正确)
b. 崩溃了(进程异常)  崩溃的本质:进程因为某些原因,导致进程收到了来自操作系统的信号(kill -9)

2.1.1 查看退出码

我们一般在写C语言程序都会在main函数结束时返回 0,这个0代表着该进程的退出码,在linux中,可通过这样的指令查看进程的退出码:echo $?。看下面代码:

int add_to_top(int num)
{
   
  	int sum=0;
  	for(int i=1;i<=num;i++)
  	{
   
    	sum+=i;
  	}
  	return sum;
}

int main()
{
   
   	int ret=add_to_top(100);
  	if(ret==5050)
    	return 1;
  	else 
    	return 0;
}

上面的代码要实现的功能:从1加到100,若和为5050,则返回1,否则返回0。通过下图可以看到该进程的退出码为1,表示结果正确。但是奇怪的是,后两次的查看退出码都为了0,这是因为该指令只会保留最近一次执行的进程的退出码!后两次代表着该条指令执行后的退出码。
在这里插入图片描述

2.1.2 退出码的含义

我们看到的退出码都是数字,对于程序员来说,我们可能知道一些退出码所代表的含义,但是对于一般人来说看到这些数字并不了解所蕴含的意义。所以对于一般人来说,如果你只给他退出码是没有价值,因为他并不知道这些退出码代表的含义。关于退出码的含义我们可以自定义,下面看一下C语言所提供的退出码的含义。

int main()
{
   
  	for(int i=0;i<200;i++)
  	{
   
    	printf("%d:%s\n",i,strerror(i));
  	}
  	return 0;
}

这只是前二十个,后面还有更多。当然这是在linux操作系统下,在windows下所提供的退出码含义是不同的。

在这里插入胜多负少描述

2.2 如何理解进程退出?

关于进程的退出,可以理解的是操作系统内少了一个进程,操作系统要释放进程对应的内核数据结构+代码和数据。

2.3 进程退出的方式

  1. main函数return。而其他函数的return仅仅代表该函数的返回。对于这种方式来说,进程执行本质是main执行流执行,当main函数执行完时代表着进程也就结束了。
  2. exit函数退出。exit函数所包含的数字为该进程的退出码,在函数任意位置调用直接使进程退出。
  3. _exit函数退出。直观感觉上和exit的功能是一样的,但是在一些细节是不一样的。exit函数在退出的时候会自动刷新缓冲区,而_exit函数不会刷新缓冲区。它们两个的关
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

情话0.0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值