linux源码剖析 | 进程(task)数据结构 上

本文详细介绍了Linux内核中进程(任务)的管理,包括任务ID的区分、信号处理机制及其对栈的影响,以及任务的各种状态如运行、睡眠和停止。还探讨了任务调度的原理,特别是不同睡眠状态的响应特性。对于理解Linux系统底层运作十分有益。
摘要由CSDN通过智能技术生成

目录

任务 ID

信号处理

任务状态

进程调度


标题写进程主要是为了引流吧。

在 Linux 里面,无论是进程,还是线程,到了内核里面,我们统一都叫任务(Task)。由一个统一的结构 task_struct 进行管理。

 

Linux 内核有一个链表,将所有的 task_struct 串起来。

struct list_head    tasks;

任务 ID

task_struct 里面涉及任务 ID:

pid 是 process id

tgid 是 thread group ID。

如果只有主线程: pid 是自己,tgid 是自己,group_leader 指向的还是自己。

同一个进程多个线程的话:线程有自己的 pid,tgid 就是进程的主线程的 pid,group_leader 指向的就是进程的主线程

信号处理

task_struct 里面关于信号处理的字段

定义了哪些信号被阻塞暂不处理(blocked),哪些信号尚等待处理(pending),哪些信号正在通过信号处理函数进行处理(sighand)。处理的结果可以是忽略,可以是结束进程等等。

信号处理函数默认使用用户态的函数栈,也可以开辟新的栈专门用于信号处理,这就是 sas_ss_xxx 这三个变量的作用。

  1. sigpending

task_struct 里面有一个 struct sigpending pending

struct signal_struct *signal里有struct sigpending shared_pending

它们一个是本任务的,一个是线程组共享的。

任务状态

task_struct 里面,涉及任务状态的变量:

 

state(状态)可以取的值定义在 include/linux/sched.h 头文件中,state 是通过 bitset 的方式设置的:

 

TASK_RUNNING 并不是说进程正在运行,而是表示进程在时刻准备运行的状态。

当处于这个状态的进程获得时间片的时候,就是在运行中;如果没有获得时间片,就说明它被其他进程抢占了,在等待再次分配时间片。

在运行中的进程,一旦要进行一些 I/O 操作,需要等待 I/O 完毕,这个时候会释放 CPU,进入睡眠状态。

 

  1. 种睡眠状态
  1. TASK_INTERRUPTIBLE,可中断的睡眠状态

是一种浅睡眠的状态,也就是说,虽然在睡眠,等待 I/O 完成,但是这个时候一个信号来的时候,进程还是要被唤醒

不过唤醒后,是进行信号处理,不是继续刚才的操作。程序员可以根据自己的意愿,来写信号处理函数,例如收到某些信号,就放弃等待这个 I/O 操作完成,直接退出;或者收到某些信息,继续等待。

  1. TASK_UNINTERRUPTIBLE,不可中断的睡眠状态

是一种深度睡眠状态,不可被信号唤醒,只能死等 I/O 操作完成。一旦 I/O 操作因为特殊原因不能完成,这个时候,谁也叫不醒这个进程了。

kill 本身也是一个信号,既然这个状态不可被信号唤醒,kill 信号也被忽略了。除非重启电脑,没有其他办法。

  1. TASK_KILLABLE,可以终止的新睡眠状态

它的运行原理类似 TASK_UNINTERRUPTIBLE,只不过可以响应致命信号。

TASK_STOPPED 是在进程接收到 SIGSTOP、SIGTTIN、SIGTSTP 或者 SIGTTOU 信号之后进入该状态。

TASK_TRACED 表示进程被 debugger 等进程监视,进程执行被调试程序所停止。当一个进程被另外的进程所监视,每一个信号都会让进程进入该状态。

EXIT_ZOMBIE:一旦一个进程要结束,先进入的是 EXIT_ZOMBIE 状态,但是这个时候它的父进程还没有使用 wait() 等系统调用来获知它的终止信息,此时进程就成了僵尸进程

EXIT_DEAD 是进程的最终状态。

EXIT_ZOMBIE 和 EXIT_DEAD 也可以用于 exit_state。

还有其他的一些状态,称为标志。放在 flags 字段中,这些字段都被定义成为,以 PF 开头

 

PF_EXITING 表示正在退出。当有这个 flag 的时候,在函数 find_alive_thread 中,找活着的线程,遇到有这个 flag 的,就直接跳过。

PF_VCPU 表示进程运行在虚拟 CPU 上。在函数 account_system_time 中,统计进程的系统运行时间,如果有这个 flag,就调用 account_guest_time,按照客户机的时间进行统计。

PF_FORKNOEXEC 表示 fork 完了,还没有 exec。在 _do_fork 函数里面调用 copy_process,这个时候把 flag 设置为 PF_FORKNOEXEC。当 exec 中调用了 load_elf_binary 的时候,又把这个 flag 去掉。

进程调度

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值