linux进程学习-进程描述符的存储
当进程被新建时,内核会给进程分配一个8K的空间作为进程的内核堆栈。同时我们知道task_struct结构体也会被创建,但有意思的是,内核不会给task_struct单独分别空间,而是直接将其扔到8k的内核堆栈中,与内核堆栈共享这8K内存。 假设我们用如下结构表示进程描述符和内核堆栈: struct task_struct task; unsigned long stack [INIT_TASK_SIZE/sizeof(long)]; 那么我们很容易将其做成一个联合体: union task_union { struct task_struct task; unsigned long stack[INIT_TASK_SIZE/sizeof(long)]; }; 实际上,进程创建时内核会分配2个连续的页面(8192byte),将其底部大约1k(960byte)的空间拿来存放进程描述符(task_struct),上部大约7k(7232byte)的空间拿来作为内核堆栈。(更多,参考这里和这里) 内核不会让内核堆栈超出7232byte,否则会覆盖task_struct而导致错误。 在内核空间(kernel space)中,有一个专门的全局数组来保存所有的进程描述符(指针),数组条目就是上面的task_union的指针, 这个数组称为Task Array。 很明显的一个问题:pid的最大值是32767,而系统允许的最大进程数是512,如果用pid作为Task Array的索引而将数组大小设为32768的话,数组空间上存在明显的浪费。实际上Task Array的实际大小是系统允许的最大进程数,而内核采用了一些其他的算法(???)将进程描述符分布到数组中去。 现在,如果我们想遍历系统中所有的进程,由于一般情况下Task数组中的大多数元素都是空的,所以下面的代码是低效的: for ( i=; i<NR_TASKS; i++ ) { if (task[i]) //do something } 为此,task_struct结构体中加了如下字段:struct task_struct *next_task, *prev_task; 分别指向上一个进程和下一个进程,那么所有进程在连接在一起便形成了一个双向循环链表(double circular linked list),这样的遍历就变得高效了。该链表的头和尾都始终是init进程,因为init进程是长期存在的,这能保证链表一直有效。 随着进程的创建,我们需要在Task数组中找到空闲位置而将新进程插入进去。遍历Task数组的方式是可行却低效的,一个很简单的方式是准备一个堆栈(数据结构上的stack),让栈持有Task数组空闲位置的指针。当你需要插入新元素Task数组时,弹出栈顶元素供你使用便可;当你从Task数组中删除元素后,将该空闲位置压栈以便下次使用。而这个栈,就是linux中的tarray_freelist (自由时间列表) 试想如下case,进程p1要kill进程p2: p1: kill - pidOfP2 此时系统如何通过p2的PID找到p2的进程描述符?遍历task数组或遍历task_struct形成的双向循环链表都是低下的。 快速查找的一个简单方案是散列表(hash table),这个散列表称为pidhash,该表以pid为键(key),以指向pid对应的进程描述符的指针为值(value)。散列算法为: #define pid_hashfn(x) ((((x)>>8) ^ (x)) & (PIDHASH_SZ-1)) 其中PIDHASH_SZ为系统定义的此散列表的大小。 pidhash解决碰撞(冲突,colliding)的算法是“链接表法” (扩展, 其实效率最高的做法是直接通过pid做索引而用普通数组,只所以用散列表,道理和Task数组一样:节约空间)
linux进程学习-进程描述符的存储的更多相关文章
- Linux中的文件描述符与打开文件之间的关系
Linux中的文件描述符与打开文件之间的关系 导读 内核(kernel)利用文件描述符(file descriptor)来访问文件.文件描述符是非负整数.打开现存文件或新建文件时,内核会返回一个文件描 ...
- Linux中的文件描述符与打开文件之间的关系------------每天进步一点点系列
http://blog.csdn.net/cywosp/article/details/38965239 1. 概述 在Linux系统中一切皆可以看成是文件,文件又可分为:普通文件.目录文件. ...
- (转)Linux中的文件描述符
本文转自:http://blog.csdn.net/cywosp/article/details/38965239 作者:cywosp 1. 概述 在Linux系统中一切皆可以看成是文件,文件又可分为 ...
- (转)Linux中的文件描述符与打开文件之间的关系
转:http://blog.csdn.net/cywosp/article/details/38965239 1. 概述 在Linux系统中一切皆可以看成是文件,文件又可分为:普通文件.目录文 ...
- Linux exec与文件描述符
看到好几篇文章讲述exec都是一知半解,所以我尽量说的清楚明白一些.本文首先讲述Linux文件描述符,然后是exec,最后举例说明exec I/O重定向及其用法. 概念:exec命令用于调用并执行指令 ...
- Linux Linux下最大文件描述符设置
Linux下最大文件描述符设置 by:授客 QQ:1033553122 1. 系统可打开最大文件描述符设置 查看系统可打开最大文件描述符 # cat /proc/sys/fs/file-max 6 ...
- [svc]linux中的文件描述符(file descriptor)和文件
linux中的文件描述符(file descriptor)和文件 linux为了实现一切皆文件的设计哲学,不仅将数据抽象成了文件,也将一切操作和资源抽象成了文件,比如说硬件设备,socket,磁盘,进 ...
- linux fcntl 对文件描述符控制
linux fcntl 对文件描述符控制 linux fcntl 对文件描述符控制 linux fcntl 对文件描述符控制
- linux进程学习-进程描述符,控制块
从数据结构的角度,进程用task_struct结构来描述,称为“进程描述符 (Process Descriptor)”或者“进程控制块(Process Control Block, PCB)”,其包含 ...
随机推荐
- java equals与==区别
java中的数据类型,可分为两类: 1.基本数据类型,也称原始数据类型.byte,short,char,int,long,float,double,boolean 他们之间的比较,应用双等号(== ...
- qrCode生成二维码图片
QRCode.js 是一个用于生成二维码图片的插件. 1.文件脚本 var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,th ...
- Javascript模式(三) 策略模式
var data = { "username" : "zhangsan", "password" : "12345690" ...
- 【Android应用开发详解】实现第三方授权登录、分享以及获取用户资料
由于公司项目的需要,要实现在项目中使用第三方授权登录以及分享文字和图片等这样的效果,几经波折,查阅了一番资料,做了一个Demo.实现起来的效果还是不错的,不敢独享,决定写一个总结的教程,供大家互相 ...
- Redis专题(2):Redis数据结构底层探秘
前言 上篇文章Redis闲谈(1):构建知识图谱介绍了redis的基本概念.优缺点以及它的内存淘汰机制,相信大家对redis有了初步的认识.互联网的很多应用场景都有着Redis的身影,它能做的事情远远 ...
- jQuery Validate(三)
这里,我们再说说radio.checkbox.select的验证方式. 1.用新版的写法进行验证. <!DOCTYPE html> <html> <head> &l ...
- 在diy的文件系统上创建文件的流程
[0]README 0.1) source code are from orange's implemention of a os , and for complete code , please v ...
- Jquery datepicker的使用
1. 设定初始日期 $("#<%=txtStart.ClientID %>").datepicker("setDate", start); 2. 设 ...
- linux c编程:文件的读写
Linux系统中提供了系统调用函数open()和close()用于打开和关闭一个存在的文件 int open(const char *pathname,int flags) int open(cons ...
- git版本控制-- Windows+Git+TortoiseGit+COPSSH安装图文教程
Windows+Git+TortoiseGit+COPSSH 安装图文教程 教程网址: http://www.liaoxuefeng.com/wiki/0013739516305929606dd183 ...