深入理解linux内核
第三章进程
在linux源代码中,常把进程称为任务task或者线程thread
进程的目的就是担当分配系统资源(CPU时间、内存等)的实体
父子进程可以共享含有程序代码的页,但是他它们有各自独立的数据拷贝(堆和栈),因此子进程对一个内存单元的修改对父进程是不可见的
一个多线程应用的所有线程共享相同的PID
进程描述符存放在动态内存中,而不是放在永久分配给内核的内存区
对于每个进程来说,Linux把两个紧凑的数据结构存放在一个单独为进程分配的区域内:一个是内核态的进程堆栈,另一个是紧挨进程描述符的小数据结构thread_info,叫做线程描述符,这块存储区域的大小通常为8192字节(两个页框)
esp寄存器是CPU栈指针,用来存放栈顶单元的地址,在80x86中,栈起始于末端,并朝这个内存区开始的方向增长
一些数据写入堆栈,esp的值就递减
对于每个硬件处理器,仅通过检查栈就可以获得当前正确的进程
两个不同的PID散列到相同的表索引,称为冲突
有两种睡眠进程,互斥进程(等待队列元素的flag字段为1)由内核有选择的唤醒,而非互斥进程(flag的值为0)总是由内核在是事件发生时唤醒
进程恢复执行前必须装入寄存器的一组数据称为硬件上下文(hardwarecontext),把进程切换定义为这样的行为:保存prev硬件上下文,用next以你关键上下文代替prev,强制为系统中每个不同的CPU创建一个TSS(taskstate segment任务状态段)
1.CPU从用户态切换到内核态时,它就从tss中获取内核态堆栈的地址
2.用户态进程试图通过in或out指令访问i/o端口时,CPU需访问TSS中的I/O许可权位图以检查该线程是否有访问端口的能力
第四章中断和异常
中断interrupt被定义为一个事件,该事件改变处理器执行的指令顺序。这样的事件与CPU内外部硬件电路产生的电信号相对应
中断通常分为同步中断和异步中断:
同步中断时当指令执行时由CPU控制单元产生的,之所以称为同步是因为只有在一条指令终止执行后CPU才会发生中断
异步中断是由其他硬件设备依照CPU时钟信号随机产生的
同步和异步中断分别称为异常exception和中断interrupt
中断是由间隔定时器和I/O设备产生的
异常是由程序错误或内核必须处理的异常条件产生的
为了实现中断信号的目的就要在内核态堆栈保存程序计数器的当前值(即eip和cs寄存器的内容),并把与中断类型相关的一个地址放进程序计数器
中断
分为可屏蔽中断和非屏蔽中断
可屏蔽中断:
I/O设备发出的所有请求(IRQ),都产生可屏蔽中断
一个屏蔽的中断在屏蔽状态,控制器就忽略它
非屏蔽中断:
只有几个危急事件(如硬件故障)才引起非屏蔽中断,由CPU
处理器探测异常:当CPU执行指令时探测到的一个反常条件所产生的异常,根据异常时保存在eip中的分为:
故障fault:可纠正,纠正后,程序在不失连贯性的情况下重新开始
陷阱trap:陷阱主要用途是调试程序。中断信号的作用是通知调试程序一条特殊指令已被执行(例如断点)
陷阱指令执行后立刻报告,内核把控制权返回给程序后就可以继续执行而不失连贯性
异常终止abort:发生严重错误,不能在eip中保存引起异常的指令的位置。异常终止处理程序会强制受影响的进程终止
编程异常programmed exception:
在编程者发出请求时发生。由int或int3触发。
当into(检查溢出)和bound(检查地址出界)检察的指令不为真时,也会编程异常。编程异常也叫软中断,用途为1.执行系统调用2.给调试程序通报特定的事件
每个中断和异常由0-255之间的一个数表示,8位无符号整数叫做向量vector,非屏蔽中断、异常的向量的值是固定的,可屏蔽中断可通过对中断控制器的编程来改变