Linux内核原理


1 Linux 内核原理 广东省嵌入式软件公共技术中心 梁红波 13430271863 kelvin@emakelvin@emakelvin@emakelvin@ema----tech.com.cntech.com.cntech.com.cntech.com.cn 2 Linux 内核学习方法  学习目的:了解内核的实现架 构,以及相应的内部流程和数据 结构,为学习内核编程做好准备。  学习内核三部曲 从使用者的角度,了解内核的 功能 从实现者的角度,了解内核实 现的思想 阅读相应的代码,核心源代码 3 Linux 进程管理进程管理进程管理进程管理  程序与进程  程序是机器指令和数据组成的可执行 文件.  进程是程序关于某个数据集合的动态 执行过程。动态的概念。随着程序机 器指令的执行,进程包含不断变化的 程序指令,数据,程序计数器,CPU 寄存 器以及进程栈等.  进程是在内存中存在的,包括程序、 数据、进程描述符。  程序的多次执行是相应产生多个进程。 4 Linux 进程管理进程管理进程管理进程管理  进程描述符进程描述符进程描述符进程描述符  内核对进程进行全面描述的结构体 Linux 中把对进程的描述结构叫做 task_struct: struct task_struct { … … }  进程的所有信息都记录在其对应的 task_struct 结构体变量中. 5 Linux 进程管理进程管理进程管理进程管理  数据成员分类数据成员分类数据成员分类数据成员分类数据成员分类数据成员分类数据成员分类数据成员分类  状态信息状态信息状态信息状态信息----描述进程动态的变化描述进程动态的变化描述进程动态的变化描述进程动态的变化。。。。  链接信息链接信息链接信息链接信息----描述进程的父描述进程的父描述进程的父描述进程的父////子关系子关系子关系子关系。。。。  各种标识符各种标识符各种标识符各种标识符----用简单数字对进程进行标识用简单数字对进程进行标识用简单数字对进程进行标识用简单数字对进程进行标识。。。。  进程间通信信息进程间通信信息进程间通信信息进程间通信信息----描述多个进程在同一任务描述多个进程在同一任务描述多个进程在同一任务描述多个进程在同一任务 上协作工作上协作工作上协作工作上协作工作。。。。  时间和定时器信息时间和定时器信息时间和定时器信息时间和定时器信息----描述进程在生存周期内描述进程在生存周期内描述进程在生存周期内描述进程在生存周期内 使用使用使用使用CPU 时间的统计时间的统计时间的统计时间的统计、、、、计费等信息计费等信息计费等信息计费等信息。。。。  调度信息调度信息调度信息调度信息----描述进程优先级描述进程优先级描述进程优先级描述进程优先级、、、、调度策略等信调度策略等信调度策略等信调度策略等信 息息息息。。。。  文件系统信息文件系统信息文件系统信息文件系统信息----对进程使用文件情况进行记对进程使用文件情况进行记对进程使用文件情况进行记对进程使用文件情况进行记 录录录录。。。。  虚拟内存信息虚拟内存信息虚拟内存信息虚拟内存信息----描述每个进程拥有的地址空描述每个进程拥有的地址空描述每个进程拥有的地址空描述每个进程拥有的地址空 间间间间。。。。  处理器环境信息处理器环境信息处理器环境信息处理器环境信息----描述进程的执行环境描述进程的执行环境描述进程的执行环境描述进程的执行环境(处处处处 理器的寄存器及堆栈等理器的寄存器及堆栈等理器的寄存器及堆栈等理器的寄存器及堆栈等) 6 Linux 进程管理进程管理进程管理进程管理  进程状态信息  State 保存进程的状态。每个进程必 然处于5种进程状态中的一种。  可运行状态 TASK_RUNNING 0  可中断的等待状态 TASK_INTERRUPTIBLE 1  不可中断的等待状态 TASK_UNINTERRUPTIBLE 2  僵死状态 TASK_ZOMBIE 4  暂停状态 TASK_STOPPED 8 7 Linux 进程管理进程管理进程管理进程管理  LinuxLinux 进程状态及转换进程状态及转换进程状态及转换进程状态及转换进程状态及转换进程状态及转换进程状态及转换进程状态及转换 资源到位 TASK_RUNNING 就绪就绪就绪就绪 TASK_INTERRUPTIBLE 浅度睡眠浅度睡眠浅度睡眠浅度睡眠 TASK_UNINTERRUPTIBLE 深度睡眠深度睡眠深度睡眠深度睡眠 TASK_STOPPED 暂停暂停暂停暂停 TASK_ZOMBIE 僵死僵死僵死僵死 占有占有占有占有CPU 执行执行执行执行 do_exit() schedule() ptrace() schedule() 时间片耗尽 等待资源到位 sleep_on() schedule() 等待资源到位 interruptible_sleep_on() schedule() wake_up_interruptible() 或收到信号 wake_up() 资源到位 wake_up() 收到信号SIGCONT wake_up() 8 Linux 进程管理进程管理进程管理进程管理  进程标识符进程标识符进程标识符进程标识符进程标识符进程标识符进程标识符进程标识符  每个进程都有一个唯一的标识符,内 核通过这个标识符来识别不同的进 程 。  进程标识符PID 也是内核提供给用户程序 的接口,用户程序通过PID 对进程发号施 令 。  PID 是32 位的无符号整数,它被顺序编号  每个进程都属于某个用户组。  task_struct 结构中定义有用户标识符UID(User Identifier )和组标识符GID(Group Identifier )  这两种标识符用于系统的安全控制  系统通过这两种标识符控制进程对系统 中文件和设备的访问。 9 Linux 进程管理进程管理进程管理进程管理  双向链表  Linux 内核涉及非常多的链表。Linux 内核定义list_head 结构体,作为结构 体的成员,用于实现结构体链表。 10 Linux 进程管理进程管理进程管理进程管理  进程链表  进程链表:链接所有进程的 task_struct  由tasks 成员实现  Init_task 作为进程链表的链表头 11 Linux 进程管理进程管理进程管理进程管理  可运行队列进程链表  每种进程优先级对应一个可运行队列 链表  使用run_list 链接。 12 Linux 进程管理进程管理进程管理进程管理  进程间的亲属  进程1(init )进程是所有用户进程的 祖先。其他进程均通过已有的进程创 建。对应称为父子进程。 父 进父 进父 进父 进 程程程程 兄 进兄 进兄 进兄 进 程程程程 进 程进 程进 程进 程 P 弟 进弟 进弟 进弟 进 程程程程 指向父指向父指向父指向父 进程进程进程进程 指向兄指向兄指向兄指向兄 进程进程进程进程 指向子指向子指向子指向子 进程进程进程进程 指向弟指向弟指向弟指向弟 进程进程进程进程 13 Linux 进程管理进程管理进程管理进程管理  进程间的亲属  Real_parent 指向进程的父进程的进 程控制块。  Parent 指向父进程的进程控制块。 当进程被跟踪时,指向跟踪进程的 task_struct 。  Children 指向子进程链表  Sibling 指向兄弟进程链表  Group_leader 指向进程(线程)组 的头进程。 14 Linux 进程管理进程管理进程管理进程管理 15 Linux 进程管理进程管理进程管理进程管理  与进程调度相关的成员  Run_list 指向进程所属的运行队列中 的下一个和前一个元素,进程通过它 链入可运行队列。  prio 进程的动态优先权  static_prio 进程的静态优先权  array 指向包含进程所在运行队列的 结构 prio_array_t  policy 进 程 的 调 度 类 型 (SCHED_NORMAL, SCHED_RR, 或 SCHED_FIFO)  rt_priority 进程的实时优先权 16 Linux 进程管理进程管理进程管理进程管理 17 Linux 进程管理进程管理进程管理进程管理  文件系统相关的域  fs 指针指向当前目录所在的文件系统 fs_struct  files 指针指向files_struct, 该结构体描 述进程的打开文件信息表,包含进程 的打开文件对象数组fd_array 。  进程空间相关域  mm 指向进程地址空间以及内存管理 的相关信息。  Active_mm 包含最近最长使用的地址 空间的指针。 18 Linux 进程调度进程调度进程调度进程调度  Linux 与任何分时系统一样,通过一个进 程到另一个进程的快速切换,达到表面 上看来多个进程同时执行的神奇效果。 多进程并发执行,让每个进程觉得自己 独享处理器。  也就是通过进程调度实现,微观上进程 交替执行,宏观上并发执行。 19 Linux 进程调度进程调度进程调度进程调度  调度算法考虑的因素  公平:保证每个进程得到合理的CPU 时间。  高效:使CPU 保持忙碌状态,即总是 有进程在CPU 上运行。  响应时间:使交互用户的响应时间尽 可能短。  周转时间:使批处理用户等待输出的 时间尽可能短。  吞吐量:使单位时间内处理的进程数 量尽可能多。 20 Linux 进程调度进程调度进程调度进程调度  Linux 调度策略  实现几个互相冲突的目标:进程响应 时间尽可能快,后台作业的吞吐量尽 可能高,尽可能避免进程的饥饿现 象,低优先级和高优先级进程的需要 尽可能调和等等。  调度策略两个矛盾目标:响应时间、 最大系统吞吐量。 21 Linux 进程调度进程调度进程调度进程调度  Linux 调度策略 Linux 进程区分为三类  交互式进程:进程经常与用户进行交 互,要花很多时间等待输入操作。当 接受了输入后,进程必须被很快唤 醒,否则,用户将发现系统反应迟钝。  批处理进程:进程不必与用户交互, 在后台运行。不必被很快地响应,受 到调度程序的慢待。  实时进程:进程有很强的调度需要。 进程决不会被低优先级的进程阻塞, 有一个短的响应时间,更重要的是, 响应时间的变化应该很小。 22 Linux 进程调度进程调度进程调度进程调度  Linux 调度策略  Linux 2.6 调度程序实现了基于进程过 去行为的启发式算法,以确定进程应 该被当作交互式进程还是批处理进程。  Linux 向交互式进程倾斜,优先调度 交互式进程,缩短响应时间。  同时为了平衡目标,提高吞吐量,采 用动态优先级,提高低优先级的批处 理进程,尽可能避免进程的饥饿现象。 23 Linux 进程调度进程调度进程调度进程调度  Linux 调度策略---- 进程的抢占  Linux 是抢占式的。如果进程进 TASK_RUNNING 状态,内核检查它 的动态优先级是否大于当前正运行进 程的优先级。如果是,current 的执 行被中断,并调用调度程序选择优先 级高的进程运行(通常是刚刚变为可 运行的进程)。 24 Linux 进程调度进程调度进程调度进程调度  时间片  时间片的长短对系统性能是很关键的。 平均时间片太短,由进程切换引起的 系统额外开销就变得非常高。平均时 间片太长,进程看起来就不再是并发 执行。  Linux 默认时间片很短,对于优先级 高的进程,提供较长的默认时间。而 且通过动态调整进程优先级,动态调 整分配给进程的时间片。 25  调度类型  SCHED_FIFO 先进先出的实时进程。当调度程序把CPU 分 配给进程的时候,它把该进程控制块保留在 运行队列链表的当前位置。如果没有其他可 运行的高优先权实时进程,进程就继续使用 CPU,想用多久就用多久,即使还有其他具 有相同优先权的实时进程处于可运行状态。  SCHED_RR 时间片轮转的实时进程。当调度程序把CPU分配给进程的时候,把该进程的控制块放在 运行队列链表的末尾。这种策略保证对所有 具有相同优先权的SCHED_RR 实时进程公平 地分配CPU 时间。  SCHED_NORMAL 普通的分时进程 26 Linux 进程调度进程调度进程调度进程调度  普通进程的调度  每个普通进程都有它自己的静态优先 权,调度程序使用静态优先权来估价 系统中这个进程与其他普通进程之间 调度的程度。  内核用从 100 (最高优先权)到139 (最低优先权)的数表示普通进程的 静态优先权。注意,值越大静态优先 权越低。  新进程总是继承其父进程的静态优先 权。当然可以通过系统调用nice( ) 和setpriority( ) 改变进程的静态优先 权。 27 Linux 进程调度进程调度进程调度进程调度  普通进程的调度  基本时间片。静态优先权本质上决定 了进程的基本时间片,即进程用完了 以前的时间片时,系统分配给进程的 时间片长度。  静态优先权和基本时间片的关系用下 列公式确定: 28 Linux 进程调度进程调度进程调度进程调度  普通进程的调度  静态优先权越高,基本时间片就越长。 其结果是,与优先权低的进程相比, 通常优先权较高的进程获得更长的 CPU 时间片。 29 Linux 进程调度进程调度进程调度进程调度  普通进程的调度  动态优先权。  普通进程除了静态优先权,还有动态优 先权,其值的范围是 100 (最高优先权) 到139 (最低优先权)。  动态优先权是调度程序在选择新进程来 运行的时候使用的数。  与静态优先权的关系 动态优先权 = max ( 100, min ( 静态优先权 - bonus + 5, 139 ) )  Bonus 是范围从0到10 的值,bonus 的值 小于5表示降低动态优先权以示惩罚, bonus 的值大于5表示增加动态优先权以 示额外奖赏。Bonus 30 Linux 进程调度进程调度进程调度进程调度  普通进程的调度  平均睡眠时间是进程在睡眠状态所消耗的平 均纳秒数。  平均睡眠时间 Bonus  大于或等于0小于100ms 0  大于或等于100 小于200ms 1  大于或等于200 小于300ms 2  大于或等于300 小于400ms 3  大于或等于400 小于500ms 4  大于或等于500 小于600ms 5  大于或等于600 小于700ms 6  大于或等于700 小于800ms 7  大于或等于800 小于900ms 8  大于或等于900 小于1000ms 9  1 秒 10 31 Linux 进程调度进程调度进程调度进程调度  普通进程的调度  交互进程 “动态优先权≤3 × 静态优先权 /4+28 ”的进程 (有特权,后面讲到)  相当于下面公式: bonus-5≥静态优先权/4-28 32 Linux 进程调度进程调度进程调度进程调度  普通进程的调度  活动和过期进程。  为了避免进程饥饿,当一个进程用完它 的时间片时,它应该被还没有用完时间 片的低优先权进程取代。调度程序维持 两个不相交的可运行进程的集合,实现 这种机制。  活动进程:这些进程还没有用完他们的 时间片。  过期进程:这些可运行进程已经用完了 他们的时间片,被禁止运行,直到所有 活动进程都过期。  一般情况下,当进程用完其时间片后, 就会挪到过期进程集合,最终活动进程 集合最终会变为空,过期进程将有机会 运行。 33 Linux 进程调度进程调度进程调度进程调度  普通进程的调度  活动和过期进程。 34 Linux 进程调度进程调度进程调度进程调度  普通进程的调度  活动和过期进程。  调度程序试图提升交互进程的性能。用 完其时间片的活动批处理进程总是变成 过期进程。用完其时间片的交互进程通 常仍然是活动进程:调度程序重填它的 时间片并把它留在活动进程集合中。  如果最老的过期进程已经等待了很长时 间,或者过期进程比交互进程的静态优 先权高,调度程序就把用完时间片的交 互进程移到过期进程集合中。  最终,活动进程集合最终会变为空,过 期进程将有机会运行。 35 Linux 进程调度进程调度进程调度进程调度  实时进程的调度  每个实时进程都与一个实时优先权相 关,实时优先权是一个范围从 1(最 高优先权)到99 (最低优先权)的 值。  调度程序总是让优先权高的进程运 行,换句话说,实时进程运行的过程 中,禁止低优先权进程的执行。  如果几个可运行的实时进程具有相同 的最高优先级,调度程序选择第一个 出现在运行队列链表中的进程  与普通进程相反,实时进程总是被当 成活动进程 36 Linux 进程调度进程调度进程调度进程调度  调度程序的数据结构 可运行队列rq 数据结构  运行队列链表链接所有的可运行进程(也就 是处于 TASK_RUNNING 状态的进程)的进 程控制块。  系统中的每个CPU 都有它自己的运行队列。  unsigned long nr_running 运行队列链表中 可运行进程的数量  arrays 字段是一个包含两个prio_array_t 结构 的数组。  每个数据结构都表示一个可运行进程的集 合,并包括140 个双向链表头(每个链表对 应一个可能的进程优先权)、一个优先权位 图和一个集合中所包含的进程数量的计数器 37 Linux 进程调度进程调度进程调度进程调度  可运行队列rq  active 字段指向数组中两prio_array_t 数据结构之一:对应于包含活动进程 的可运行进程的集合。  expired 字段指向数组中的另一个 prio_array_t 数据结构:对应于包含 过期进程的可运行进程的集合。  数组中两个数据结构的作用会发生周 期性的变化:活动进程突然变成过期 进程,而过期进程变为活动进程,调 度程序简单地交换运行队列的 active 和 expired 字段的内容以完成这种变 化。 38 Linux 进程调度进程调度进程调度进程调度  调度程序所使用的函数  scheduler_tick( ) 函数  每次时钟节拍到来时,scheduler_tick( ) 被 调用执行,递减当前进程的时间片计数器, 并检查是否已经用完时间片。进程的调度类 型不同,函数所执行的这一步操作也有很大 的差别。  更新实时进程的时间片:  如果当前进程是先进先出(FIFO )的实时进 程,函数scheduler_tick( ) 什么都不做。  如果current 表示基于时间片轮转的实时进 程,scheduler_tick( ) 就递减它的时间片计数 器并检查时间片是否被用完。如果函数确定 时间片确实用完了,就执行一系列操作以达 到抢占当前进程的目的。 39 Linux 进程调度进程调度进程调度进程调度  schedule( ) 调度函数  从运行队列的链表中找到一个进程, 并随后将CPU 分配给这个进程。 schedule( ) 可以可以采取直接调用 或延迟调用(把 TIF_NEED_RESCHED 标志设置为1) 的方式。  判断那个进程是优先级最高的进程: 40  schedule( ) 调度函数  判断那个进程是优先级最高的进程: 41 Linux 内存管理内存管理内存管理内存管理 42 物理页管理  Linux 采用4Kb 作为标准的内存分配单元。 称为物理页。整个内存划分成无数大小 相等的页(4K) 。页作为分配和回收内存 的基本单位。  与虚拟内存的页面大小一致  4k 是磁盘块大小的倍数  Linux 内核需要记录物理页面的使用情况  采用page 结构体记录物理页面的状态信息  Count 页框引用计数。为零表示空闲  Flags 页框状态,是不是脏的,是否上锁等。 每一位表示一种状态。  Page 页描述符存放在mem_map 数组 43 物理页管理  由于计算机体系结构的硬件限制,物理 页框使用具有不公平性。(x86 )  ISA 总线只能寻址16MB 的内存范围。  具有大容量RAM 的系统,CPU 可能不能直接 访问所有的物理内存。  Linux 把物理存储器分为3个管理区:  ZONE_DMA , 大小小于16MB ,用于ISA DMA  ZONE_NORMAL, 大小范围16MB--896MB , 内核可直接映射。  ZONE_HIGHMEM ,大于896MB ,不能使用 L1 和L2 高速缓存,存放不常访问的用户进程 或不常用的页表项,如果使用频繁,可以通 过内存交换换到ZONE_NORMAL 中。 44 物理页管理 45 物理页管理-- 伙伴系统算 法  外碎片问题  Linux 内核采用buddy system 算法解决 外碎片问题,实现高效、健壮的连续物 理页面的分配策略。  Buddy system  把所有的空闲物理页面分组在11 个块链表中  每个链表分别包含大小为1,2,4,8,16 , 32 ,64 、512 和1024 个连续的页面。即每个每个每个每个 链表中的一个块含有链表中的一个块含有链表中的一个块含有链表中的一个块含有2的幂次个页面的幂次个页面的幂次个页面的幂次个页面  区描述符zone_struct 中free_area 数组描述 该区的伙伴系统,管理这11 个块链表。第第第第k 项管理大小为项管理大小为项管理大小为项管理大小为2 k的块的块的块的块。。。。 46 物理页管理  Buddy system 工作原理  分配时,按照最佳匹配分拆临近大块。 首先在大小满足要求的块链表中查找 是否有空闲块,若有则直接分配,否 则在更大的块中查找。  释放:会尽可能将物理地址相邻的空 闲块合并成更大的块。 47 物理页管理  举例:申请16k 内存  在4页(2 2)大小的页块链表中查询, 如果有,申请到。否则在8页链表中 查询。  在8页的链表中查询,如果有,则申 请4页,把剩余的四页加到4页的链 表中。否则,到16 页的块中查寻, 循环往更大的页面链表查询。  如果一直没有合适的内存大小,发出 申请失败消息。退出。 48 物理页管理  请求和分配页面 page_alloc.c gfp.h  __get_free_pages(gfp_mask, order)  __get_free_page(gfp_mask)  alloc_pages( gfp_mask, order)  alloc_page(gfp_mask)  __free_pages(page, order)  free_pages(addr, order)  __free_page(page)  __free_page(addr) 49 物理页管理 50 物理内存的分配 Slab系统 动态存储区的页框数组 VM 系统 连续存储器分配连续存储器分配连续存储器分配连续存储器分配 伙伴系统 非连续存储器分配非连续存储器分配非连续存储器分配非连续存储器分配 51 物理页管理  伙伴系统,可以成功的实现连续存储的 分配和收。必须以页框为单位,造成” 内碎片”。  怎样能按照需要的任意大小来分配? 内核需要的存储区,往往大小固定,可以考 虑将一系列固定大小的存储空间管理起来。 提出了存储区的概念  内核实现slab 分配器。 由内核在内存区维护 一个缓存区,缓存区维护着已分配的、已初 始化的、待部署的存储区对象。当进程不再 需要内存区时,把释放的内存区放回缓存区 中。减少分配、初始化、撤销和释放内存的 代价。 52 物理页管理  slab 分配器把存储器区看作对象(object) 。  slab 分配器通过Cache-Slab-Object 三级 体系对这些存储区对象进行管理。 53 物理页管理  slab 分配器通过Cache-Slab-Object 三级 体系对这些存储区对象进行管理。  slab 分配器首先由cache 组成。Slab 分配器把 对象按照类型分组成不同的cache 。不同 cache 大小不同,分专用cache 和通用cache 。 专用cache 用于特定对象,例如进程描述符 结构体task_struct 。  一个Cache 管理着一组Slab ,每个slab 都由一 个或者多个连续的页面组成。 Slab 分配器通 过伙伴系统分配页框。 Slab 里面就是一个个 的对象,包含已分配的对象,也包含空闲的 对象。  Object 就是特定大小的存储区。一个Cache 中的所有对象,大小一样。 54 物理页管理  slab 分配器的组织关系 55 物理页管理  Slab 描述符struct slab  List ,在高速缓存中根据类型不同分 别存在不同的slab 链表中。  S_mem ,指向首个对象。  Inuse ,当前含有缓存对象的数量。  Free 是slab 对象数组的索引值,对应 第一个可用对象。 56 物理页管理  Slab 描述符 57 物理页管理  一个slab 将其管理的连续内存区分割成 多个对象,排列成连续的对象数组,分 别管理他们的分配和回收。对象,是 slab 体系里面真正被分配的单位。对象 的内存大小,取决于所处的cache.  对象也有自己的描述符 kmem_bufctl_t ,一个无符号整数。 只有在对象空闲的时候,这个整数包含 下一个空闲对象在slab 中的下标。 58 物理页管理  Slab 分配器:与伙伴系统的接口 void * kmem_getpages(kmem_cache_t*cachep, unsigned long flags) { void*addr; addr= (void*) __get_free_pages(flags, cachep- > gfporder); return addr; } 功能:为创建的slab 分配一组空闲连续的页框 参 cachep 指向需要额外页框的高速缓存描述符 flags 说明如何请求页框 59 物理页管理  Slab 分配器的接口  kmem_cache_create 创建一个cache ,分配 合适的slab 大小。  kmem_cache_alloc 从高速缓存中获取对象。 实例:task_struct 对象 (kernel/fork.c )  内核用全局变量存放指向task_struct 高速缓 存的指针:static kmem_cache_t *task_struct_cachep ;  内核初始化时,fork_init 创建高速缓存: task_struct_cachep =kmem_cache_create("task_struct", sizeof(struct task_struct), ARCH_MIN_TASKALIGN, SLAB_PANIC, NULL, NULL); 60 物理页管理  Slab 分配器的接口 实例:task_struct 对象 (kernel/fork.c )  进程调用Fork() ,就创建一个新的 task_struct 。do_fork() 调用 dup_task_struct() ,分配task_struct 对象。 tsk = alloc_task_struct(); 该函数的定义 就是下列语句: kmem_cache_alloc(task_struct_cachep, GFP_KERNEL) 61 物理内存管理  Slab 分配器:高速缓存中的通用对 象管理  kmalloc(size_t size, int flags):得到 通用对象,获得以字节为单位的一个 存储区对象。  kfree(const void *block) :释放通用 对象  例子: struct dog * ptr; ptr = kmalloc(sizeof(struct dog),GFP_KERNEL); 62 物理内存管理  非连续存储区:  线性地址连续,而物理地址不连续。  每个非连续区都有一个vm_struct 的 描述符。  将描述符组成一个简单的链表  内核可以使用vmalloc 函数从内核分 配一个非连续存储器区。  vmalloc 函数从伙伴系统申请页框 (多次申请),并且在在内核页表中 建立新的页表,将这些页框映射到一 段连续的线性地址空间。 63 物理内存管理 Slab系统 动态存储区的页框数组 VM 系统 连续存储器分配连续存储器分配连续存储器分配连续存储器分配 伙伴系统 非连续存储器分配非连续存储器分配非连续存储器分配非连续存储器分配 64 进程地址空间 65 进程空间  虚拟内存-共4G字节,分为内核空间 (最高的1G字节)和用户空间(较低的 3G字节)两部分,每个进程最大拥有3G 字节私有虚存空间  地址转换-通过页表把虚存空间的一个 地址转换为物理空间中的实际地址。 66 内核空间内核空间内核空间内核空间((((1GB )))) 进进进进 程程程程 1 的的的的 用用用用 户户户户 空空空空 间间间间 (3G B) 进进进进 程程程程 2 的的的的 用用用用 户户户户 空空空空 间间间间 (3G B) … 进进进进 程程程程 n 的的的的 用用用用 户户户户 空空空空 间间间间 (3G B) 虚虚虚虚 拟拟拟拟 地地地地 址址址址 空空空空 间间间间 67  Linux 把进程的用户空间划分为一个个区间,便于 管理  一个进程的用户地址空间主要由mm_struct 结构和 vm_area_structs 结构来描述。  mm_struct 结构它对进程整个用户空间进行描述  vm_area_structs 结构对用户空间中各个区间(简称 虚存区虚存区虚存区虚存区)进行描述 进程用户空间管理进程用户空间管理进程用户空间管理进程用户空间管理进程用户空间管理进程用户空间管理进程用户空间管理进程用户空间管理 mm ap 进程内存描 述符 mm_struct Vm_area_st ruct 进程虚拟地 址 68 相关数据结相关数据结相关数据结相关数据结 构之间的关构之间的关构之间的关构之间的关 系示意图系示意图系示意图系示意图 69  进程控制块是内核中的核心数据结构。  在进程的 task_struct 结构中包含一个mm 域,它是指向 mm_struct 结构的指针。是 对整个进程的地址空间的描述。表示进程 的全部地址空间——包含了和进程地址空 间有关的全部信息  而进程的 mm_struct 结构则包含进程的可 执行映像信息以及进程的页目录指针pgd 等。  该结构还包含有指向 vm_area_struct 结 构的几个指针,每个 vm_area_struct 代 表进程的一个虚拟地址区间。 进程用户空间管理进程用户空间管理 70 进程用户空间管理  进程的内存区域,可通过 /proc/pid/maps 查看  Maps 每一项都与一个vm_area_struct 数 据结构对应。 71 进程内存的分配与回收  创建进程fork() 、程序载入execve() 、映射 文件mmap() 、动态内存分配malloc()/brk() 等进程相关操作都需要分配内存给进程。 不过这时进程申请和获得的还不是实际内 存,而是虚拟内存,准确的说是“内存区域”。  进程并没有获得物理内存,获得的仅仅是 对一个新的线性地址区间的使用权。  实际的物理内存只有当进程真的去访问新 获取的虚拟地址时,才会由“请页机制”产生 “缺页”异常,从而进入分配实际页框的例程。  这种请页机制把页框的分配推迟到不能再 推迟为止 。 72 内存管理分析线索  分析第二个问题:  进程空间地址如何管理?  进程地址如何映射到物理内存?  物理内存如何被管理? 73 分页机制 74 分页机制  应用程序操作的对象是虚拟内 存,处理器直接操作的却是物理 内存。  应用程序访问一个虚拟地址时,必须 将虚拟地址转化成物理地址,处理器 才能解析地址访问请求。  地址的转换工作需要通过查询页表才 能完成。  地址转换需要将虚拟地址分段,使每 段虚地址都作为一个索引指向页表, 而页表项则指向下一级别的页表或者 指向最终的物理页面。 75  32 位系统对页表采用了两级表的结构, 线性地址分成3个字段,对应的是两步 转换,相应的有页表和页目录表。这样 做减小了页表所需的RAM。  两级表结构的第一级称为页目录,存储在一 个4K 字节的页面中。页目录表共有1K 个表 项,每个表项为4个字节,并指向第二级表。  两级表结构的第二级称为页表,也刚好存储 在一个4K 字节的页面中,包含1K 个字节的表 项,每个表项包含一个页的物理基地址。 分页机制 76 分页机制  采用两级表的结构的32 位系统 的地址映射 77 分页机制  页目录项:最多可包含1024 个页 目录项,每个页目录项为4个字节。  第31~12 位是20 位页表地址,由于页表地址 的低12 位总为0,所以用高20 位指出32 位页 表地址。最多包含1024 个页表地址。  第0位是存在位,表示页表地址指向的页是 否在内存中。 78 分页机制  页面项:每个页目录项指向一个页表, 页表最多含有1024 个页面项,每项4个 字节。页面的起始地址也是4K 的整数倍。  第31~12 位是20 位物理页面地址,除第6位 外第0~5位及9~11 位的用途和页目录项一 样,第6位是页面项独有的,当对涉及的页 面进行写操作时,D位被置1。 79 分页机制  4GB 的存储器只有一个页目录,它 最多有1024 个页目录项,每个页 目录项又含有1024 个页面项。  存储器一共可以分成 1024 ×1024=1M 个页面。每个页面 为4K 个字节。存储器的大小正好最 多为4GB 。 80 分页机制  Linux 采用的是三级分页模式,对于32 位处理 器,Linux 忽略中间目录层,总目录就叫页目 录。 mm pgd 1 0 1 1 ...... 1 0 1 1 ...... Page Frame Page Frame Physical Memory task_struct mm_struct 1 0 1 1 ...... pgd p 位p 位pte pte Page Frame Linux 文件系统文件系统文件系统文件系统 广东省嵌入式软件公共技术支持 中心 梁红波 2008年06 月 82 Linux 支持多种文件系统  文件和文件系统的概念  文件:数据块的集合,表示一个有意义的信 息  文件系统:对文件的管理系统,包含很多对 文件的操作方法(函数)。  文件系统类型  磁盘文件系统:对磁盘文件的管理  ext,ext2,minix,  msdos,vfat ,ntfs  iso9660  网络文件系统:访问网络上其他计算机的文 件  NFS、CIFS、NCP  特殊文件系统  PROC 文件系统 83 Linux 支持多种文件系统  Linux 允许不同的文件系统共存,并支 持跨文件系统的文件操作。  Linux 内核提供VFS(虚拟文件系统转换) 实现这个功能。  用户访问文件的操作是通过虚拟文件系 统提供的接口完成的。  虚拟文件系统会根据文件所在的文件系 统类型而调用相应的操作函数。 84 Linux 支持多种文件系统  CP 实例 85 虚拟文件系统  VFS: 虚拟文件系统转换  内核软件层,在Linux 系统中为用户访问 不同的文件系统提供统一的通用的接口。 86 虚拟文件系统  VFS 并不是一种实际的文件系统。它只 存在于内存中,不存在于任何外存空间。 VFS 在系统启动时建立,在系统关闭时 消亡。  对LINUX 的每个文件系统的所有细节进 行抽象,使得不同的文件系统在LINUX核心以及系统中运行的其他进程看来, 都是相同的。 87 通用文件模型  VFS 的设计思想:  引入一个通用文件模型,表示所有支持 的文件系统。  提供一些面向文件的通用操作;涉及到 针对文件系统的操作时,VFS 把操作通 过函数指针映射到具体文件系统的操作 函数上。 File -> f_op -> read( );  通用文件模型采用unix 风格。  面向对象的思想:数据结构+操作函数 指针 88 通用文件模型  Unix 风格是指Unix 文件系统传统上使用了 四种和文件系统相关的抽象概念:  文件——在Unix 中的文件都被看做是一有序字 节串,它们都有一个方便用户或系统识别的名 称。  目录项——不要和目录概念搞混淆,在Linux 中 目录被看作文件。而目录项是文件路径中的一 部分。  索引节点——Unix 系统将文件的相关信息(如 访问控制权限、大小、拥有者、创建时间等等 信息),存储在一个单独的数据结构中,该结 构被称为索引节点(inode)。  安装点——在Unix 中,文件系统被安装在一个 特定的安装点上,所有的已安装文件系统都作 为根文件系统树中的叶子出现在系统中。 89 通用文件模型的构成  超级块对象super block 描述特定的已安装文件系统信息。对于 基于磁盘的文件系统,这类对象通常对 应于存放在磁盘上的文件系统控制块。  索引节点对象inode  描述具体文件信息。对于基于磁盘的文 件系统,这类对象通常对应于存放在磁 盘上的文件控制块。  文件对象file  存放打开文件与进程之间进行交互的有 关信息。  目录项对象dentry  存放目录项与对应文件链接的信息。 90 通用文件模型的构成  每个主要对象中都包含一个操作对象, 操作对象描述了内核针对主要对象可以 使用的方法。  super_operations 对象 包括针对特定文件系统所能调用的方 法,比如read_inode() 和sync_fs() 方 法等。  inode_operations 对象 包括针对特定文件所能调用的方法, 比如create() 和link() 方法等。  dentry_operations 对象 包括对特定目录所能调用的方法,比 如d_compare() 和d_delete() 方法等。  file_operations 对象 包括进程针对已打开文件所能调用的 方法,比如read() 和write() 方法等。 91 通用文件模型的构成  三个不同的进程打开同一个文件,两个 进程使用同一个硬链接 92 VFS 的数据结构  VFS 依靠四个主要的数据结构和一些 辅助的数据结构来描述其结构信息, 这些数据结构表现得就像是对象;  每个主要对象中都包含由操作函数表 构成的操作对象,这些操作对象描述 了内核针对这几个主要的对象可以进 行的操作。 93 super_block 超级块对象  存储一个已安装的文件系统的控制信息, 代表一个已安装的文件系统;  一个的文件系统被安装时,内核会从磁盘 的特定位置读取一些控制信息来填充内存 中的超级块对象。  一个已安装文件系统和一个超级块对象一 一对应。  超级块通过其结构中的域s_type 记录它所属 的文件系统类型。  所有的超级块对象通过双向链表的形式链 接在一起。  S_fs_info 指向属于具体文件系统的超级块 信息 94 超级块操作 s_op  与超级块关联的方法就是所谓的超级 块操作superblock operation 。这些 操作是由数据结构super,operations 来描述的,该结构的起始地址存放在 超级块的s_op 域中。  每个具体的文件系统都可以定义自己 的超级块操作。当VFS 需要调用其中 某一操作时,将调用s_op 域所指向的 操作。例如read_inode 。 sb 一>s-op 一>read_inode(inode); 95 Inode 索引节点对象  索引节点对象包含了在操作文件 时所需要的全部信息,代表了存 储设备上的一个实际的物理文 件。  仅在文件被访问的时候,在内存 中创建。  当一个文件首次被访问时,内核 会在内存中组装相应的索引节点 对象,以便向内核提供对一个文 件进行操作时所必需的全部信 息;这些信息一部分存储在磁盘 特定位置,另外一部分是在加载 时动态填充的。  一个被访问的文件只有一个索引 节点  索引节点相关操作 96 File 对象  文件对象描述的是进程怎样与一个打 开文件交互。  文件对象是在进程打开文件时创建的。  存放在文件对象中的主要信息是文件 指针,即进程对文件的当前操作的位 置。 97 File 对象 98 dentry 目录项对象  引入目录项的概念主要是出于方便查找 文件的目的。  一个路径的各个组成部分,不管是目录 还是普通的文件,都是一个目录项对 象。  如,在路径/ home / source / test.c 中,目录 /, home, source 和文件 test.c 都对应一个目录项对象。  和前面的超级块以及索引节点对象不一 样,目录项对象,并没有磁盘上对应的 存在。这些对象,是VFS 根据磁盘上的 目录文件的内容,在内存中临时生成的。  在查找路径名/tmp/test 时,内核为根 目录/ 创建一个目录项对象,为根目 录下的tmp 项创建一个第二级目录项 对象,为tmp 目录下的test 项创建一个 第三级目录项对象。  系统使用目录项高速缓存,存放目录项 对象。 99 文件读写  用户空间通过read/write 系统调用进入 内核执行文件操作,sys_read( ) 和 sys_write( ) 几乎执行相同的步骤: 1. 调用fget( ) 从fd 获取相应文件对象file ,并 把引用计数器file->f_count 减1。 2. 检查file->f_mode 中的标志是否允许请求访 问(读或写操作)。 3. 调用locks_verify_area( ) 检查对要访问的文 件部分是否有强制锁。 4. 调用file->f_op->read 或file->f_op->write 来传送数据。两个函数都返回实际传送的 字节数。 5. 调用fput( ) 以减少引用计数器file->f_count 的值 6. 返回实际传送的字节数。 100  要求文件系统在频繁的文件操作(例如,新建, 删除,截断)下能够保持较高的读写性能,要求 低碎片化。  Linux 下的日志文件系统(XFS,ReiserFS,Ext3 等) 能保持数据的完整性,但消耗过多系统资源,的 弱点使之不能成为嵌入式系统中的主流应用。并 且这些都是专门为硬盘这类的存储设备优化,对 于flash 这类的存储介质并不适用。  因为现有的嵌入式文件系统的碎片化的问题,大 部分的嵌入式设备只给用户提供了只读文件系 统,给用户带来不便。  嵌入式文件系统的载体是以Flash 为主的存储介 质,所以为了延长Flash 的使用寿命,应该尽量 减少对Flash 的写入操作。  文件系统采用Direct I/O 的话,使I/O 效率明显降 低,增加了写入次数;但采用延时写的话,虽然 能够降低碎片问题,如果加入日志系统的话,有 不能保证数据的安全性。这是一个矛盾。 Linux 对文件系统的要求: 101 Ramdisk 文件系统  Ramdisk 是通过将计算机的 RAM 用作设 备来创建和挂装文件系统的一种机制, 它通常用于无盘系统(当然包括微型嵌 入式设备,它只包含作为永久存储媒质 的闪存芯片)。  用 Ramdisk 挂装 Ext2fs 通过使用 Ramdisk 的概念,可以在嵌入 式设备中创建并挂装 Ext2 文件系统 (以及用于这一目的的任何文件系统)。 102 RomFS 文件系统  uClinux 系统多采用Romfs 文件系统, Romfs 是一种相对简单、占用空间较少 的文件系统。空间的节约来自于两个方 面:首先内核支持Romfs 文件系统比支 持ext2 文件系统需要更少的代码;其次 romfs 文件系统相对简单,在建立文件 系统超级块(Superblock )需要更少的 存储空间。Romfs 是只读的文件系统, 禁止写操作,因此系统同时需要虚拟盘 (RAMDISK )支持临时文件和数据文件 的存储。  只读文件系统,可以放在ROM 空间,也 可以在系统的RAM 中,嵌入式linux 中常 用来作根文件系统。 103 CRAMFS 文件系统  CRAMFS 中的数据已被压缩,属于只读 性文件系统,不能在闪存中修改。用户 想获取数据时,CRAMFS 先把数据送到 RAM 中,用户从RAM 中读取。一般 CRAMFS 的上层为RAMFS 文件系统,经 修改过的文件都保存在RAM 中。 104 JFFS2 文件系统  为此Linux 采用了新的文件系统- JFFS2 ,它允许在闪存中直接进行 修改,在掉电时会自动保存数据。 JFFS2 的数据压缩方式和CRAMFS 一样,其数据可存放在全部的闪 存区域中,数据的写入和删除分 布在很大一片区域中以防止同样 的块会被重复使用。 105 MTD 设备与JFFS 文件系统 JFFS2 是比较常用的嵌入式日志文件系统。JFFS2 因为 有以下这些 优点优点优点优点而在无盘嵌入式设备中越来越受欢迎:  JFFS2 在扇区级别上执行闪存擦除/写/读操作要 比 Ext2 文件系统好。  JFFS2 提供了比 Ext2fs 更好的崩溃/掉电安全保护。 当需要更改少量数据时,Ext2 文件系统将整个扇区复 制到内存(DRAM)中,在内存中合并新数据,并写回 整个扇区。这意味着为了更改单个字,必须对整个扇 区(64 KB )执行读/擦除/写例程 ― 这样做的效率 非常低。要是运气差,当正在 DRAM 中合并数据时, 发生了电源故障或其它事故,那么将丢失整个数据集 合,因为在将数据读入 DRAM 后就擦除了闪存扇区。 JFFS2 附加文件而是重写整个扇区,并且具有崩溃/ 掉电安全保护这一功能。 106 MTD 设备与JFFS 文件系统  这可能是最重要的一点:JFFS2 是 专门为象闪存芯片那样的嵌入式 设备创建的,所以它的整个设计 提供了更好的闪存管理。  除了JFFS2 之外,另外一种的嵌入 式文件系统的选择是YAFFS2. 107 Yaffs 与jffs2 文件系统比较  Nand 上yaffs 文件系统的优势 • 专门为Nand flash 设计的日志文件系 统,提供磨损平衡和调电恢复的鲁棒性。 Yaffs 将文件组织成固定大小(512B ) 的数据段,在进行文件修改时,总是先 写入新的数据块,然后将旧的的数据块 从文件中删除。  jffs /jffs2 文件系统的缺点: •不适合大容量的Nand flash • jffs 的日志通过jffs_node 建立在RAM中,占用RAM 空间:对于128MB 的Nand大概需要4MB 的空间来维护节点 • 启动的时候需要扫描日志节点,不适合 大容量的Nand flash 108 tmpfs 文件系统 当 Linux 运行于嵌入式设备上 时, 设备就成为功能齐全的单元,许 多守护进程会在后台运行并生成许多 日志消息。另外,所有内核日志记录 机制,象 syslogd 、dmesg 和 klogd ,会在 /var 和 /tmp 目录下生 成许多消息。由于这些进程产生了大 量数据,所以允许将所有这些写操作 都发生在闪存是不可取的。由于在重 新引导时这些消息不需要持久存储, 所以这个问题的解决方案是使用 tmpfs 。 109  tmpfs 是基于内存的文件系统,它主 要用于减少对系统的不必要的闪存写操作 这一唯一目的。因为 tmpfs 驻留在 RAM 中,所以写/读/擦除的操作发生在 RAM 中而不是在闪存中。因此,日志消息写入 RAM 而不是闪存中,在重新引导时不会保 留它们。tmpfs 还使用磁盘交换空间来存 储,并且当为存储文件而请求页面时,使 用虚拟内存(VM)子系统。 110  tmpfs 的优点包括: a) 动态文件系统大小 — 文件系统大小 可以根据被复制、创建或删除的文件或 目录的数量来缩放。使得能够最理想地 使用内存。 b) 速度 — 因为 tmpfs 驻留在 RAM, 所以读和写几乎都是瞬时的。即使以交 换的形式存储文件,I/O 操作的速度仍 非常快。  tmpfs 的一个缺点是当系统重新引 导时会丢失所有数据。因此,重 要的数据不能存储在 tmpfs 上。 111 linux 进程间通信进程间通信进程间通信进程间通信  进程间通信概述  管道通信  信号  共享内存  消息队列 112 进程间通信概述  进程间通信有如下一些目的: 数据传输:一个进程需要将它的数据 发送给另一个进程,发送的数据量在 一个字节到几兆字节之间。 共享数据:多个进程想要操作共享数 据,一个进程对共享数据的修改,别 的进程应该立刻看到。 通知事件:一个进程需要向另一个或 一组进程发送消息,通知它(它们) 发生了某种事件(如进程终止时要通 知父进程)。 资源共享:多个进程之间共享同样的 资源。为了作到这一点,需要内核提 供锁和同步机制。 进程控制:有些进程希望完全控制另 一个进程的执行(如Debug 进程), 此时控制进程希望能够拦截另一个进 程的所有陷入和异常,并能够及时知 道它的状态改变。 113 进程间通信概述  linux 下的进程通信手段基本上是从Unix 平台上 的进程通信手段继承而来的。  AT&T 的贝尔实验室对Unix 早期的进程间通信手 段进行了系统的改进和扩充,形成“system V IPC”,通信进程局限在单个计算机内。  BSD(加州大学伯克利分校的伯克利软件发布中 心)则跳过单个计算机的限制,形成了基于套 接口(socket )的进程间通信机制。 114 进程间通信概述  现在linux 使用的进程间通信方式:  (1)管道(pipe )和有名管道 (FIFO)  (2)信号(signal )  (3)消息队列  (4)共享内存  (5)信号量  (6)套接字(socket ) 115 管道通信  普通的Linux shell 都允许重定向,而重定向使 用的就是管道。例如:  ps | grep vsftpd  管道是单向的、先进先出的、无结构的、固定 大小的字节流,它把一个进程的标准输出和另一个 进程的标准输入连接在一起。写进程在管道的尾端 写入数据,读进程在管道的首端读出数据。数据读 出后将从管道中移走,其它读进程都不能再读到这 些数据。管道提供了简单的流控制机制。进程试图 读空管道时,在有数据写入管道前,进程将一直阻 塞。同样,管道已经满时,进程再试图写管道,在 其它进程从管道中移走数据之前,写进程将一直阻 塞。  管道主要用于不同进程间通信。 116  子进程写入和父进程读的命名管道: 关闭父进程fd[1] 和 子进 程[0] 117 信号通信  信号概述  信号是软件中断。信号(signal) 机制是 Unix 系统中最为古老的进程之间的通信机 制。它用于在一个或多个进程之间传递异 步信号。  很多条件可以产生一个信号。  当用户按某些终端键时,产生信号。在 终端上按DELETE 键通常产生中断信号 (SIGINT )。这是停止一个已失去控制程 序的方法。(第11 章将说明此信号可被映 射为终端上的任一字符。)  硬件异常产生信号:除数为0、无效的 存储访问等等。这些条件通常由硬件检测 到,并将其通知内核。然后内核为该条件 发生时正在运行的进程产生适当的信号。 例如,对执行一个无效存储访问的进程产 生一个SIGSEGV。 118  进程用kill( 2 ) 函数可将信号发送给另 一个进程或进程组。自然,有些限制:接 收信号进程和发送信号进程的所有者必须 相同,或发送信号进程的所有者必须是超 级用户。  用户可用kill( 1 ) 命令将信号发送给其 他进程。此程序是kill 函数的界面。常用此 命令终止一个失控的后台进程。  当检测到某种软件条件已经发生,并将 其通知有关进程时也产生信号。这里并不 是指硬件产生条件(如被0除),而是软 件条件。例如SIGURG ( 在网络连接上传来 非规定波特率的数据)、SIGPIPE ( 在管道 的读进程已终止后一个进程写此管道),以 及SIGALRM( 进程所设置的闹钟时间已经超 时)。 119  内核为进程生产信号,来响应不同的事 件,这些事件就是信号源。主要的信号源 如下:  异常:进程运行过程中出现异常;  其它进程:一个进程可以向另一个 或一组进程发送信号;  终端中断:Ctrl-C,Ctrl-\等;  作业控制:前台、后台进程的管 理;  分配额:CPU 超时或文件大小突破 限制;  通知:通知进程某事件发生,如I/O 就绪等;  报警:计时器到期。 120  下面是几个常见的信号。  SIGHUP: 从终端上发出的结束信号;  SIGINT : 来自键盘的中断信号(Ctrl- C);  SIGQUIT :来自键盘的退出信号(Ctrl- \);  SIGFPE : 浮点异常信号(例如浮点运 算溢出);  SIGKILL :该信号结束接收信号的进 程;  SIGALRM :进程的定时器到期时,发送 该信号;  SIGTERM:kill 命令发出的信号;  SIGCHLD :标识子进程停止或结束的信 号;  SIGSTOP:来自键盘(Ctrl-Z)或调试 程序的停止执行信号 121  可以要求系统在某个信号出现时按照下列 三种方式中的一种进行操作。  (1) 忽略此信号。大多数信号都可使用这种 方式进行处理,但有两种信号却决不能被忽略。 它们是:SIGKILL 和SIGSTOP。这两种信号不 能被忽略的原因是:它们向超级用户提供一种 使进程终止或停止的可靠方法。另外,如果忽 略某些由硬件异常产生的信号(例如非法存储 访问或除以0),则进程的行为是未定义的。  (2) 捕捉信号。为了做到这一点要通知内核 在某种信号发生时,调用一个用户函数。在用 户函数中,可执行用户希望对这种事件进行的 处理。如果捕捉到SIGCHLD 信号,则表示子进 程已经终止,所以此信号的捕捉函数可以调用 waitpid 以取得该子进程的进程ID 以及它的终 止状态。  (3) 执行系统默认动作。对大多数信号的系 统默认动作是终止该进程。 122  每一个信号都有一个缺省动作,它是 当进程没有给这个信号指定处理程序时, 内核对信号的处理。有5种缺省的动作:  异常终止(abort ):在进程的当前目 录下,把进程的地址空间内容、寄存器内 容保存到一个叫做core 的文件中,而后终 止进程。  退出(exit ):不产生core 文件,直接 终止进程。  忽略(ignore ):忽略该信号。  停止(stop ):挂起该进程。  继续(continue ):如果进程被挂起, 则恢复进程的运行。否则,忽略信号。 123 共享内存  共享内存区域是被多个进程共享 的一部分物理内存。如果多个进程 都把该内存区域映射到自己的虚拟 地址空间,则这些进程就都可以直 接访问该共享内存区域,从而可以 通过该区域进行通信。共享内存是 进程间共享数据的一种最快的方 法,一个进程向共享内存区域写入 了数据,共享这个内存区域的所有 进程就可以立刻看到其中的内容。 124 进程一 进程二共享内存 共享内存原理示意图 125  共享内存实现分为两个步骤:  一、创建共享内存,使用shmget 函数。  二、映射共享内存,将这段创建 的共享内存映射到具体的进程空间 去,使用shmat 函数。 126  系统调用:shmget( ) ;  原型:int shmget ( key_t key, int size, int shmflg );  返回值:如果成功,返回共享内存段 标识符。  如果失败,则返回- 1:  errno = EINVAL ( 无效的内存段大小)  EEXIST ( 内存段已经存在, 无法创建)  EIDRM ( 内存段已经被删除)  ENOENT ( 内存段不存在)  EACCES ( 权限不够)  ENOMEM ( 没有足够的内存 来创建内存段) 127  系统调用:shmat();  原型:int shmat ( int shmid, char *shmaddr, int shmflg);  返回值:如果成功,则返回共享内 存段连接到进程中的地址。  如果失败,则返回- 1:  errno = EINVAL ( 无效的IPC ID 值 或者无效的地址)  ENOMEM ( 没有足够的内 存)  EACCES ( 存取权限不够) 128  当一个进程不在需要共享的内存段 时,它将会把内存段从其地址空间中 脱离。  系统调用:shmdt();  调用原型:int shmdt ( char *shmaddr );  返回值:如果失败,则返回- 1:  errno = EINVAL ( 无效的连 接地址)  共享内存实例见:shmadd.c 129 Understanding the Linux Kernel
还剩128页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 10 金币 [ 分享pdf获得金币 ] 3 人已下载

下载pdf

pdf贡献者

hhm4202

贡献于2012-04-25

下载需要 10 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf