Linux内核设计与实现——第三章进程管理

最近在Linux的进程,很多文章看了之后并不是很完整,决定潜心看Linux内核的一些设计。

 

1、Linux系统的线程实现非常特别:它对线程进程不特别区分。对Linux而言,只不过是一种特殊的进程罢了。

2、进程提供两种虚拟机制:虚拟处理器虚拟内存

3、在现代的Linux内核中,fork()实际上是由clone()系统调用实现的。

4、内核把进程的列表存放在叫做任务队列双向循环链表中。链表中的每一项都是类型为task_struct(/usr/src/)、称为进程描述符的结构,该结构定义在中。进程描述符中包含一个具体进程的所有信息。

5、Linux通过slab分配器分配task_struct结构,达到对象复用缓存着色(cache coloring)的目的。

6、由于现在用slab分配器动态生成task_struct,所以只需在栈底(对于向下增长的栈来说)或栈顶(对于向上增长的栈来说)创建新的结构struct thread_info:

struct thread_info {
    struct task_struct  *task;
    struct exec_domain  *exec_domain;
    __u32                flags;
    __u32                status;
    __u32                cpu;
    int                  preempt_count;
    mm_segment_t         addr_limit;
    struct restart_block restart_block;
    void                *sysenter_return;
    int                  uaccess_err;
};

7、内核通过一个唯一的进程标示值或PID来标识每个进程。PID是一个数,表示为pid_t隐含类型,实际就是一个int类型。为了与老版本的Unix和Linux兼容,PID的最大值默认设置为32768(short int短整数的最大值),尽管这个值也可以增加到高达400万。内核把每个进程的PID存放在他们各自的进程描述符中。

8、所有的进程都是PID为1的init进程的后代。内核在系统启动的最后阶段启动init进程。该进程读取系统的初始化脚本并执行其他的相关程序,最终完成系统启动的整个过程。

9、每个task_struct都包含一个父进程的task_struct、叫做parent的指针,还包含一个称为children的子进程链表。

10、fork()、vfork()和_clone()库函数都根据各自需要的参数标志去调用clone(),然后由clone()去调用do_fork()。 

11、除了不拷贝父进程页表项外,vfork()系统调用和fork()的功能相同。

12、从内核的角度来说,它并没有线程这个概念。Linux把都有的线程都当做进程来实现。内核并没有准备特别的调度算法或是定义特别的数据结构在表征线程。相反,线程仅仅被视为一个与其他进程共享某些资源的进程。每个线程都拥有唯一隶属于自己的task_struct,所以在内核中,它看起来就像是一个普通的进程(只是线程和其他一些进程共享某些资源,如地址空间)。对于Linux来说,它只是一种进程间共享资源的手段(Linux的进程本身就够轻量了)。

13、

线程的创建和普通进程的创建相似,只是在调用clone()的时候需要传递一些参数标志
clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, 0);

fork():
clone(SIGCHLD, 0;

vfork():
clone(CLONE_VFORK | CLONE_VM | SIGCHLD, 0);

14、 在调用了do_exit()之后,尽管线程已经僵死不能再运行了,但是系统还保留了它的进程描述符。这样做可以让系统有办法在子进程终结后仍能获得它的信息。

你可能感兴趣的:(Linux,Linux内核设计与实现)