Linux->父子进程初识和进程状态

news/2024/4/25 7:13:04/文章来源:https://blog.csdn.net/weixin_52345097/article/details/129194077

目录

前言:

1. 父子进程创建

2. 进程状态

 R(running)状态:

S(sleep)状态:

D(disk sleep)状态:

T(stopped)状态:

X(dead)和Z(zombie)状态:

孤儿进程:   


前言:

        本篇主要讲解关于关于父子进程的生成,以及利用fork生成子进程返回两个不同的返回值的概念,以及不同进程在不同反应下的状态的演示。

1. 父子进程创建

        操作系统会为我们提供一些系统接口服务于我们的程序,而今天我们又会看到一个新的函数接口用于使用,那就是fork()

        这个函数的在#include<unistd.h>这个头文件当中,该函数的返回值为pid_t,也是这个头文件会为我们提供的新的类型。这个函数的作用就是会在当前进程下创建一个子进程,下面请看一个简单的程序来学习父子进程。

  1 #include<stdio.h>2 #include<unistd.h>3 #include<sys/types.h>4 5 int main()6 {7   pid_t ret = fork();8   while(1)9   {10 11     if(ret == 0)12     {13       printf("我是子进程,我的PID是%d,我的PPID是%d,ret = %5d,&ret = %p。\n" 14               ,getpid(),getppid(), ret,&ret);15       sleep(1);16     }17     else18     {19       printf("我是父进程,我的PID是%d,我的PPID是%d,ret = %5d,&ret = %p。\n" 20           ,getpid(),getppid(),ret,&ret);                                                                 21       sleep(1);22     }23     //while(1)24     //{25     //  printf("hello world\n");26     //  sleep(1);27     //}28   }29 30   return 0;

        首先咱们可以看到我们通过fork()生成了一个子进程,由ret来接收它的返回值,但是大伙可能不知道ret其实接收的不只是子进程的返回值,还有当前进程的返回值,请看下图。

         可以看到父子进程的ret变量的地址是一模一样的,但是有没有发现这个地址却对应了两个值?子进程的返回值是0,而父进程是一个非0的值。

        这很明显不符合我们学习这么长时间代码的规律——一个地址只能存取一个数据。那么这里是系统出BUG了吗?很显然不是的,要是这是一个BUG我也不会为大家讲解了。

        那么会出现这个问题的原因其实简单来说就是,我们在程序中获取到的地址,并不是数据存储的真实位置,这是一个伪地址,操作系统会偷偷的给ret找两个存储空间,这一过程被称为写时拷贝,我会在下一篇“进程地址空间”中详细讲解,下面请先看图。

        首先我们得知道进程是有独立性的,而进程又是由于内核相关的数据结构 + 代码和数据所构成,那么我们也得保证代码、数据和数据结构也的是独立得才行,所以在同一块地址需要存储两个数据时就不能放在同一块空间,从而出现写时拷贝。       

         从程序运行图当中,我们还能看到两个东西PID(Process ID)和PPID(Parent Process ID),也就是当前进程的ID和它的父进程ID。通过函数getpid()和getppid()可以得到。

        进程ID也就相当于我们得身份证,标明这个进程存在,可以通过这个ID找到它,同时也可以通过这个ID对它进行修改等操作。

2. 进程状态

        我们为了弄明白正在运行得进程时什么意思,我们需要知道进程得不同状态。一个进程可以有几个状态。请先看状态在kernel源码中的定义:

/*
* The task state array is a strange "bitmap" ofreasons to sleep. Thus "running" is zero, and *you can test for combinations of others with simple bit tests.
*/
static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};

 R(running)状态:

        R——运行状态,我问大家一个问题,当我们的电脑中有多个软件都被运行着,那么这些软件是否在每一时刻都被CPU运行着呢?

        答案是不是,还记得我们的PCB吗,CPU基于PCB去管理这些进程,而管理方式为将这些PCB结构体用特定的数据结构组织起来,例如链表方式,所以CPU在运行这些进程的时候会拿到这些进程的PCB,从而执行程序,那么此时咱们就可以联想到,CPU运行进程其实是拿到PCB,运行一会,中断,拿到下一个PCB在运行,再中断,周而复始,那么运行状态的出现其实是这个进程要么在运行,要么处于运行队列当中。

        虽然这样说,但是我们是没有实际感受的,因为我们平时用电脑也没有看到一个程序一会关掉,一会又开始的情况,对此我只能说,CPU的运行速度确实厉害。

        不过大家却遇到过另一个问题,那就是电脑卡死的现象,这一现象与我们下一个状态S有关。

S(sleep)状态:

        在理解S状态之前我们需要先明白阻塞的概念,阻塞顾名思义,也就是当前进程没有继续推进,在等待某种资源获取成功

        那么某种资源是什么呢?举一个简单的例子大家就会懂了:

        我们在网上下载游戏或者影视资源时需不需要联网?肯定是需要的,但是在下载的时候,我们将网线给他拔了,又或者是把WIFI给砸了,那么这个时候电脑处于没有网络的状态,他还能继续下载吗?当然是不能的,毕竟没有网嘛,那么此时我们的进程就在等待着网络资源,CPU就不会将他放在运行队列当中,而给它挂上S状态,让它自己去等。

         我们运行的进程当中STAT下的S+就是睡眠状态,也可以叫做阻塞状态。不过大家可能有些奇怪,我不是将程序运行起来了吗?网好好的,也没个键盘输入啥的,为什么不是R状态而是S状态呢?有这个疑问的朋友可能忘记了一件事情,那就是将数据打印到显示器上有没有等待显示器准备完毕的资源信息呢?一定是有的咯,所以我们基本看不出来有程序处于R状态,一般都是在S状态。

D(disk sleep)状态:

        D状态是S状态的另外一种表现形式,我们也称为不可中断睡眠状态,挂起。这个概念不好理解,我还是以讲故事的形式为大家解释。

        我们有CPU,内存,磁盘三个人,某一天磁盘中有程序要运行,然后操作系统就将程序加载到内存当中,然后呢,这个程序要下载100个G的数据进磁盘当中,操作系统说:“好,你下载吧”,然后程序就呆在内存当中挂一个S状态等着。此时,电脑开了很多进程,CPU忙的不可开交,这个时候他就看到了内存里有个程序啥都不干,就在那里呆着。CPU气不过,说:“我都快要忙死了,你还在这里干扰我?去死吧你。”然后这个进程就被CPU杀死了。

        这个时候,磁盘内容已经下好了,却发现找不到人来拿了,这就把磁盘急坏了,他又不敢删,但是又不知道应该把这个数据交给谁,问题就出现了。

         上面的故事谁错了呢?其实它们都没有错,错的是这个世界。哈哈,开个玩笑,它们确实都没有做错,操作系统可以杀掉进程,这是它的权力,进程在等待资源,也是它的权力,而磁盘人家一直在辛辛苦苦的下载,有什么错?

        其实,上面的过程究其原因不就是操作系统把进程给杀掉了,导致磁盘找不到人了吗?所以我们让进程不能被杀掉不就可以了?所以这个时候D状态就出现了。

        操作系统看到进程是D状态,它就先获取这个进程的PCB,然后把这个进程退出内存,回到磁盘当中,当磁盘资源下载完毕,又将这个进程重新加载进入内存当中执行。

T(stopped)状态:

         该状态表示当前停止当前的进程,直到收到继续执行的指令才会再次运行。

        下面我以例子在执行:

        初始运行状态

         输入指令kill -19 27911,暂停父进程。运行状态,只有子进程还在执行。

        此时的父进程状态也由S+变为了T。 

         注意,这里的子进程也由S+变为了S,这里的+表示前台运行,可以直接ctrl+c终止,但是没有+表示后台运行,需要kill杀掉进程才能终止。

X(dead)和Z(zombie)状态:

        X状态是在一个进程结束之后显示的状态,这只是一个返回状态,我们不能在人物列表里面看到这个状态。

        而Z状态表示当父进程和子进程都运行着,然后子进程被干掉了,此时子进程的资源还没有被系统回收,这个时候就会处于僵尸状态等待父进程去回收它。如下:

孤儿进程:   

        孤儿进程与僵尸状态正好相反,它是父子进程都在运行时,父进程被干掉了,此时的子进程会被init初始进程也就是1号进程收养,用于子进程结束后回收资源。如下:

         看到此时的子进程的父进程变化称为了1。


        以上就是我对本篇的全部理解,谢谢大伙查看。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_73566.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

同事每天早下班,原来是用了这8个开发工具

引言 工欲善其事必先利其器&#xff0c;说的就是工匠要想更加高效的做事情&#xff0c;就得先将工具变得锋利。那么对于程序员来说同样也是如此&#xff0c;如果要想每天早点下班&#xff0c;就必须借助于一些开发工具来提高自己的工作效率&#xff0c;今天慕枫就给大家总结一…

365智能云打印怎么样?365小票无线订单打印机好用吗?

365智能云打印怎么样&#xff1f;365智能云打印是有赞官方首推的订单小票打印机&#xff0c;荣获2016年有赞最佳硬件服务商。可以实现远程云打印&#xff0c;无需连接电脑&#xff0c;只需通过GPRS流量或者WIFI即可连接&#xff0c;不受地理位置和距离限制。365小票无线订单打印…

关于高并发场景和进程线程协程的一些总结

1、IO复用和线程池哪个好&#xff1f;应用场景&#xff1f; IO复用就是一个线程处理多个客户端连接。如果自己实现的话&#xff0c;就是要不断轮询每个客户端连接&#xff0c;看看有没有事件发生&#xff08;数据到达&#xff09;&#xff0c;即使可以用非阻塞的read函数&…

Python编写GUI界面,实现小说下载器

嗨害大家好鸭&#xff01;我是小熊猫~思路一、数据来源分析二. 代码实现步骤代码实现一、单章小说下载二、整本小说下载三、多线程采集四、采集排行榜所有小说五、搜索小说功能六、GUI界面<center>**&#x1f447;问题解答 源码获取 技术交流 抱团学习请联系&#x1f…

金仓数据库安装

一、麒麟操作系统安装金仓数据库 操作系统 DISTRIB_IDKylin DISTRIB_RELEASEV10 DISTRIB_CODENAMEjuniper 按照安装文档的步骤安装&#xff0c;记得记住设置的数据库的用户名、密码 二、window安装连接数据库的工具软件 三、jdbc连接数据库 &#xff08;1&#xff09;连接工…

错误记录:py2neo.errors.ProtocolError: Cannot decode response content as JSON

py2neo.errors.ProtocolError: Cannot decode response content as JSON 原因&#xff1a;目前不清楚 解决方法&#xff1a;进入\lib\site-packages\py2neo\database.py中更改graph_name为neo4j 程序正常运行

Linux命令及CPU占用过高的定位分析思路

一、vim命令不要使用vim打开大文件&#xff0c;vim会一次性读取所有内容到内存&#xff0c;容易造成宿主机内存溢出。 打开文件前&#xff0c;可以使用du -h命令查看文件大小。一般&#xff0c;100MB以下为宜。1、普通模式j 向下30j 向下移动30行k 向上h 向左l 向右0 到行首^ 到…

分阶段构建golang运行环境Dockerfile镜像

在开始这项工作之前大家可以先去看一下docker官方给出关于空镜像scratch的说明&#xff0c;采用官方简单的一句话就是&#xff1a;scratch是一个明确的空图像&#xff0c;特别是对于“从头开始”构建图像。分阶段构建镜像就会用到scratch这个空镜像&#xff0c;这样的好处是可以…

Vulnhub靶场----7、DC-7

文章目录一、环境搭建二、渗透流程三、思路总结一、环境搭建 DC-7下载地址&#xff1a;https://download.vulnhub.com/dc/DC-7.zip kali&#xff1a;192.168.144.148 DC-7&#xff1a;192.168.144.155 二、渗透流程 nmap -T5 -A -p- -sV -sT 192.168.144.155思路&#xff1a; …

【Rust 日报】2023-2-23 Ambient 0.1 发布

治理改革 RFC公告官方博客发布了治理改革RFC的公告&#xff0c;了解详情请点开链接查看。主要看点其实是新的RFC改革治理之后&#xff0c;提供了多语言的支持&#xff0c;其中包括简体中文&#xff0c;该PR目前还在讨论中。原文: https://blog.rust-lang.org/inside-rust/2023/…

RabbitMQ 实现延迟队列

业务场景&#xff1a;1.生成订单30分钟未支付&#xff0c;则自动取消&#xff0c;我们该怎么实现呢&#xff1f;2.生成订单60秒后,给用户发短信1 安装rabbitMqwindows安装ubuntu中安装2 添加maven依赖<!-- https://mvnrepository.com/artifact/org.springframework.boot/spr…

「JVM 编译优化」Graal 编译器

文章目录1. 历史背景2. 构建编译调试环境3. JVMCI 编译器接口4. 代码中间表示5. 代码优化与生成1. 历史背景 Graal 编译器在 JDK 9 以 Jaotc 提前编译工具的形式首次加入到官方的 JDK 中&#xff0c;JDK 10 开始提供替换&#xff08;得益于 HotSpot 编译器接口&#xff0c;Jav…

扬帆优配|“涨停敢死队”慌了?监管“盯紧”异常交易

日前&#xff0c;沪深买卖所发布《主板股票反常买卖实时监控细则》&#xff0c;对反常买卖行为的类型和标准作出规则。其间&#xff0c;针对“打板”“封板”等反常行为的监控遭到商场重视&#xff0c;有商场传闻称&#xff0c;新规或导致高频买卖毁灭&#xff0c;“量价型股票…

MySQL进阶知识

1 存储引擎1.1 MySQL体系结构1.2 存储引擎简介存储引擎就是存储数据、建立索引、更新/查询数据等技术的实现方式。存储引擎是基于表的&#xff0c;而不是基于库的&#xff0c;同一个库的多个表可以采用不同的存储引擎&#xff0c;所以存储引擎也经常称为表类型。创建表时可以指…

pyhon笔记——Anaconda安装

一、简介 Anaconda包括Conda、Python以及一大堆安装好的工具包&#xff0c;比如&#xff1a;numpy、pandas等 Miniconda包括Conda、Python conda是一个开源的包、环境管理器&#xff0c;可以用于在同一个机器上安装不同版本的软件包及其依赖&#xff0c;并能够在不同的环境之…

Android:实现签名功能——signature-pad库

文章目录实现效果步骤1、添加 signature-pad 库的依赖。2、在 layout 文件中使用 SignaturePad 控件&#xff0c;另外添加“清空”和“保存”两个按钮。3、实现清空 SignaturePad 控件内容的功能4、实现保存 SignaturePad 控件内容的功能5、实现兼容Android10以下和Android10以…

Video 标签无法播放 mp4 的原因和解决办法

问题 用 QQ 的截图录屏功能录制的 mp4 视频&#xff0c;无法用 <video> 标签正常播放。 原因 通过搜索的说法是&#xff1a; 查阅文档&#xff08;不知道是啥文档&#xff09;&#xff0c;关于video标签所支持的视频格式和编码&#xff1a; MPEG4 带有H.264视频编码和…

大规模食品图像识别:T-PAMI 2023论文解读

美团基础研发平台视觉智能部与中科院计算所展开科研课题合作&#xff0c;共同构建大规模数据集Food2K&#xff0c;并提出渐进式区域增强网络用于食品图像识别&#xff0c;相关研究成果已发表于T-PAMI 2023。本文主要介绍了数据集特点、方法设计、性能对比&#xff0c;以及基于该…

【STM32MP157应用编程】2.GPIO输入、输出、中断

目录 GPIO文件 指令操作GPIO 程序操作GPIO 程序说明 程序代码 2_GPIO_4.c 启动交叉编译工具 编译 拷贝到开发板 测试 GPIO文件 在/sys/class/gpio目录下&#xff0c;存放了GPIO的文件。 gpiochipX&#xff1a;当前SoC所包含的GPIO控制器&#xff0c;STM32MP157一共包…

input 子系统

简介 先来了解什么是输入设备&#xff1f; 常见的输入设备有键盘、 鼠标、 遥控杆、 书写板、 触摸屏等等,用户通过这些输入设备与 Linux 系统进行数据交换。 什么是输入系统&#xff1f; 输入设备种类繁多&#xff0c; 能否统一它们的接口&#xff1f; 既在驱动层面统一&…