Linux:进程状态

文章目录

  • 前言
  • 一、初识fork
    • 1.1 fork函数的介绍
    • 1.2 fork出的子进程存在形式
    • 1.3 写时拷贝
  • 二、进程的状态
    • 2.1 Linux内核源代码
    • 2.2 理解内核链表(重要)
    • 2.3 运行状态
    • 2.4 阻塞状态
    • 2.5 挂起状态
  • 三、Z(zombie)状态 ,僵尸进程
  • 四、 孤儿进程
  • 总结


前言

本文将介绍如何利用系统调用来在创建进程,并进一步了解进程的状态,以及相对应延伸出来的僵尸进程和孤儿进程等知识点


一、初识fork

Linux中的fork函数是进程创建的核心机制之一。它允许从一个已经存在的进程中创建一个新的进程(子进程),并通过写时拷贝技术优化内存使用。

1.1 fork函数的介绍

我们在函数内部使用fork时它会创建一个子进程,并且它会返回两个pid_t类型值(实际上就是整形),子进程的pid会返回给父进程,0会返回给子进程,创建错误返回-1。

而返回两个值的具体的实现方法主要依赖于操作系统的进程管理和上下文切换机制(当前不做过多赘述,只需要知道有这个东西就好了)。并且由task_struct链表形式可知每个进程都是具有独立性的!
在这里插入图片描述
在这里插入图片描述

当他返回两个值的时候我们就可以根据if语句来对父子进程做出不同的代码逻辑实现了。

1.2 fork出的子进程存在形式

父进程与子进程的存在是 1 :n 存在的,这意味着一个父进程可以有多个子进程,但一个子进程只有一个父进程。这也是父进程内部代码使用fork函数创建子进程的时候返回子进程id并返回0给子进程的原因。

并且子进程的PCB跟父进程的PCB相同。这意味着两者的exe和cwd相同,意味着指向同一块代码和数据。
在这里插入图片描述

1.3 写时拷贝

写时拷贝(Copy On Write,简称COW)是一种优化技术,主要用在计算机编程中,特别是在处理字符串或大型数据结构时

定义:
写时拷贝是指在多个对象或变量共享同一块内存空间时,如果其中一个对象或变量试图修改这块内存中的数据,系统就会为修改者分配一块新的内存空间,并将原始数据复制到这块新空间中,然后让修改者在新空间中操作数据,而其他对象或变量仍然共享原始的内存空间。

二、进程的状态

由于状态也是进程的一个属性, 所以进程的状态就是task_struct内的一个整数!

2.1 Linux内核源代码

  • 为了弄明⽩正在运⾏的进程是什么意思,我们需要知道进程的不同状态。⼀个进程可以有⼏个状态(在Linux内核⾥,进程有时候也叫做任务)。
/*
*The task state array is a strange "bitmap" of
*reasons 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):并不意味着进程⼀定在运⾏中,它表明进程要么是在运⾏中要么在运⾏
队列⾥。
• S睡眠状态(sleeping):意味着进程在等待事件完成(这⾥的睡眠有时候也叫做可中断睡眠
(interruptible sleep))。
• D磁盘休眠状态(Disksleep)有时候也叫不可中断睡眠状态(uninterruptiblesleep),在这个
状态的进程通常会等待IO的结束。
• T停⽌状态(stopped):可以通过发送SIGSTOP信号给进程来停⽌(T)进程。这个被暂停的
进程可以通过发送SIGCONT信号让进程继续运⾏。
• X死亡状态(dead):这个状态只是⼀个返回状态,你不会在任务列表⾥看到这个状态。

2.2 理解内核链表(重要)

在前面的认知中,我们说进程的数据结构是双链表,但是它同时也可以存在于队列结构中,这是为什么呢?

我们平时设计的双链表结构是这样子的
在这里插入图片描述

但是在PCB及task_struct中并不是这么设计的,它没有定义同类型指针next和prev!!它选择在自己的成员变量中增加一个结构体,这个结构体只定义了同类型指针next和prev,然后task_struct将这个结构体包含。
在这里插入图片描述

细节上是:原本的设计会指向整个结构体,但是增加一个结构体成员指针变量后,就通过这个list_head,而指向另外task_struct结构体的list_head而不会指向整个task_struct

我们在c语言阶段知道有个东西叫做偏移量,当我们想访问整个task_struct结构体的时候,就可以通过lit_head的偏移量(&(struct task_struct*)0->links)计算出task_struct结构体地址并通过强转成task_struct,代码为(struct task_struct*)(next - (struct task_struct*)0->links),这意味着lsit_head结点可以存储task_struct的位置信息
在这里插入图片描述

以下总结很重要!!:
就相当于list_head这个结构体存储了task_struct的位置信息,如果想要树结构我们再定义一个struct tree_node放入task_struct里面就可以构成树结构了!!
一个task_struct可以包含右很多的类似list_head结点,因此一个task_struct能被放到双链表或者队列来进行操作。一个PCB在内核中只存在一份,但它可以隶属于多种数据结构,意味着我们可以把这个task_struct根据不同的需求来变成双链表或者队列等含节点的数据结构进行操作。

由此引出以下概念:
进程状态的变化,表现之一就是在不同的队列中进行流动,本质都是数据结构的增删改查

2.3 运行状态

Runqueue(运行队列)是Linux内核中用于管理和调度进程的核心数据结构之一。Runqueue是Linux内核调度程序中的数据结构,用于存储给定处理器(CPU)上的可执行进程。

当一个进程被放到运行队列里面的时候,就是运行状态
在这里插入图片描述

2.4 阻塞状态

当进程由于等待某个事件(如I/O操作完成、资源可用、信号量等)而暂时无法继续执行。此时这个状态就叫做进程的阻塞状态

此时细节上的发生就是身处调度队列中的一个PCB因为执行到某个代码块(例如scanf函数需要我们输入时),这个PCB会流动到另一个队列中,等到事件结束
在这里插入图片描述
以下是一个简单的示例,用于说明进程从运行状态到阻塞状态的流动过程:

  • 假设有一个进程正在执行一个需要从键盘读取数据的操作(如使用scanf函数)。
  • 当进程执行到scanf函数时,它会等待用户输入数据。此时,由于用户尚未输入数据,进程无法继续执行,因此会进入阻塞状态。
  • 操作系统会将该进程的PCB从运行队列中移出,并放入到键盘的等待队列中。
  • 当用户输入数据并按下回车键时,键盘中断被触发,操作系统会读取输入数据并将其放入到内核输入缓冲区中。
  • 随后,操作系统会通知该进程数据已经就绪,进程会从键盘的等待队列中移出,并重新进入运行队列等待被调度执行

2.5 挂起状态

  • 进程的执行被暂时停止,并且其数据被保存在内存中,但不会被调度执行。
  • 挂起可以由系统主动发起(如内存不足时,将不活跃进程挂起),也可以由用户请求(如调试、暂停进程)。
  • 挂起状态可以是“就绪挂起”(Ready Suspended)或“阻塞挂起”(Blocked Suspended),分别对应于就绪和阻-塞状态的挂起。
    在这里插入图片描述

三、Z(zombie)状态 ,僵尸进程

当一个进程退出时会释放其占用的系统资源,但是其PCB并不会消失,task_struct里面会记录一些自己完成退出的信息,返回给父进程

  • 僵死状态(Zombies)是⼀个⽐较特殊的状态。当进程退出并且⽗进程(使⽤wait()系统调⽤,后
    ⾯讲)没有读取到⼦进程退出的返回代码时就会产⽣僵死(⼫)进程
  • 僵死进程会以终⽌状态保持在进程表中,并且会⼀直在等待⽗进程读取退出状态代码。
  • 所以,只要⼦进程退出,⽗进程还在运⾏,但⽗进程没有读取⼦进程状态,⼦进程进⼊Z状态

总结:僵尸进程就是子进程结束后,父进程没有处理子进程的返回状态,并且这个过程很可能造成内存泄漏!

四、 孤儿进程

产生原因如下

  • 子进程是通过父进程创建的。子进程的结束和父进程的运行是一个异步过程,即父进程无法准确预测子进程何时会结束。当一个父进程由于正常完成工作而退出,或者由于其他情况(如异常终止)被操作系统终止时,如果它的一个或多个子进程仍在运行,那么这些子进程就会失去父进程,成为孤儿进程。

特点如下:

  1. 无父进程控制:孤儿进程失去了原父进程的直接控制,但它们仍然能够继续运行并完成剩余的工作。
  2. 被init进程收养:操作系统会自动将孤儿进程的父进程设置为init进程 (在Unix/Linux系统中,init进程通常是PID为1的进程,而在现代系统中可能是systemd),由init进程负责后续对孤儿进程的管理和回收。(由前面僵尸进程中的知识点可知子进程一定是要靠父进程回收处理的,但如果一个父进程先结束了,那么子进程就会被1号进程托管)
  3. 无害性:与僵尸进程不同,孤儿进程并不会对系统造成危害。因为init进程会确保它们在完成工作后得到妥善处理。

总结:孤儿进程是操作系统中一种常见的进程状态,其产生原因和处理机制都是操作系统设计中的重要考虑因素。通过init进程的收养和回收机制,可以确保孤儿进程在完成工作后得到妥善处理,从而避免系统资源的浪费。


总结

本文主要讲解了进程的创建初步认识,并说明了为什么一个task_struct可以做不同的数据结构去操作,然后把进程的重要状态描述一遍。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

qml显示加载嵌入QWidget窗口

本篇博客介绍如何在qml界面里显示QWidget窗口,开发环境Qt6.5.3 qml. 视频讲解:https://edu.csdn.net/learn/40003/654001?spm=3001.4143 qml和QWidget是两套独立的开发方式,二者的窗口可以相互嵌套显示,本篇博客介绍把QWidget窗口封装为动态库,然后在QML的窗口里显示出来…

【MySQL】多表查询

5. 多表查询 5.1 多表关系 项目开发中,在进行数据库表结构设计时,会根据业务需求及业务模块之间的关系,分析并设计表结构,由于业务之间相互关联,所以各个表结构之间也存在着各种联系,基本上分为三种&#…

2024-11-16 串的存储结构

一、顺序存储。 1.首先定一个静态数组,然后定义i记录串的实际长度。(缺点:长度不可变) 2.使用malloc申请动态空间,定义指针指向串的地址。(需手动ferr) 方案一: 数组末尾记录长度 …

nodejs21: 快速构建自定义设计样式Tailwind CSS

Tailwind CSS 是一个功能强大的低级 CSS 框架,只需书写 HTML 代码,无需书写 CSS,即可快速构建美观的网站。 1. 安装 Tailwind CSS React 项目中安装 Tailwind CSS: 1.1 安装 Tailwind CSS 和相关依赖 安装 Tailwind CSS: npm…

Windows 安装Docker For Desktop概要

Windows 安装docker 下载部分的工作需要使用科学技术。如果没有可以联系博主发送已下载好的文件。 本文档不涉及技术的讲解,仅有安装的步骤。 准备工作 包含下载与环境准备,下载的文件仅下载,在后续步骤进行安装。 微软关于wsl的文档&…

对称加密算法DES的实现

一、实验目的 1、了解对称密码体制基本原理 2、掌握编程语言实现对称加密、解密 二、实验原理 DES 使用一个 56 位的密钥以及附加的 8 位奇偶校验位,产生最大 64 位的分组大小。这是一个迭代的分组密码,使用称为 Feistel 的技术,其中将加密…

三十八、Python(pytest框架-上)

一、介绍 框架(framework):框架是为解决一类事情的功能集合。 pytest框架:pytest框架是单元测试框架,这是第三方框架想要使用必须要安装,可以使用pytest来作为自动化测试执行框架,用来管理测试…

《Django 5 By Example》阅读笔记:p165-p210

《Django 5 By Example》学习第6天,p165-p210总结,总计46页。 一、技术总结 1.bookmarks项目 (1)登录认证 作者这里使用的是Django自带的auth。 (2)上传头像 图片处理,使用Pillow。 (3)扩展user 扩展user模型与自带的user使用外键进行…

shell基础(3)

声明! 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽sec团…

JVM面试题总结

1.介绍一下JVM的内存结构 JDK1.8及以后,JVM主要分为元空间、堆、虚拟机栈、本地方法栈、程序计数器五个部分,另外还有一个直接内存部分,是直接属于操作系统的。 其中元空间、堆是线程共享的,虚拟机栈、本地方法栈、程序计数器是线…

小新Pro 14 AHP9 2024款(83D3)原装oem预装系统Win11恢复安装包下载

适用品牌机型 :LENOVO联想【83D3】 链接:https://pan.baidu.com/s/10RAxNdvYPWJ21b_4--Y7Xw?pwdo5ju 提取码:o5ju 联想原装出厂Windows11系统自带所有驱动、出厂主题壁纸、系统属性联机支持标志、系统属性专属LOGO标志、Office365办公软…

【论文笔记】Towards Privacy-Aware Sign Language Translation at Scale

🍎个人主页:小嗷犬的个人主页 🍊个人网站:小嗷犬的技术小站 🥭个人信条:为天地立心,为生民立命,为往圣继绝学,为万世开太平。 基本信息 标题: Towards Privacy-Aware Si…

Spring:bean的配置

对于bean的配置中,主要会讲解bean基础配置,bean的别名配置,bean的作用范围配置(重点),这三部分内容: bean基础配置 id与class配置 bean的name属性 bean的别名配置 bean作用范围scope配置 scope使用后续思考 介绍完scope属性以后,我们…

贴代码框架PasteForm特性介绍之markdown和richtext

简介 PasteForm是贴代码推出的 “新一代CRUD” ,基于ABPvNext,目的是通过对Dto的特性的标注,从而实现管理端的统一UI,借助于配套的PasteBuilder代码生成器,你可以快速的为自己的项目构建后台管理端!目前管…

【RK3588 Linux 5.x 内核编程】-内核中的链表(Linked List)及使用

内核中的链表(Linked List)及使用 文章目录 内核中的链表(Linked List)及使用1、Linked List介绍2、Linux内核中的链表3、链表的操作3.1链表初始化3.2 创建节点3.3 添加节点3.4 删除节点3.5 替换节点3.6 移动节点3.7 链表旋转3.8 链表检测3.9 链表分割与合并3.10 链表遍历4、驱…

永夜星河主题特效2(星河背景 + 闪烁文字+点击星星 + 文字弹出特效)

目录 图片展示 星河背景 闪烁文字点击星星 文字弹出特效 特效介绍&#xff1a; 使用方式&#xff1a; 图片展示 星河背景 闪烁文字点击星星 文字弹出特效 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8">&l…

通过JS实现下载图片到本地教程分享

今天分享的这个方法我之前自己试了一下&#xff0c;感觉还行&#xff0c;原理就是通过<a>标签的新增属性实现的&#xff0c;然后可以强制触发下载功能&#xff0c;废话不多说&#xff0c;直接上教程。 首先在HTML写下面的代码: <a href"img.jpg" download…

Harmony错题本--@Preview标注上依然无法预览

初学HarmonyOs开发&#xff0c;写了一个超级简单的组件&#xff0c;但是代码上没有什么问题&#xff0c;DevEco Studio却无法完成预览 代码如下&#xff1a; // 单纯的右键-> ArkTsFile的话&#xff0c;可以创建一个组件。 // 原因是&#xff0c;之前我们学过通过右键->…

【linux学习指南】VSCode部署Ubantu云服务器,与Xshell进行本地通信文件编写

文章目录 &#x1f4dd;前言&#x1f320; 步骤&#x1f309;测试同步 &#x1f6a9;总结 &#x1f4dd;前言 本文目的是讲使用Vscode连接Ubantu,与本地Xshell建立通信同步文件编写。 查看本机系统相关信息&#xff1a; cat /etc/lsb*DISTRIB_IDUbuntu: 表示这是 Ubuntu 发行…

ES-针对某个字段去重后-获取某个字段值的所有值

针对上面表的数据&#xff0c;现在想根据age分组&#xff0c;并获取每个分组后的name有哪些(去重后)。 select age, GROUP_CONCAT(DISTINCT(name)) from testtable group by age ; 结果&#xff1a; 如果想要增加排序&#xff1a; SELECT age, GROUP_CONCAT(DISTINCT name)…