Linux内核设计与实现读书笔记

简介:

Unix强大的根本原因:

  1. Unix简洁, 提供几百个系统调用, 设计目的明确
  2. Unix中 所有东西都被当做文件对待
  3. Unix内核和相关系统工具是用C语言开发的, 移植能力强大
  4. Unix进程创建迅速, 有独特的fork机制
  5. Unix提供简单稳定的进程间通信元语

Linux是类Unix系统, 借鉴了Unix设计并实现了Unix的API.

应用程序通常调用库函数(如C库函数)再由库函数通过系统调用界面, 让内核代其完成各种任务.

  • Linux支持动态加载内核模块
  • Linux支持对称多处理(SMP)机制
  • Linux为 抢占式内核
  • Linux并不区分线程和其他的一般进程
  • Linux提供具有设备类的面向对象的设备模型, 热插拔事件, 以及用户控件的设备文件系统

中断和中断处理

中断是一种解决处理器和速度差异的方案, 只有在硬件需要的时候再向内核发出信号. 中断本质上是一种特殊的电信号.

  • 内核响应特定中断, 然后 内核 调用特定的 中断处理程序 , 终端处理程序是设备驱动程序的一部分
  • Linux中的终端处理程序是不可重入的, 同一个中断处理程序不会被同时调用
  • 中断上下文不可以睡眠(我理解当前被中断的程序再中断处理结束后需要继续执行)
  • 中断处理程序不在进程上下文中进行, 他们不能阻塞
  • 中断处理分为两部分, 上半部为中断处理程序, 要求尽可能快的执行, 下半部( 用于减少中断处理程序的工作量 )执行与中断处理密切相关但中断处理程序本身不执行的工作
  • 下半部的实现方法 软中断、tasklet、工作队列 ,

中断机制的实现:设置产生中断, 通过电信号给处理器的特定管脚发送一个信号, 处理器听着当前处理工作, 关闭中断系统 , 然后调到内存中预定义的位置(中断处理程序的入口点)开始执行.计算终端号, do_IRQ() 对接收的中断进行应答, 禁止这条线上的中断传递.

内核同步

对于共享资源, 如果同时被多个线程访问和操作, 就可能发生各线程之间相互覆盖共享数据, 造成访问数据不一致.

同步实现通过主要 锁机制 对共享资源进行加锁, 只有持有锁的线程才能操作共享资源, 其他线程睡眠(或者轮询). 资源操作完成后, 持有锁的线程释放锁, 由等待线程抢锁.

内核同步方法:

  1. 原子操作
  2. 自旋锁 , 特性是当线程无法获取锁, 会一直忙循环( 忙等 )等待锁重新可以, 适用于短期轻量级加锁
  3. 读/写自旋锁 (共享/排它锁), 一个或多个任务可以并发的持有读者锁, 写者锁只能被一个写任务持有.
  4. 信号量 (睡眠锁), 如果一个任务试图获得一个被占用的信用量时, 信号量会将其推进一个等待队列, 然后让其睡眠. 当信号量可用后, 等待队列中的任务会被唤醒. 适用于锁被长期占用的时候.
  5. mutex(计数为1的信号量), 这个是编程中最常见的.
  6. 顺序锁
  7. 屏障 (barriers), 用于确保指令序列和读写的执行顺序

内核中造成并发的原因:

  • 中断, 几乎可以再任何时刻异步发生, 可能随时打断当前正在执行的代码
  • 软中断和tasklet, 内核能在任何时刻唤醒或调度软中断或tasklet, 打断当前正在执行的代码
  • 内核抢占
  • 睡眠及与用户空间的同步
  • 对称多处理, 多个处理器同时执行代码

内存管理

内核把物理页作为内存管理的基本单位, 内存管理单元(MMU, 管理内存并将虚拟地址转换为物理地址) 通常以页为单位来管理系统中的页表.

内核把也划分为不同的区( zone ), 使用区对具有相似特性的页进行分组


   
   
  1. // <linux/gfp.h> 该函数分配2的order次方个连续`物理页`, 返回指针指向第一个页的page结构体  
  2. staticinlinestructpage *  
  3. alloc_pages(gfp_tgfp_mask,unsignedintorder)  
  4. // 释放物理页  
  5. externvoidfree_pages(unsignedlongaddr,unsignedintorder);  
  6. //<linux/slab.h>以字节为单位分配一块内核内存(物理上连续)  
  7. static__always_inlinevoid*kmalloc(size_tsize,gfp_tflags)  
  8. //释放kmalloc分配的内存块  
  9. voidkfree(constvoid*); 

虚拟文件系统

虚拟文件系统为用户控件程序提供了文件和文件系统相关接口.

文件的元数据, 被存储在一个单独的数据结构中, 被称为 inode (索引节点)

虚拟文件系统(VFS)有四个主要的对象模型:

  • 超级块对象, 代表一个具体的已安装文件系统, 存储特定文件系统的信息
  • 索引节点对象, 代表一个具体文件, 包含内核在操作文件或目录时需要的全部信息, 一个索引节点代表文件系统中的一个文件,
  • 目录项对象, 代表一个目录项, 是路径的一个组成部分, VFS把目录当做文件处理 , 目录项对象没有对应的磁盘数据结构
  • 文件对象, 代表进程打开的文件, 进程直接处理的是文件

   
   
  1. // <linux/fs.h> 文件对象的数据结构 
  2. structfile { 
  3. union
  4. structllist_node fu_llist; 
  5. structrcu_head fu_rcuhead; 
  6.  } f_u; 
  7. structpath f_path; 
  8. structinode *f_inode;/* cached value */ 
  9. conststructfile_operations *f_op; 
  10.  
  11. /* 
  12.  * Protects f_ep_links, f_flags. 
  13.  * Must not be taken from IRQ context. 
  14.  */ 
  15. spinlock_tf_lock; 
  16. atomic_long_tf_count; 
  17. unsignedintf_flags; 
  18. fmode_tf_mode; 
  19. structmutex f_pos_lock; 
  20. loff_tf_pos; 
  21. structfown_struct f_owner; 
  22. conststructcred *f_cred; 
  23. structfile_ra_state f_ra; 
  24.  
  25.  u64 f_version; 
  26. #ifdefCONFIG_SECURITY 
  27. void*f_security; 
  28. #endif 
  29. /* needed for tty driver, and maybe others */ 
  30. void*private_data; 
  31.  
  32. #ifdefCONFIG_EPOLL 
  33. /* Used by fs/eventpoll.c to link all the hooks to this file */ 
  34. structlist_head f_ep_links; 
  35. structlist_head f_tfile_llink; 
  36. #endif/* #ifdef CONFIG_EPOLL */ 
  37. structaddress_space *f_mapping; 
  38. } __attribute__((aligned(4)));/* lest something weird decides that 2 is OK */ 

块I/O层

系统中能够 随机访问 固定大小数据片(chunks)的硬件设备称作块设备, 如硬盘. 按照字符流的方式被 有序访问 的硬件设备称为字符设备, 如键盘


   
   
  1. # <linux/bio.h>I/O设备基本容器由bio结构体表示 
  • I/O调度程序 用于管理块设备的请求队列, 决定队列中的请求排列顺序以及什么时刻派发请求到挂设备. 这样有利于减少磁盘的寻址时间, 从而提高全局的吞吐量
  • linux实际使用的I/O调度程序有 linux电梯, 最终期限I/O调度, 预测I/O调度程序, 空操作的I/O调度程序

进程地址空间

内核需要管理用户空间中进程的内存, 这个内存称为 进程地址空间 , 系统中所有进程之间以虚拟方式共享内存.

进程地址空间由进程可寻址的虚拟内存组成, 每个进程有32位或64位地址空间.

虚拟地址空间, 可被访问的合法地址空间称为 内存区域 :

  • 可执行文件代码的内存映射, 称为代码段
  • 可执行文件的已初始化全局变量的内存映射, 称为数据段
  • 包含未初始化全局变量,bss(block started by symbol)段的零页的内存映射
  • 用于进程用户空间栈的零页内存映射
  • 每一个如C库或动态链接程序等共享库的代码段、数据段和bss会被载入进程的地址空间
  • 任何内存映射文件
  • 任何共享内存段
  • 任何匿名的内存映射, 如malloc分配的内存

内核使用内存描述符结构体表示进程的地址空间, 内存描述符由mm_struct( <linux/sched.h> )结构体表示. 内核线程没有进程地址空间, 也没有相关的内存描述符, 所有内核线程没有用户上下文

应用程序操作的对象是 映射到物理内存上的虚拟内存 , 而处理器操作的是物理内存, Linux使用三级页表完成地址转换, 每个虚拟地址作为索引指向页表, 页表项则指向下一级的页表. 在多级页表中通过TLB(translate lookaside buffer)作为一个虚拟地址映射到物理地址的缓存





作者:Andrew Liu
来源:51CTO
目录
相关文章
|
5天前
|
Ubuntu Linux 开发者
Ubuntu20.04搭建嵌入式linux网络加载内核、设备树和根文件系统
使用上述U-Boot命令配置并启动嵌入式设备。如果配置正确,设备将通过TFTP加载内核和设备树,并通过NFS挂载根文件系统。
33 15
|
30天前
|
算法 Linux
深入探索Linux内核的内存管理机制
本文旨在为读者提供对Linux操作系统内核中内存管理机制的深入理解。通过探讨Linux内核如何高效地分配、回收和优化内存资源,我们揭示了这一复杂系统背后的原理及其对系统性能的影响。不同于常规的摘要,本文将直接进入主题,不包含背景信息或研究目的等标准部分,而是专注于技术细节和实际操作。
|
30天前
|
存储 缓存 网络协议
Linux操作系统的内核优化与性能调优####
本文深入探讨了Linux操作系统内核的优化策略与性能调优方法,旨在为系统管理员和高级用户提供一套实用的指南。通过分析内核参数调整、文件系统选择、内存管理及网络配置等关键方面,本文揭示了如何有效提升Linux系统的稳定性和运行效率。不同于常规摘要仅概述内容的做法,本摘要直接指出文章的核心价值——提供具体可行的优化措施,助力读者实现系统性能的飞跃。 ####
|
1月前
|
监控 算法 Linux
Linux内核锁机制深度剖析与实践优化####
本文作为一篇技术性文章,深入探讨了Linux操作系统内核中锁机制的工作原理、类型及其在并发控制中的应用,旨在为开发者提供关于如何有效利用这些工具来提升系统性能和稳定性的见解。不同于常规摘要的概述性质,本文将直接通过具体案例分析,展示在不同场景下选择合适的锁策略对于解决竞争条件、死锁问题的重要性,以及如何根据实际需求调整锁的粒度以达到最佳效果,为读者呈现一份实用性强的实践指南。 ####
|
1月前
|
缓存 监控 网络协议
Linux操作系统的内核优化与实践####
本文旨在探讨Linux操作系统内核的优化策略与实际应用案例,深入分析内核参数调优、编译选项配置及实时性能监控的方法。通过具体实例讲解如何根据不同应用场景调整内核设置,以提升系统性能和稳定性,为系统管理员和技术爱好者提供实用的优化指南。 ####
|
1月前
|
负载均衡 算法 Linux
深入探索Linux内核调度机制:公平与效率的平衡####
本文旨在剖析Linux操作系统内核中的进程调度机制,特别是其如何通过CFS(完全公平调度器)算法实现多任务环境下资源分配的公平性与系统响应速度之间的微妙平衡。不同于传统摘要的概览性质,本文摘要将直接聚焦于CFS的核心原理、设计目标及面临的挑战,为读者揭开Linux高效调度的秘密。 ####
37 3
|
1月前
|
消息中间件 安全 Linux
深入探索Linux操作系统的内核机制
本文旨在为读者提供一个关于Linux操作系统内核机制的全面解析。通过探讨Linux内核的设计哲学、核心组件、以及其如何高效地管理硬件资源和系统操作,本文揭示了Linux之所以成为众多开发者和组织首选操作系统的原因。不同于常规摘要,此处我们不涉及具体代码或技术细节,而是从宏观的角度审视Linux内核的架构和功能,为对Linux感兴趣的读者提供一个高层次的理解框架。
|
2月前
|
Linux 网络安全 数据安全/隐私保护
Linux 超级强大的十六进制 dump 工具:XXD 命令,我教你应该如何使用!
在 Linux 系统中,xxd 命令是一个强大的十六进制 dump 工具,可以将文件或数据以十六进制和 ASCII 字符形式显示,帮助用户深入了解和分析数据。本文详细介绍了 xxd 命令的基本用法、高级功能及实际应用案例,包括查看文件内容、指定输出格式、写入文件、数据比较、数据提取、数据转换和数据加密解密等。通过掌握这些技巧,用户可以更高效地处理各种数据问题。
141 8
|
2月前
|
监控 Linux
如何检查 Linux 内存使用量是否耗尽?这 5 个命令堪称绝了!
本文介绍了在Linux系统中检查内存使用情况的5个常用命令:`free`、`top`、`vmstat`、`pidstat` 和 `/proc/meminfo` 文件,帮助用户准确监控内存状态,确保系统稳定运行。
568 6
|
2月前
|
Linux
在 Linux 系统中,“cd”命令用于切换当前工作目录
在 Linux 系统中,“cd”命令用于切换当前工作目录。本文详细介绍了“cd”命令的基本用法和常见技巧,包括使用“.”、“..”、“~”、绝对路径和相对路径,以及快速切换到上一次工作目录等。此外,还探讨了高级技巧,如使用通配符、结合其他命令、在脚本中使用,以及实际应用案例,帮助读者提高工作效率。
106 3