进程控制块的存放和当前进程的确定

    当一个进程从用户态进入内核态,CPU自动设置该进程的内核栈,这个栈位于内核数据段上。同时,为节省空间,Linux把内核栈和一个紧挨近PCB的小数据结构thread-info放在一起,占用8KB的内存区。

    在Intel系统中,栈起始于末端,并朝这个内存区开始的方向“增长”。刚切换过来,内核栈是空的,堆栈寄存器ESP直接指向此内存区的顶端。通过找到thread-info来找到当前运行的task-struct(PCB)(,那么是怎样找到的呢?下边介绍)。

但是要注意,实际上进程的PCB所占内存是由内核动态分配的,更确切的说,内核根本不给PCB分配内存,而仅仅给内核栈分配8KB的内存,并把其中的一部分让给PCB使用。

 

    因为thread-info结构和内核栈放在一起,内核就很容易从ESP寄存器的值获取当前在CPU上正在运行的thread-info结构的地址。实际上,如果thread-union结构(即内核栈和thread-info联合组成的一个混合结构)长度为8KB(2^13字节),则内核通过屏蔽ESP寄存器的的低13位有效位就可以获得thread-info结构的基地址;这可以由current-thread-info()函数来完成。而其实进程最常用的是task-struct结构的地址而不是什么thread-info结构的地址,于是为了获得当前CPU上运行进程的PCB指针 ,内核需要调用current宏,该宏本质上等价于current-thread-info()->task。同时对于当前进程父进程的PCB可通过下面代码获得。

struct task_struct *my_parent = current->parent;

 

#define pid_hashfn(x) ((((x) >> 8) ^ (x)) & (PIDHASH_SZ – 1))

 

posted @ 2013-07-24 14:47  herry_tu  阅读(1253)  评论(0编辑  收藏  举报