《深入理解Linux内核》学习笔记-第三章 进程

7月8日

1.进程是程序执行时的一个实例。进程的目的就是担当分配系统资源(CPU时间、内存)的实体。

2.对进程(Process)和线程(Thread)的理解:
    从时间颗粒度上来看,线程是比进程颗粒度更细的划分单位。一个进程可以有多个线程,当启动一个进程的时候,至少会启动一个线程。
    从资源分配上来看,进程拥有独立的内存空间,而同一进程内的多个线程共享内存,从而极大地提高了效率。
    从逻辑上来看,进程就是一个程序运行之后抽象出来的实体,而线程则是一个进程当中完成不同任务的实体。
参考:https://blog.csdn.net/mxsgoden/article/details/8821936

3.进程描述符
进程描述符用于描述进程,进程描述符使用task_struct类型结构,包含进程的基本信息、指向内存区描述符的指针、与进程相关的tty、当前目录、指向文件描述符的指针和所接收的信号。

4.进程状态,进程状态通常使用一个简单的赋值语句进行设置
P->state = TASK_STATE

5.标识进程,Linux使用PID进行进程标识。 
PID被循环顺序编号,新创建的PID通常是上一个进程号加1。
PID有上限值32767,系统管理员可以在/proc/sys/kernel/pid_max中写入一个更小的值来限制。
内核通过管理pidmap_array位图来表示当前已分配的PID和闲置的PID号。

6.进程链表
进程链表使用一个双向链表,把所有进程的描述符连接起来。
每个task_struct结构都包含一个list_head类型的task字段,这个类型的prev和next字段分别指向前面和后面的task_struct。

7.当内核寻找一个新进程在CPU上运行时,必须只考虑可运行进程,即处于TASK_RUNNING状态的进程。在Linux 2.6之前,系统把所有进程都放在同一个叫运行队列的链表里,因此早期的调度程序不得不为了选择最佳的可运行进程而扫描整个队列。
在Linux 2.6之后,系统按照不同的优先级建立多个可运行进程链表,进程按照不同的优先级存放在不同的链表中,大幅提升了调度系统的操作效率。但是这样的做法增大了内存开销,但这点内存开销在现在已经完全不值一提了。

7月11日

1.进程关系
进程关系可分为亲属和非亲属
其中亲属关系的描述符字段有real_parent/parent/children/sibling
非亲属关系的描述符字段有gourp_leader/singal->pgrp/tgid/signal->session/ptrace_children/ptrace_list

7月13日

1.运行队列
运行队列链表把处于TASK_RUNNING状态的所有进程组织在一起,对处于TASK_STOPPED、EXIT_ZOMBIE或EXIT_DEAD状态的进程没有建立专门的链表,因为这些状态的进程访问比较简单。

2.等待队列
等待队列由双向链表实现,其元素包含指向进程描述符的指针,用于中断处理、进程同步和定时。

3.资源限制
每一个进程都有相关的资源限制,对当前进程的资源限制存放在current->signal->rlim字段中。该字段是rlimit结构的数组,每个资源限制对应一个元素。
struct rlimit{
    unsigned long rlim_cur;
    unsigned long rlim_max;
};

7月14日

1.进程切换
为了控制进程的执行,内核必须有能力挂起正在CPU上运行的进程,并恢复以前挂起的某个进程的执行,这种行为被称为进程切换。

2.硬件上下文(Context Switch)
在恢复一个进程的执行之前,内核必须确保每个寄存器装入了挂起时进程的值。
进程恢复执行前必须装入寄存器的一组数据被称为硬件上下文。

3.在x86架构中包含了一个特殊的段类型,叫做任务状态段(Task State Segment,TSS
用来存放硬件上下文。

7月15日

1.进程切换
进程切换只可能发生在schedule()函数
进程切换由两步组成:a)切换页全局目录以安装一个新的地址空间 b)切换内核态堆栈和硬件上下文,因为硬件上下文提供了内核执行新进程所需要的所有信息。

2.switch_to宏,包含prev,next和last三个参数,last这个参数用来指向切换完成后的前进程。
这个switch_to宏的过程相当晦涩难懂,翻找许久,查找到r00tk1t大佬对于整个进程切换过程的详细解释,在此放下链接,后续补上自己的理解。
https://r00tk1ts.github.io/2017/08/26/Linux%E8%BF%9B%E7%A8%8B%E5%88%87%E6%8D%A2/

7月19日

创建进程
1.在Linux中,轻量级进程是由clone()函数创建的。clone()函数是在C语言库中定义的一个封装(wrapper)函数,它负责建立新轻量级进程的堆栈并且调用对编程者隐藏的clone()调用。传统的fork()调用在Linux中是用clone()实现的,vfork()系统调用在Linux中也是用clone()实现的。
2.进程0,所有进程的祖先叫做进程0,idle进程,它是在Linux的初始化阶段从无到有创建的一个内核线程,在多处理器系统中,每个CPU都有一个进程0。
3.进程0会通过start_kernel()函数创建另一个PID为1的init进程,进程1与进程0共享所有的内核数据结构。

7月28日

撤销进程

进程终止
1.进程终止的一般方式是调用exit()函数,C语言编译程序总是把exit()函数插入到main()函数的最后一条语句之后。
2.exit_group()系统调用,它终止整个线程组,即整个基于多线程的应用。do_group_exit()是这个系统调用的主要内核函数。
3.exit()系统调用,它终止某一个线程,而不管该线程所属线程组中所有其他进程。do_exit()是这个系统调用的主要内核函数。

进程删除
0 条评论
发表一条评论