您的位置:首页 > 运维架构 > Linux

Linux进程(Linux内核设计与实现学习笔记)

2015-05-26 21:39 387 查看
1. 进程描述符和任务结构

内核把进程的列表放在叫做任务队列(task list)的双向循环队列中,链表中的每一项都是一个类型位task_struct、称为进程描述符(process descriptor)的数据结构,该结构定义在<linux/sched.h>中,进程描述符包括了进程所有的信息,包括打开的文件、进程地址空间、进程状态,还有其他更多信息(如下图所示)。



2.分配进程描述符

Linux通过slab分配器分配task_struct结构,这样能达到对象复用和缓存着色的目的。内存中普通对象的初始化时间超过了对其进行分配和释放所需的时间,因此不应该将内存释放回一个全局的内存池,而是将内存保持为针对特定目的而初始化的状态,后续的内存分配不需要执行这个初始化函数,因为从上次释放和调用析构之后,它已经处于所需的状态中了。Linux
slab 分配器使用了这种思想和其他一些思想来构建一个在空间和时间上都具有高效性的内存分配器。slab分配器由物理上一个或几个连续的页组成,一般情况下,也就由一个页组成。每个slab对象中包括了一些被缓存的数据结构,slab处于三种状态:满、部分满和空。当内核需要一个新的对象时,先从部分满的slab中进行分配,如果没有部分满的就从空的slab中分配,若是没有空的slab就创建一个新的slab。这种策略能减少碎片。



slab分配task_struct时,只需在栈底(向下增长的栈)或栈顶(向上增长的栈)创建一个新的结构struct thread_info。通过预先分配和重复使用task_struct,可以避免动态分配和释放所带来的开销。


     
     


3. 进程描述符的存放

在内核中,访问任务通常需要获得其指向task_struct的指针,因此通过current宏查找到当前正在运行进程的进程描述符的速度就尤为重要。对于X86结构,只能在内核栈的尾端创建thread_info结构,通过计算偏移间接地查找task_struct。current把栈指针后13位有效位屏蔽掉,用来计算thread_info的偏移。该操作是通过current_thread_info()函数实现的,汇编代码如下:

movl $-8192, %eax

andl %esp, %eax

这里假设栈的大小是8K,若是4K,就用4096。(-8129=2的32次方减去8192就是二进制的11111111111111111110000000000000。这就是-8192在内存中的存储。这个值再与上 $sp
就是只保留上面的19位,也就是-8k也就是两页的最低地址)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux 操作系统 进程