进程描述符是用来在操作系统中标识一个进程的
slab机制的linux进行进程描述符分配的一种机制。
比如土司面报被切成很多片,每一块就是slab.
内存区间通过动态分配机制分配下来,这个区间按照一定的结构尺寸切成若干份,在使用时就在若干份存储区间中去申请,每次去分配一块,每块对应的就是具体应用的数据结构的尺寸;应用在进程描述符时,每个slab的尺寸就是进程描述符的尺寸。
Linux为什么用这种机制而不是使用动态分配内存呢?
针对资源要被频繁使用归还的使用slab机制就可以提升很大的效率
2.6内核之前,在每个进程内核栈末端来分配。
总结:
linux进程状态没有 就绪 这个状态 ;就绪 和 执行 状态都是 TASK_RUNNING;就绪到执行需要通过调度的方式进行上下文切换linux中某个进程(任务 task)发生了睡眠,或者在某个队列中等待某些资源,就要进入TASK_INTERRUPTIBLE;就是阻塞状态。linux中,进程消亡时释放了代码空间,数据空间等,但在内核中的资源是没有释放的,比如进程描述符;所以linux提供了一个僵死的状态。进程在Linux中创建是父子的关系,父进程创建子进程后,子进程执行完毕后,父进程是需要知道子进程是否终止以及以什么方式终止等状态信息的,linux的设计理念是进程终止之后会对父进程发送一个信号,告诉他我这个进程已经结束了,这是父进程可以通过系统提供的数据结构(比如子进程的进程描述符)来获取子进程执行过程中的状态信息,直到父进程觉得没必要保留这个信息时会通知内核,让内核把这个子进程的数据都释放掉。
设置进程的状态:
<linux/sched.h>中
set_task_state(task,state);
task->state=state;
更清晰的一个
进程上下文指的是整个进程和他相关的自身的和周围环境的整个场景是什么。
一个进程的代表是进程描述符
疑问1:可执行代码是如何组织的?疑问2:相关的数据如何组织?用户空间与内核空间
用户进程在哪个空间?是否进入内核空间?如何进入内核空间?用户的代码是不能进入到内核空间去执行的,也不能访问内核空间的数据,但可以通过系统调用与内核发生关系。这个系统调用是在内核空间执行的,而它代表的是当前的这个进程,所以进程上下文仍然是当前的进程上下文。
copy-on-weite:
原因:大多数时子进程都不需要父进程的那些代码和资源,但fork()是直接父进程创建出一个和自己一摸一样的子进程,所以如果创建时直接把自己的代码段和数据段复制一份出来是效率很低的。
策略:当子进程被创建出来时,它可以共享父进程的代码段和数据段,当子进程要对这块共享的内存进行写操作时,再进行拷贝操作。这就是一种延迟的拷贝策略,这样就最大限度的保证了创建进程的执行效率。
fork()--调用--clone()--调用--do_fork()--调用--copy_process()
除了写时拷贝还有个优化拷贝的策略
关于僵尸进程和孤儿进程有一个不错的总结:
https://www.cnblogs.com/Anker/p/3271773.html