加入收藏 | 设为首页 | 会员中心 | 我要投稿 辽源站长网 (https://www.0437zz.com/)- 云专线、云连接、智能数据、边缘计算、数据安全!
当前位置: 首页 > 服务器 > 搭建环境 > Windows > 正文

从C语言源代码分析,神秘的Linux系统是如何记录和描述进程的?

发布时间:2019-08-03 07:40:07 所属栏目:Windows 来源:嵌入式时代
导读:上一节简要讨论了下Linux操作系统中进程的概念,其实简单来说,进程无非就是处于运行期的程序及其相关资源的总和。这里读者应该注意相关资源一词,Linux 在内核中是如何记录进程的资源的呢? Linux内核如何记录进程的资源? 首先应该明白,Linux 内核大都是
副标题[/!--empirenews.page--]

上一节简要讨论了下Linux操作系统中进程的概念,其实简单来说,进程无非就是处于运行期的程序及其相关资源的总和。这里读者应该注意“相关资源”一词,Linux 在内核中是如何记录进程的资源的呢?

从C语言源代码分析,神秘的Linux系统是如何记录和描述进程的?

Linux内核如何记录进程的资源?

首先应该明白,Linux 内核大都是采用C语言编写的,因此要弄清楚内核如何记录进程资源,只需要查看相关的C语言代码就可以了。事实上,Linux 内核是使用 task_struct 结构体描述进程的资源的,它的C语言部分代码如下,请看:

从C语言源代码分析,神秘的Linux系统是如何记录和描述进程的?

task_struct 结构体很长

task_struct 结构体很长,在我手中的 Linux 内核C语言源代码中,它占用了280行。当然了,这其中包含很多条件编译部分,在 32 位机器上,task_struct 大约要占用 1.7 KB 的内存空间,不过考虑到它可以管理完整的进程,1.7kB 其实并不算大了。

鉴于 task_struct 结构体过长,这里不可能将其成员一一介绍清楚。如果读者和我一样好奇,粗略的浏览 task_struct 结构体,应该能够发现一些比较令人熟悉的成员,例如:

从C语言源代码分析,神秘的Linux系统是如何记录和描述进程的?

task_struct 结构体令人熟悉的成员

通过C语言注释以及成员的变量名,能够看到 task_struct 结构体包含了文件系统,线程结构体,以及进程打开的文件等信息,这就与上一节文章的内容对应上了。其他成员在我之后的文章中会涉及到,这里暂不赘述。

在创建进程时,Linux 通过 slab 分配器分配 task_struct 结构,这样可以避免动态分配和释放带来的开销,提高内存的使用效率。

那么创建 task_struct 结构后,内核如何访问它呢?

根据我手上的内核C语言源代码,Linux 中还有一个结构体 thread_info,它的其中一个成员 task 指针正好适合用于索引 task_struct 结构体,在X86_64平台上,thread_info 的相关C语言代码如下,请看:

从C语言源代码分析,神秘的Linux系统是如何记录和描述进程的?

task 指针

Linux 通常会在内核栈底或者栈顶保留 thread_info 结构,而内核栈通常大小都是可知的,因此每个进程都能方便的从自己的栈中找到 thread_info 结构,进而找到 task_struct 结构。

查找当前进程的 thread_info 结构,可以调用 current_thread_info() 函数,它的C语言代码如下,请看:

  1. static inline struct thread_info *current_thread_info(void) 
  2. {  
  3.  register unsigned long sp asm ("sp");  
  4.  return (struct thread_info *)(sp & ~(THREAD_SIZE - 1)); 
  5. }    
从C语言源代码分析,神秘的Linux系统是如何记录和描述进程的?

current_thread_info() 函数

可见,current_thread_info() 函数其实就是通过进程栈计算的,因此它的实现与平台架构有关,上述C语言代码其实只是 arm 平台的实现方法,其他平台的实现方法,读者可自行查阅。

此时,要获取当前进程的资源,可以通过 current_thread_info()->task 索引。

进程 PID

Linux 内核为每一个进程分配独一无二的进程标识(process identification,PID)用于区分不同的进程。PID 是一个整数,在内核的C语言源码中表示为 pid_t 类型(其实就是 int 类型)。在Linux命令行输入 ps 命令,即可查看进程的 PID,例如:

从C语言源代码分析,神秘的Linux系统是如何记录和描述进程的?

查看进程的 PID

task_struct 结构体使用成员 pid 记录进程的 PID 值,相关的C语言代码如下,请看:

从C语言源代码分析,神秘的Linux系统是如何记录和描述进程的?

task_struct 结构体使用成员 pid 记录进程的 PID 值

在Linux系统中,PID 的最大值是可以调整的,早期为了兼容老版本的 Unix 和 Linux,默认最大值为 32768(short int 类型能够表示的最大值),这个值可以通过 cat 命令查看:

  1. # cat /proc/sys/kernel/pid_max  
  2. 32768 

PID 的最大值对于Linux系统的运行是有影响的,因为 PID 值是独一无二的,所以它的最大值实际上就表示系统可以同时运行的最多进程数目。对于普通的个人用户来说,32768 足够多,但是对于大型服务器来说,32768 可能就远远不够了,这时可以修改 pid_max 解决这一问题。

进程的状态

现在知道了Linux内核是如何描述和记录进程资源,以及如何区分不同进程的了。那么进程有哪些状态呢?读者应该注意到 task_struct 结构体的第一个成员 state 了,它就是用于记录进程状态的。进程的状态在C语言源代码中是使用几个宏定义的:

从C语言源代码分析,神秘的Linux系统是如何记录和描述进程的?

进程的状态在C语言源代码中是使用几个宏定义的

(编辑:辽源站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读