Linux 内核整理

1 内存寻址

  1. 三种地址:逻辑地址:segment + offset;线性地址:32位无符号数;物理地址:用于芯片级内存寻址。
    逻辑地址经过分段单元转为线性地址。段寄存器保存segment(16位)。其中cs有两位表示特权级,0级为内核态,3级为用户态。首先从段选择符的TI域找到段描述符存放的位置(GDT还是LDT),然后根据段选择符的索引部分找到段描述符,最后和offset结合得到线性地址。
    线性地址经过分页单元转为物理地址。32位线性地址分为三部分:页目录(top10),页表(top10),偏移量(last12)。页表项的几个重要参数:present(是否在主存中),dirty(是否被修改过),acessed(是否被访问过),read/write(读写权限),U/S(权限)
  2. 写回策略:只修改高速缓存内的页表,只有当信号到来时才讲cache中的页表写回到RAM中。TLB(快表)作为存放页表的高速缓存
  3. Linux的分页采用三级页表。每一个进程有自己的页全局目录和页表集合。Linux的内核代码保存在保留frame 1中(frame 0用于BIOS启动)。进程地址空间将后1GB留给内核态。

2 进程

  1. 进程由进程描述符表示进程状态。存储于进程地址空间的最低位。
  2. 为了有效的搜索进程,进程描述符以双向链表的形式储存。为了进程调度,进程描述符保存在一个队列中。为了方便通过pid查询进程,内核维护一个hash链表。为了在进程空闲的时候及时更新task数组,内核维护一个空闲进程列表。
  3. 进程亲属关系需要注意:如果没有父进程,那么祖先进程是1(init)
  4. 进程切换:硬件上下文,硬件支持,代码,浮点寄存器(根据新进程是否使用来决定保存与否,设置TS标志位)。switch_to宏执行进程切换:挂起prev进程描述符,调用schedule将next载入CPU。
  5. 内核线程特点:每个kernel thread对应一个内核函数,只运行在内核态,只能使用大于PAGE_OFFSET的地址空间。0号进程->1号内核进程->1号用户进程(init进程)->getty进程->shell进程。其中1号内核进程调用执行init函数并演变成1号用户态进程(init进程)

3 中断和异常

  1. 同步中断(异常):指令运行结束后产生的中断;异步中断(中断):其他设备依照CPU时钟信号产生的中断。
    中断分为可屏蔽中断(IO设备发起的)和不可屏蔽中断(硬件故障等)
    异常分为处理器检测异常(异常地址保存在栈寄存器eip中)和编程异常(软中断)
    0-31标识异常和不可屏蔽中断;32-47标识可屏蔽中断;其余为软中断(linux中128作为系统调用)

  2. 中断描述符表(IDT)有256 X 8个字节。中断门和陷阱门区别在于会不会关闭可屏蔽中断
    异常处理程序结构:

    1. 保存要用的寄存器到堆栈中
    2. 调用C函数处理
    3. ret_from_exception退出高级语言。

    内核使用设备不可用异常(进程切换)和缺页异常(内存管理)来提高效率
    中断处理程序结构:

    1. 保存中断请求(IRQ)的值和寄存器
    2. 给正在服务IRQ的中断控制器(PIC)发出应答
    3. 执行中断服务历程(ISR)
    4. ret_from_intr结束
  3. 对于优先级不高的中断,等到内核处理完系统调用,异常,中断和进程切换后空闲了才执行。下半部分由上半部分触发。

4 定时测量(timing measurement)

  1. 内核两种定时测量:持续计时器(time,ftime,gettimeofday)定时器(settimer,alarm) 基于固定频率的振荡器和计数器实现的电路完成定时测量。
  2. 内核交互的时钟:
    实时时钟(RTC):独立于CPU,独自供电,固定频率。
    时间戳计数器(TSC):64位,汇编中通过rdtsc读取,每个时钟信号到来+1
    可编程间隔定时器器(PIT):定时发送中断。Linux给PC的第一个PIT设置为每10ms产生一次中断,称为tick,tick决定系统运行节拍。
  3. 定时中断程序需要自己完成更新自系统启动以来所经过的时间,其他交给下半部分TIMER_BH
    PIT中断服务例程:如果有TSC寄存器,保存TSC寄存器的值和中断与中断例程之间的延迟。调用do_timer_interrupt(1. 调用do_timer 2. 每11分钟调整一次RTC)
    do_timer 参数:jiffies 自系统启动以来的节拍数(32位无符号);lost_ticks 自xtime更新后的节拍数;lost_ticks_system 自xtime更新后再内核态的节拍数
    TIMER_BH:
    1. 更新时间和日期。更新xtime,自197001010时以来的秒数存放于xtime.tv_sec。
    2. 更新资源统计使用数。update_times关闭中断。 保存并清空 lost_ticks,保存并清空 lost_ticks_system,calc_load(ticks)更新CPU使用统计数,update_process_times(ticks,system)。进程描述符的counter域记录还能使用的节拍数,就是通过update_process_times更新。
  4. linux维护三种定时器(对定时器的检查总存在与下半部分,不适合时间要求严苛的应用):
    1. 静态定时器。内核,32个,到时间后执行fn域指向的函数。在timer_active中存储标志。存放于timer_struct中。
    2. 动态定时器。内核,存储于timer_list中,双向循环列表。为了插入和删除的效率,采用tvesc的结构,分为5个子tv,存储在下一个节拍会过期的所有动态定时器,每个子tv包含 2 8 2^8 28个节拍。
    3. 间隔定时器。用户态创建。

5 内存管理

  1. Linux采用4KB大小的page frame。page frame的描述符由一下域组成:
    1. count。有多少进程在使用这个页,如果空闲设为0。
    2. flags。32位的描述页框状态。
  2. 外碎片处理方法:Buddy系统算法
    把所有空闲页框分为10个块链表。由连续的1,2,,,512个页框组成。
    分配:从小到大分配,如果是由比需求大的块链表分配,则把空余的页框向下填充。(e.g. 128如果由块10分配,则把剩余的384分为256和128并入块9和块8)
    实现Buddy算法的数据结构:
    free_data[0 or 1][K]:大小为 2 K 2^K 2K的块的双向循环链表。
    map:第K项位图的描述大小为 2 K 2^K 2K的状态。
    清晰的图讲解可见buddy数据结构和位图
  3. 内碎片处理方法:slab分配器,是分配cache中内存的方法。
    释放slab的条件:
    1. slab中所有的对象都是空闲的。
    2. buddy系统不能满足新的请求。
      slab着色:为了防止cache冲突
  4. 非连续内存区管理
    避免外碎片,但是打乱了内核页表。因此linux很保守的在用。

6 进程的地址空间

  1. 与进程地址空间有关信息保存在mm_struct中。线性区保存在vm_area_struct中。线性区是地址空间的一部分。
    当进程有大量线性区时,保存在AVL树中;反之,保存在链表中。
    分配线性区:do_mmap。释放线性区:do_munmap。
  2. do_page_fault
    缺页异常处理流程
  3. 堆管理。用于动态内存分配,由内存描述符的start_brk和brk域管理。

7 系统调用

linux调用系统调用前,必须执行int 128发出中断。

  1. 系统调用的参数传递一般是先传入到寄存器,在拷贝到内核态的栈上面。
    对地址参数的验证:是否小于PAGE_OFFSET(即没有落入内核保留地址空间中)
  2. 动态地址检查和修正。异常表记录了访问地址空间的指令的线性地址,以及对应的修正码。
  3. linux为内核函数提供了系统调用的封装。以参数数位末尾数字,从system0到5,不能调用超过5个参数的system call。

8 信号

名字前缀为SIG的宏标识信号。

  1. 信号的作用:
    1. 让进程知道发生某一特定事件
    2. 强制进程执行代码中的信号处理程序
  2. 进程对信号的应答:
    1. 显示的忽略
    2. 执行默认调用
    3. 执行信号处理函数
  3. 与信号有关的系统调用:
    1. kill(pid,sig)。
      当pid=0,发送给调用进程的同组进程
      当pid=-1,发送给非swapper(0),init(1),和current进程。
      当pid<-1,发送给进程组-pid中的所有进程
    2. sigaction(sig,act,oact),改变信号的操作,act为新操作表,oact为可选参数,输出原来的操作表。
    3. sigpending() 检查挂起的阻塞信号
    4. sigprocmask() 修改阻塞信号集合
    5. sigsuspend() 挂起进程

9 进程调度

  1. 进程的两种优先级:
    1. 静态优先级。用户给实时进程设置的,调度算法不管。优先级高于动态优先级。
    2. 动态优先级。基本时间片+当前剩余时间片,只针对普通进程。
  2. do_fork函数会将父进程的时间片平分给父子进程。
  3. 调用schedule函数的两种形式:
    1. 直接调用。current进程需要立即阻塞。
    2. 松散调用。将current的need_resched设置为1,等待合适的时机调用。
  4. goodness函数表示进程的优先度。返回值为c。
    c=-1000,永远不调度这个进程。
    c=0,用完时间片的进程。
    0<c<1000,用了部分时间片的普通进程。
    c>=1000,实时进程。

10 内核同步

  1. 内核同步技术:
    1. 内核态的进程的非抢占性。这意味着:
      1. 占有内核态的进程不会被抢占。
      2. 可被中断,中断结束后需要返还控制权。
    2. 原子操作。以下是原子操作:
      1. 访问零次或一次内存的指令。
      2. 单处理器的从内存读,更新,写数据。
      3. 多处理器的前缀有lock的从内存读,更新,写数据。(锁住总线防止窃用)
    3. 关中断。较短的临界区代码可以通过关中断实现同步。
    4. 锁。 较长的临界区代码通过锁实现同步。
  2. 多处理下的自旋锁:
    当进程发现锁被其他进程占用时,进行“旋转”,执行一条tight指令。
    优点在于多处理器下系统负载小,减少了上下文切换的开销。
  3. 处理器间中断(IPI)用来CPU之间通信,可以群发、发给自己、发给自己以外的其他CPU和发给特定CPU。
    能实现的操作:
    1. RESCHEDULE_VECTOR。强制某CPU调用schedule函数。
    2. INVALIDATE_TLB_VECTOR。重置TLB,内核修改某进程页表时用。
    3. STOP_CPU_VECTOR。强制停止自己以外的CPU,内核检测到无法解决的错误时使用。
    4. LOCAL_TIMER_VECTOR。定时中断发给所有CPU。
    5. CALL_FUNCTION_VECTOR。强制自己以外的CPU执行函数。

11 虚拟文件系统

  1. VFS是用户程序与实际操作系统之间的一层抽象。
  2. VFS通过通用文件模型来实现抽象。对于函数调用,则是通过内核调用文件数据结构中f_op域中对应的函数指针来实现。
    举例:file → \rightarrow f_op → \rightarrow read(…)
    通用文件模型包含:
    1. superblock。存放已安装文件系统的信息。
    2. inode。每个inode对象有个inode号, 唯一标识指定文件。
      inode有两种,一种是VFS的inode,一种是具体文件系统的inode。前者在内存中,后者在磁盘中。所以每次其实是将磁盘中的inode调进填充内存中的inode,这样才是算使用了磁盘文件inode。
    3. file。存放文件与进程交互的信息,仅当进程访问文件时存在与内核中。
    4. dentry。存放目录项文件链接的信息。
  3. 软链接:有一个目录项,指向独立INODE,INODE不存文件数据,存指向真实文件的路径,可以在不同分区
    硬链接:有一个目录项,没有独立INODE,指向原始INODE,并且原始INODE的引用计数加1 ,不能在不同分区。

12 管理IO设备

  1. CPU和IO设备之间有三个层次的硬件结构:
    1. IO端口
      IO端口可以被映射为实际物理地址,方便用对内存操作的指令操作。
    2. IO接口
      将IP端口中的值翻译成对应的命令和数据。
    3. 设备管理器
      复杂设备需要设备管理器将来自IO接口命令解释。比如磁盘控制器接受到写命令,解释为具体磁道调整命令。
  2. 监控IO操作的两种方法:轮询和中断。
  3. 通过引用计数器来决定是否为设备文件被多少进程访问。值为0是调用open,则需要分配IRQ。调用release后值为0,释放IRQ。

13 磁盘高速缓存

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值