linux之运行状态(2),内核链表与进程状态

1.linux的内核链表(为什么一个进程可以在多个数据结构的原因)

1.不同于传统的直接给每一个结点直接设计_next和_prev指针,内核中将_next和-prev指针封装成一个独立的结构体并封装在每一个结点中。

也就是每一个指针的结构体指向的是对方的结构体而非整个结构体本身,也就是功能从指向整体到指向局部成员了。

有struct的成员地址从上往下依次增大且struct的地址与第一个成员的地址在大小上相同。

取整个struct成员的方式:

复制代码
//links代表的是该指针结构体的变量名的统称,
//此处计算的是links到结构体第一个成员地址的偏差值(offset)
((struct task_struct*)0->links)
//_next/list,其中list代表的是头结点存的地址,
//_next指的是下第一个结点的地址
//二者相减得到该结构体的空间开始地址
_next/list - &((struct task_struct*)0->links)
//强转类型得对应类型的指针
(struct task_struct*)(_next/list - &((struct task_struct*)0->links));

而一个进程中可以创建很多个struct list_head,用不同的变量名表示区分就可以将该进程连接到不同的数据结构中。

因此进程能同时在双链表和调度队列的与原因就是二者的struct list_head不同。

2.linux的进程状态

linux中的进程状态是存在一个字符数组中的:

复制代码
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 */
};

(1)

复制代码
//&可以将该进程放在后台运行
(可执行程序).exe &
//proc中的STAT的状态显示中的状态有+好代表在前台运行,没有代表在后台运行。

例:

复制代码
//前台运行 
2361  2709  2709  2361 pts/0     2709 R+       0   0:00 ps axj
//后台睡眠
 1209 14595  1209  1209 ?           -1 S       89   0:00 pickup -l -t unix -u

(2)

t是暂停,例:debug下的断点(即进程被暂停了)

T也是暂停,例:进程运行时用户用ctrl+z强制暂停时的状态就为T,还有以一种情况就是OS认为该进程有问题但需要用户来决定是否需要中止该进程时的暂停也是T。(给用户作决策时处于的暂停状态)

(3)

s和D都是阻塞状态,只是s是浅睡眠,而D是深睡眠。

(4)

x就是死亡状态。

(5)

z:僵尸状态。(x,z都算是结束状态)

介绍:我们创建子进程的目的是为了让子进程完成某种事情,而父进程就需要得到子进程的相关信息,因此在子进程被杀死前给父进程传输数据时的状态就叫僵尸进程。

子进程结果的相关信息存在task_struct中,即子进程的数据和代码别删除了其的task_struct还会存在一段时间依然其他进程读取。

如果父进程一直不管,不回收,不获取子进程发出的信息,那么该子进程的尸体就会一直存在。(也就是内存会被一直占用发生内存泄漏)

(6)

挂起状态,用户不关心,OS也不会提供呈现。

当进程退出时,内存会被OS回收,自然不存在内存泄漏的问题。

3.内核结构的资源申请

每一个PCB的创建就要malloc一块空间,不用时就释放,但当下次使用时又要重新malloc,对于PCB这种会被大量使用的资源。OS采用了对处于x状态的PCB用一个叫unuse的链表进行管理存储,当OS想要新的PCB时就将unuse的旧PCB更新一下后再使用。这种也叫数据结构对象的缓存(slab)

孤儿进程:父子关系中,如果父进程先退出,子进程就会被1号进程领养,这个被领养的子进程的状态就是孤儿进程。(系统就是1号进程,叫systemd)

领养的目的是为了保证子进程能顺利从僵尸进程中死去且领养后很快就变成了后台进程了(即无法用ctrl+c杀死该进程,只能kill -9 指定杀死了)

相关推荐
硬核子牙4 小时前
代码展示大模型的智能
linux·chatgpt·agent
清水白石0084 小时前
Python 类定义阶段自动注册子类:从 `__init_subclass__` 到插件系统实战
linux·前端·python
jiang_changsheng5 小时前
Conda 的默认环境创建优先级。
linux·windows·python
smallerxuan5 小时前
Linux 设备树(Device Tree)概览
linux·设备树·dts
Mortalbreeze5 小时前
深入理解 Linux 线程机制(四):线程同步——条件变量与信号量
linux·运维·服务器·开发语言·c++
Huangjin007_5 小时前
【Linux 系统篇(一)】入门基础指令详解(一)
linux·服务器
嵌入式小能手5 小时前
飞凌嵌入式ElfBoard-i2c与从设备通讯编程示例之i2c设备通信编程示例
linux
mounter6255 小时前
现代 Linux 内核中的数据持久化艺术:从回写(Writeback)到多样化写策略
linux·linux kernel·kernel·writeback·writethrough
会飞的小新6 小时前
《深入理解 DDR Memory Margin》系列之第一章:从 DDR 到 Memory Margin——为什么服务器需要进行内存裕量测试?
linux·服务器
治愈系贝壳6 小时前
ARM ---day1
linux·arm开发·学习