进程的状态与task_struct结构体

2023-10-31

一、什么是进程
进程,就是程序的一个执行实例,或正在执行的程序。
详细介绍请看 点击打开链接
那么进程在Linux中有几种状态呢?如下:

1、R
处于运行或可运行状态,即进程正在运行或在运行队列(可执行队列)中等待。只有在该状态的进程才可能在CPU上运行,同一时刻可能有多个进程处于该状态。
(注:很多教科书上将正在CPU上执行的进程的状态定义为Running,将可执行但尚未被调度执行的进程状态定义为Ready,这2种状态在Linux下统一为R状态)
2、S
处于可中断的睡眠状态,即进程在休眠中,由于在等待某个事件的完成(或等待某个条件的形成或等待某个信号等)
(注:等待socket连接、等待信号量等)而被挂起;当这些事件发生时,对应的等待队列中的一个或多个进程将被唤醒。一般情况下,进程列表中绝大多数进程都处于该状态。 
3、D
处于不可中断的睡眠状态不可中断指的并不是CPU不响应外部硬件的中断,而是指进程不响应异步信号,无法用kill命令杀死,进程必须等待直到有中断发生。
4、T
处于暂停或跟踪状态。进程收到SIGSTOP、SIGSTP、SIGTIN、SIGTOU等信号进入暂停状态(除非进程处于不可中断的睡眠状态);当接着向进程发送1个SIGCONT信号,进程可以从暂停状态恢复到运行或能运行状态。
当进程被跟踪时,它处于被跟踪状态。“被跟踪”指进程暂停下来,等待跟踪它的进程对它进行操作。例如在GDB调试中,对被跟踪的进程设置某个断点,进程执行到断点处停下来的时候就处于被跟踪状态。
暂停与跟踪状态还是有区别的,被跟踪状态相当于在暂停状态之上多了一层保护,处于被跟踪状态的进程不能响应SIGCONT信号而被唤醒,只能等到调试进程通过ptrace系统调用执行ptrace_cont、ptrace_detach等操作(通过ptrace系统调用的参数指定操作),或调试进程退出,被调试的进程才能恢复到R状态。
5、Z
处于僵死状态,也称退出状态。它指进程已经结束,放弃了几乎所有的内存空间,没有任何可执行代码,也不能被调度,仅仅在进程列表中保留一个位置来记载该进程的退出状态等信息(task_struct结构体[保存了该进程的退出码])供其他进程收集
6、X
进程在退出过程中可能不会保留它的task_struct。例如某个进程是多线程程序中被detach过的进程;或者父进程通过设置SIGCHLD信号的Handler为SIG_IGN,显示的忽略了SIGCHLD信号。

此时该进程被置于exit_dead退出状态,这意味着接下来的代码立即会将该进程彻底释放。故exit_dead状态非常短暂,几乎不可能通过ps命令捕捉到。

二、模拟实现僵尸进程与孤儿进程

1、僵尸进程

Makefile文件:

  1 
  2 .PHONY:jiangshi
  3 
  4 jiangshi:jiangshi.c
  5     gcc -o $@ $^
  6 
  7 .PHONY:clean
  8 clean:
  9     rm -f jiangshi

jiangshi.c

 1 #include<stdio.h>
  2 #include<stdlib.h>
  3 int main(){
  4         pid_t id=fork();
  5         if(id<0){
  6                 perror("fork");
  7                 return 1;
  8         }
  9         else if(id>0){//parent
 10                 printf("parent[%d] is sleeping...\n",getpid());
 11                 sleep(30);
 12             }
 13         else{
 14             printf("child[%d] is begin Z...\n",getpid());
 15             sleep(5);
 16             exit(EXIT_SUCCESS);
 17         }
 18         return 0;
 19     }

2、孤儿进程

Makefile文件

 1 
  2 
  3 .PHONY:guer
  4 
  5 guer:guer.c
  6     gcc -o $@ $^
  7 
  8 .PHONY:clean
  9 clean:
 10     rm -f guer
guer.c
  1 #include<unistd.h>
  2 #include<stdio.h>
  3 #include<stdlib.h>
  4 int main(){
  5         pid_t id=fork();
  6         if(id<0){
  7                 perror("fork");
  8                 return 1;
  9         }
 10             else if(id==0){//child
 11                 printf("I am child,pid:%d\n",getpid());
 12                 sleep(10);
 13             }
 14         else{//parent
 15             printf("I am parent,pid:%d\n",getpid());
 16             sleep(3);
 17             exit(0);
 18         }
 19         return 0;
 20     }

、task_struct结构体  

每个进程在内核中都有一个进程控制块(PCB)来维护进程相关的信息,Linus内核的进程控制块是task_struct的结构体
struct task_struct
{
volatile long state;         //说明了该进程是否可以执行,还是可中断等信息
unsigned long flags;         //Flage 是进程号,在调用fork()时给出
int sigpending;              //进程上是否有待处理的信号
mm_segment_t addr_limit;     //进程地址空间,区分内核进程与普通进程在内存存放的位置不同
                           //0-0xBFFFFFFF for user-thead
                           //0-0xFFFFFFFF for kernel-thread
//调度标志,表示该进程是否需要重新调度,若非0,则当从内核态返回到用户态,会发生调度
volatile long need_resched;
int lock_depth;  //锁深度
long nice;       //进程的基本时间片
//进程的调度策略,有三种,实时进程:SCHED_FIFO,SCHED_RR, 分时进程:SCHED_OTHER
unsigned long policy;
struct mm_struct *mm; //进程内存管理信息
int processor;
//若进程不在任何CPU上运行, cpus_runnable 的值是0,否则是1 这个值在运行队列被锁时更新
unsigned long cpus_runnable, cpus_allowed;
struct list_head run_list; //指向运行队列的指针
unsigned long sleep_time;  //进程的睡眠时间
//用于将系统中所有的进程连成一个双向循环链表, 其根是init_task
struct task_struct *next_task, *prev_task;
struct mm_struct *active_mm;
struct list_head local_pages;       //指向本地页面     
unsigned int allocation_order, nr_local_pages;
struct linux_binfmt *binfmt;  //进程所运行的可执行文件的格式
int exit_code, exit_signal;
int pdeath_signal;     //父进程终止时向子进程发送的信号
unsigned long personality;
//Linux可以运行由其他UNIX操作系统生成的符合iBCS2标准的程序
int did_exec:1;
pid_t pid;    //进程标识符,用来代表一个进程
pid_t pgrp;   //进程组标识,表示进程所属的进程组
pid_t tty_old_pgrp;  //进程控制终端所在的组标识
pid_t session;  //进程的会话标识
pid_t tgid;
int leader;     //表示进程是否为会话主管
struct task_struct *p_opptr,*p_pptr,*p_cptr,*p_ysptr,*p_osptr;
struct list_head thread_group;   //线程链表
struct task_struct *pidhash_next; //用于将进程链入HASH表
struct task_struct **pidhash_pprev;
wait_queue_head_t wait_chldexit;  //供wait4()使用
struct completion *vfork_done;  //供vfork() 使用
unsigned long rt_priority; //实时优先级,用它计算实时进程调度时的weight值

long per_cpu_utime[NR_CPUS], per_cpu_stime[NR_CPUS];
//内存缺页和交换信息:
//min_flt, maj_flt累计进程的次缺页数(Copy on Write页和匿名页)和主缺页数(从映射文件或交换
//设备读入的页面数); nswap记录进程累计换出的页面数,即写到交换设备上的页面数。
//cmin_flt, cmaj_flt, cnswap记录本进程为祖先的所有子孙进程的累计次缺页数,主缺页数和换出页面数。
//在父进程回收终止的子进程时,父进程会将子进程的这些信息累计到自己结构的这些域中
unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap;
int swappable:1; //表示进程的虚拟地址空间是否允许换出
//进程认证信息
//uid,gid为运行该进程的用户的用户标识符和组标识符,通常是进程创建者的uid,gid
//euid,egid为有效uid,gid
//fsuid,fsgid为文件系统uid,gid,这两个ID号通常与有效uid,gid相等,在检查对于文件
//系统的访问权限时使用他们。
//suid,sgid为备份uid,gid
uid_t uid,euid,suid,fsuid;
gid_t gid,egid,sgid,fsgid;
int ngroups; //记录进程在多少个用户组中
gid_t groups[NGROUPS]; //记录进程所在的组
//进程的权能,分别是有效位集合,继承位集合,允许位集合
kernel_cap_t cap_effective, cap_inheritable, cap_permitted;
int keep_capabilities:1;
struct user_struct *user;
struct rlimit rlim[RLIM_NLIMITS];  //与进程相关的资源限制信息
unsigned short used_math;   //是否使用FPU
char comm[16];   //进程正在运行的可执行文件名
 //文件系统信息
int link_count, total_link_count;
//NULL if no tty 进程所在的控制终端,如果不需要控制终端,则该指针为空
struct tty_struct *tty;
unsigned int locks;
//进程间通信信息
struct sem_undo *semundo;  //进程在信号灯上的所有undo操作
struct sem_queue *semsleeping; //当进程因为信号灯操作而挂起时,他在该队列中记录等待的操作
//进程的CPU状态,切换时,要保存到停止进程的task_struct中
struct thread_struct thread;
  //文件系统信息
struct fs_struct *fs;
  //打开文件信息
struct files_struct *files;
  //信号处理函数
spinlock_t sigmask_lock;
struct signal_struct *sig; //信号处理函数
sigset_t blocked;  //进程当前要阻塞的信号,每个信号对应一位
struct sigpending pending;  //进程上是否有待处理的信号
unsigned long sas_ss_sp;
size_t sas_ss_size;
int (*notifier)(void *priv);
void *notifier_data;
sigset_t *notifier_mask;
u32 parent_exec_id;
u32 self_exec_id;

spinlock_t alloc_lock;
void *journal_info;
};


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

进程的状态与task_struct结构体 的相关文章

  • 使用inotify监控文件

    我正在使用 inotify 来监视本地文件 例如使用 root temp inotify add watch fd root temp mask 删除该文件后 程序将被阻止read fd buf bufSize 功能 即使我创建一个新的 r
  • 如何像C99一样使用make和编译?

    我正在尝试使用 Makefile 编译 Linux 内核模块 obj m main o all make C lib modules shell uname r build M PWD modules clean make C lib mo
  • 如何告诉 CMake 将构建文件放在哪里?

    我想告诉 CMake 将文件和文件夹输出到不同的文件夹而不是当前文件夹 我在下面讨论的是 CMake 生成的文件 文件 CMakeCache txt 目录 CMakeFiles 文件 生成文件 目录 bin 文件 cmake install
  • python 的 fcntl.flock 函数是否提供文件访问的线程级锁定?

    Python 的 fcnt 模块提供了一种名为 flock 1 的方法来证明文件锁定 其描述如下 对文件执行锁定操作op 描述符 fd 文件对象提供 fileno 方法被接受为 出色地 请参阅 Unix 手册集群 2 了解详情 在某些系统上
  • 如何在 Linux 中制作一个将文件转换为大写的 x86 汇编程序?

    我找到了一个名为 ProgrammingGroundUp 1 0 booksize pdf 的 pdf 文件 其中一个项目是制作一个汇编程序 该程序接收文件并将其转换为大写 section data CONSTANTS system cal
  • 如何让 VSCode 在当前工作区中打开?

    我在 Linux 上使用 VSCode 我有多个 Linux 工作区 当我在新工作区中的 VSCode 中打开新文件时 它会在原始工作区中的 VSCode 中打开一个新选项卡 而不是在当前工作区中打开 VSCode 的新实例 这确实是令人讨
  • Java 内存错误:无法创建新的本机线程

    运行 java 服务器时 我在 UNIX 服务器上收到此错误 Exception in thread Thread 0 java lang OutOfMemoryError unable to create new native threa
  • copy_from_user() 错误:目标大小太小

    我正在为内核模块编写 ioctl 处理程序 我想从用户空间复制数据 当我编译禁用优化的代码时 O0 gflags 编译器返回以下错误 include linux thread info h 136 17 error call to bad
  • Centos/Linux 将 logrotate 设置为所有日志的最大文件大小

    我们使用 logrotate 并且它每天运行 现在我们遇到了一些情况 日志显着增长 阅读 gigabaytes 并杀死我们的服务器 所以现在我们想为日志设置最大文件大小 我可以将其添加到 logrotate conf 中吗 size 50M
  • 将 file.lib 构建为可在 linux 上使用的 file.a

    我正在尝试将 api 从 Windows 移植到 Linux 到目前为止 我已经完成了 file cpp 和 file h 的工作 但我仍然有一个指定给 Windows 的库 lib 这是 api 工作所必需的 我怎样才能从这个库构建一个可
  • 当下一条(跳过)指令是变量定义时,Shellcode 中的 JMP 意外行为

    Purpose 我试图利用 x86 64 中的 RIP 模式 尽管程序集本身按预期执行 但 shellcode 却没有 问题 简而言之 我尝试过的是这样的 jmp l1 str1 db some string l1 other code l
  • 检测后台操作

    在C中 检测程序在 后台模式 下调用的方法是什么 我有一个程序想要以交互方式或在后台启动 我怎样才能检测到我不应该从标准输入读取并以 已停止 tty 输入 状态结束 我应该测试 stdin 是否已关闭 我怎样才能做到这一点 编辑 isatt
  • 在 Windows 下对 Unix 下创建的文件使用 fstream::seekg

    我有一个C 跨平台程序 在Linux下用g 编译 在PC下用Visual Studio编译 该程序将行写入文本文件 使用 lt lt 运算符和std endl 但也可以从生成的文本文件中读回数据 使用std getline 为了优化数据访问
  • 导入错误:没有名为“tensorrt”的模块

    我使用 Debian 安装在我的虚拟机上安装了 TensorRT 如果我运行 dpkg l grep TensorRT 我会得到预期的结果 ii graphsurgeon tf 5 0 2 1 cuda10 0 amd64 GraphSur
  • 将任何当前目录“./”添加到Linux中的搜索路径[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 如何将任何当前目录 添加到 Linux 中可执行文件的搜索路径中 我知道这是一个旧答案 但如果其他人像我一样通过谷歌偶然发现这个问题 这里
  • “设置:非法选项 -”在一台主机上,但在另一台主机上则不然

    我在我的一台 ubuntu 虚拟机中编写了一个 sh 脚本 该脚本工作正常 但是当我尝试在其他虚拟机中运行它时 它不起作用 两个虚拟机应该相同 和bash version两个虚拟机均回复 GNU bash version 4 3 11 1
  • 如何为自定义应用程序选择静态端口号?

    我们有一个自定义应用程序 需要在其自己的端口号上处理请求 我们真的不在乎这个数字是多少 尽管我们在决定后会坚持使用该端口 如何选择最不可能与用户系统上运行的其他应用程序或服务发生冲突的数字 我们应该遵循什么规则或标准吗 澄清 一旦我们选择了
  • 如何在 Linux 中创建可通过 Screen 应用程序连接的 pty

    我想创建 C C 应用程序 它在 dev xxx 中创建新的 虚拟 设备 并且能够与 屏幕 应用程序连接 例如 循环运行的程序会创建新的 dev ttyABC 然后我将使用 屏幕 dev ttyABC 当我向那里发送一些字符时 应用程序将其
  • 从多个进程附加到单个文件的“线程安全”?

    假设我有 X 个进程打开文件 Y 进行追加 每个进程一次只写入一行 带有 n 真正的日志条目 文件 Y 中的每一行是否保证不会错误地交错 更新 本地附加文件系统 问题取决于正在进行什么类型的写入 如果您使用带缓冲的标准 I O 这通常是大多
  • 如何在bash中使用kill SIGUSR2?

    我在linux中使用iptraf来监控网络流量 shell命令是 让iptraf在后台运行 iptraf s eth0 f B L traffic dat 如果我想得到结果 我必须先停止 iptraf 所以我使用 shell 命令 kill

随机推荐

  • 使用R语言使用梯度提升算法进行预测建模

    目录 1 什么是梯度提升算法 2 梯度提升算法的步骤 3 在R中实现梯度提升算法进行预测建模
  • uniapp实现底部导航栏

    首先在pages json中找到 globalStyle 在它下面建立 tabBar 如下 tabBar color 7A7E83 selectedColor 3cc51f borderStyle black backgroundColor
  • statsmodels 无法安装

    statsmodels 安装报错 使用 whl 包也无法安装 error subprocess exited with error Getting requirements to build wheel did not run succes
  • End-to-End Human Object Interaction Detection with HOI Transformer(CVPR2021)

    基于HOI transformer进行端到端的人与物体的交互检测 介绍 这是CVPR2021年的一篇论文 主要是作者提出了一种端到端的HOI检测方法 基于Transformer结构 作者总结了以前的研究工作以及方法 基本上目前的HOI研究主
  • Transformers学习笔记5

    hugface hub上不仅有预训练模型还有数据集 下载数据集 from datasets import load dataset raw datasets load dataset glue mrpc raw datasets Datas
  • feign的用处以及替换实现请求方式的实现

    前言 处于分布式系统下的服务间的调用是如何实现的 一 feign是什么 fegin旨在简化服务间的调用实现 实现了开发人员不在关注服务间的http请求的编写 只关注与自生的业务实现 二 feign只有Java Http客户端变得更加容易这一
  • android NDK添加iconv支持,支持GBK UTF-8编码转换

    NDK自带的iconv的 查看 android ndk r9d sources android support include iconv h 在Android mk中加入 LOCAL WHOLE STATIC LIBRARIES andr
  • 使用JSP页面执行el表达式的方法

  • Kongfu Panda 英文字幕

    1 00 00 05 033 gt 00 00 21 700 Kongfu panda 2 00 00 34 300 gt 00 00 37 367 Tales of a legendary warrior 3 00 00 37 400 g
  • QML自定义时间选择器

    在进行使用qml编程过程中 需要实现日期时间的选择 但是qml官方只提供日期控件 因此自己定义了时间控件 注意 QtQuick 2 9不要降低版本 否则会有内部的信号处理器无法使用 import QtQuick 2 9 import QtQ
  • 关于测试$.getJSON获取json数据的问题

    最近在帮朋友解决 getJSON问题时遇到的情况 记录下来 希望能帮助到别人 getJSON是后去本地后者本地json数据的 首先 不管是获取网络或本地数据有问题 可以通过输出错误信息来查看原因 例如 getJSON Scripts Men
  • websocket使用原生js写法基础教程

    文章目录 1 框架图 2 具体实现 2 1 client 2 2 server 3 所有源码 4 总结 1 框架图 文件结构 2 具体实现 2 1 client 创建一个client文件夹里面创建两个目录表示两个页面一个login页面 一个
  • Build step 'Record JaCoCo coverage report' changed build result to UNSTABLE

    状况 这个异常jenkins job build黄色提示 原因就是加入了 这个打钩如下 去掉就行了 会如图1 和 min max值比较 产生unstable状态 JaCoCo plugin Thresholds JacocoHealthRe
  • Unity中的ComputeShader

    一 简介 和CPU Random MemoryAccesses 随机内存获取 不同 GPU是用平行架构处理大量的并行数据 例如vertex和fragment就是分开计算的 使用GPU并利用这种特性来进行非图形计算被称为GPGPU编程 Gen
  • delphi 发送html邮件,delphi-icv 邮件发送 -所用控件(HtmlSmtpCli).pdf

    kkaayy 的专专栏栏 ddeellpphhii iiccvv 邮邮件件发发送送 所所用用控控件件 HHttmmllSSmmttpp llii 分类 delphi 2013 12 10 16 39 30人阅读 评论 0 收藏 举报 1 界
  • Java多态机制在实际中的应用

    在实际开发工作中 常常遇到一个功能有多种实现方式 比如支付方式 有分微信支付 京东支付 支付宝 银联等支付方式 不同支付方式的大概流程大抵相似 实现细节有所区别 这个时候就可以用到java的多态机制 先定义一个公共接口 接口定义支付流程的各
  • ftp 使用笔记

    https www ngui cc el 2911341 html action onClick 启动 systemctl start vsftpd service 查看启动状态 systemctl status vsftpd servic
  • dart 学习列表 List

    List 列表 在 Dart 编程语言中 List 是一种有序的集合数据类型 用于存储一系列项目 它允许您在单个变量中存储多个项目 并提供了许多操作来管理列表中的数据 以下是关于 Dart 中的 List 的一些重要信息 创建 List 您
  • QDialog类

    QDialog类 QDialog类 api 使用方式 调用exec 槽函数 调用accept槽函数 调用reject槽函数 调用done槽函数 例子 QDialog类 QWedget类中的函数 在QDialog中都可以使用 api 构造函数
  • 进程的状态与task_struct结构体

    一 什么是进程 进程 就是程序的一个执行实例 或正在执行的程序 详细介绍请看 点击打开链接 那么进程在Linux中有几种状态呢 如下 1 R 处于运行或可运行状态 即进程正在运行或在运行队列 可执行队列 中等待 只有在该状态的进程才可能在C