linux内核数据结构--进程相关
linux里面,有一个结构体task_struct,也叫“进程描述符”的数据结构,它包含了与进程相关的所有信息,它非常复杂,每一个字段都可能与一个功能相关,所以大部分细节不在我的研究范围之内,在这篇文章里面只讲述这些数据结构的组织方式,相当于一个知识点的大的梗概或骨架,如果骨架搞明白了,那么内部的细节就可以抽丝剥茧,搞明白也非难事。
一,链表
很简单,上面所说的进程描述符以双向链接的形式组织起来,说起来很简单,但还是有一些特色在里面的
1,在Linux内核链表中,不是在链表结构中包含数据,而是在数据结构中包含链表节点。
在内核中定义了list_head的一个数据结构,struct list_head { struct list_head *next, *prev;}; 它只含有两个字段。它就组织成了一个没有数据域的双向链表,通过在task_struct中包含一个list_head数据结构,实现了task_struct的双向链接。
但是,list_head的指针只是指向list_head自己的地址,怎样通过list_head指针,来获取task_struct的地址呢?方法如下:
#define list_entry(ptr, type, member) container_of(ptr, type, member)
#define container_of(ptr, type, member) ({ const typeof( ((type *)0)->member ) *__mptr = (ptr);
(type *)( (char *)__mptr - offsetof(type,member) );})
#define offsetof(type, member) ((size_t) &((type *)0)-> member)
解释如下:
通过定义一个task_struct指针p,其地址指向0,然后获取p->list_head的地址,就可以获取list_head在task_struct中的偏移量,这应该是个常量。然后就用list_head的地址减去这个常量 ,就得到了task_struct的地址。
参考文献:http://www.cnblogs.com/Daniel-G/archive/2013/09/06/3305834.html

2,140个优先权队列
进程的优先权有140个,为了调度的需要,内核就组织了140个链表,每个链表代表一个优先权。这通过在task_struct中包含一个list_head字段来实现。
所有的这些链接通过一个prio_array_t的数据结构实现。如下,在里面我们看到了bitmap位图数据结构的使用。

3,等待队列
进程经常等待某些事件的发生,例如等待一个磁盘操作的终止。
当进程等待一些资源时,内核就将这个进程放到此资源对应的等待队列中。
二,哈希表
以链表的形式组织task_struct数组,特点就是灵活。但如果想通过PID获取到对应的task_struct的地址,仅仅使用链表还是不够的,O(1)神器hash_table可以解决这个问题。
内核初始化时,动态的创建4个哈希表,如下:

哈希表就不多说了,下面简单的说一下TGID哈希表的结构,如下图。
举例说明,例如现在内核要回收TGID=4351的所有进程,那么我们立即就可以得到TGID=4351的进程所在的位置,一般情况下,我们通过哈希表只得到一个节点,但内核的哈希表扩展了一下,就是将TGID=4351的所有进程都链接到一个链表中,那么遍历链表就可以获取TGID=4351的所有进程了。

三,位图
1,每个进程对有一个唯一标记PID,默认情况下最大的PID号是32767,但这个值可以更改,那么怎么做到循环使用PID呢,内核通过一个pidmap_array位图来表示当前已经分配的PID号的闲置的PID号。也就是用32767个bit就可以解决这个问题。
2,上面所讲到的优先权队列中也有bitmap的使用,用5个unsigned long型,也就是160个bit完全可以满足140个优先权的使用。
读完《深入理解linux内核》第三章后,所学到的就是上面的内容。读得也不够深入,人为的忽略了很多细节的阅读,因为我的目标也不在于细节。
有两点感受:
1,感觉内核所用的数据结构也就是我们平常使用的到的数据结构。
2,内核把性能放在了第一位,有时候可以拿一些空间来换取时间,例如上面所讲到的hash表,TGID=4351和TGID=246的所有进程完全可以放在一个链表中,然后通过遍历来拿到TGID=4351的进程,但内核还是将它们分开,代价就是需要在每一个task_struct中再增加一对指针。
linux内核数据结构--进程相关的更多相关文章
- 24小时学通Linux内核之进程
都说这个主题不错,连我自己都觉得有点过大了,不过我想我还是得坚持下去,努力在有限的时间里学习到Linux内核的奥秘,也希望大家多指点,让我更有进步.今天讲的全是进程,这点在大二的时候就困惑了我,结果那 ...
- (笔记)Linux内核中内存相关的操作函数
linux内核中内存相关的操作函数 1.kmalloc()/kfree() static __always_inline void *kmalloc(size_t size, gfp_t flags) ...
- 深入Linux内核架构——进程管理和调度(上)
如果系统只有一个处理器,那么给定时刻只有一个程序可以运行.在多处理器系统中,真正并行运行的进程数目取决于物理CPU的数目.内核和处理器建立了多任务的错觉,是通过以很短的间隔在系统运行的应用程序之间不停 ...
- Linux内核之进程地址空间
Linux内核之进程地址空间 内核中的函数以相当直接了当的方式获得动态内存: __get_free_pages 或 alloc_pages从分区页框分配器中获得页框; kmem_cache_alloc ...
- (转)Linux内核之进程和系统调用
Linux内核之进程和系统调用 什么是系统调用 在Linux的世界里,我们经常会遇到系统调用这一术语,所谓系统调用,就是内核提供的.功能十分强大的一系列的函数.这些系统调用是在内核中实现的,再通过一定 ...
- linux内核数据结构之链表
linux内核数据结构之链表 1.前言 最近写代码需用到链表结构,正好公共库有关于链表的.第一眼看时,觉得有点新鲜,和我之前见到的链表结构不一样,只有前驱和后继指针,而没有数据域.后来看代码注释发现该 ...
- 分析Linux内核中进程的调度(时间片轮转)-《Linux内核分析》Week2作业
1.环境的搭建: 这个可以参考孟宁老师的github:mykernel,这里不再进行赘述.主要是就是下载Linux3.9的代码,然后安装孟宁老师编写的patch,最后进行编译. 2.代码的解读 课上的 ...
- linux内核数据结构学习总结
目录 . 进程相关数据结构 ) struct task_struct ) struct cred ) struct pid_link ) struct pid ) struct signal_stru ...
- Linux内核分析--进程创建,执行,切换
学号:351 原创作品转载请注明出处本实验来源 https://github.com/mengning/linuxkernel/ 实验要求 从整理上理解进程创建.可执行文件的加载和进程执行进程切换,重 ...
随机推荐
- JavaScript学习总结【11】、JS 运动
动画效果在网站中是一种非常常见的交互式体验效果,比如侧边栏分享.图片淡入淡出,我们把这种动画效果就叫做运动,也就是让物体动起来.如果想让一个物体动起来,无非就是改变它的速度,也就是改变属性值,比如 l ...
- 在 Linux 命令行中使用和执行 PHP 代码
PHP是一个开源服务器端脚本语言,最初这三个字母代表的是“Personal Home Page”,而现在则代表的是“PHP:Hypertext Preprocessor”,它是个递归首字母缩写.它是一 ...
- centos下redis安装
下载redis http://www.redis.cn/download.html 下载php的redis扩展 https://github.com/phpredis/phpredis#install ...
- ubuntu导出文件
ye@aliyun:python$ ./deploy.sh backup static-rw-r--r-- 1 ye ye 174K 2014-03-22 10:36 ./backup/fbz_sta ...
- Xcode 修改工程名称
总会遇到几个项目,在做到一半的时候被要求改项目名,网上找了下相关的资料,大多数是xcode5以前的版本,所以解决好了在这里mark一下,给需要的人. 目标为:将项目名XCD4改成xcd5. 先上结果图 ...
- XCode 项目配置说明
初学XCode最让人头疼的就是项目各属性设置,各种不解,这里做个总结: 项目配置: 基本项(Basic) 1.Architectures(指令集)——设置你想支持的指令集,目前ios的指令集有以下几种 ...
- 实际中理解div布局和浮动
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- 240多个jQuery插件
概述 jQuery 是继 prototype 之后又一个优秀的 Javascript 框架.其宗旨是—写更少的代码,做更多的事情.它是轻量级的 js 库(压缩后只有21k) ,这是其它的 js 库所不 ...
- 【BZOJ 1319】 Sgu261Discrete Rootsv (原根+BSGS+EXGCD)
1319: Sgu261Discrete Roots Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 389 Solved: 172 Descriptio ...
- Android用户界面 UI组件--TextView及其子类(四) Chronometer计时器
Chronometer是一个简单的定时器,你可以给它一个开始时间,并以此定时,或者如果你不给它一个开始时间,它将会使用你的时间通话开始.默认情况下它会显示在当前定时器的值的形式“分:秒”或“H:MM: ...