网管联盟 | 网管论坛 | 网管u家 | 网管博客 | 网管软件 | 网管求职 | 小游戏 | 网管搜索 | 网管原创 | 网管聚合 | 网管读摘 | 网管焦点 | 世界素材 | 会员投稿 | 会员中心 
中国网管联盟
Windows Linux Cisco 网络技术 数据库 黑客攻防 DotNet Java PHP 认证 新闻资讯 服务器 存储资讯 网络设备 网管学堂 技术专题 焦点 网吧频道
 当前位置: > bitsCN.com > linux > 系统管理 > 内核技术 > Linux操作系统源代码详细分析  

Linux操作系统源代码详细分析

2006-11-03  作者:网管整理  来源:bitsCN.com  点评 投稿 收藏

16834:调用schedule(26686行,在第7章中讨论)将CPU转移给另一个进程。直到进程再次获得CPU时,对schedule的调用才会返回。这种情况只有当等待队列中的进程被唤醒时才会发生。

网管u家u.bitsCN.com

16836:进程已经退出了,因此条件必定已经得到了满足。进程重置TASK_RUNNING的状态(16188行),使其适合CPU运行。

网管联盟bitsCN@com

16837:通过调用remove_wait_queue(16814行)将进程从等待队列中移去。wait_event_interruptible和__wait_event_interruptible(分别参见16868行和16847)基本上与wait_event和__wait_event相同,但不同的是它们允许休眠的进程可以被信号中断。信号将在第6章中介绍。

网管论坛bbs_bitsCN_com

请注意wait_event是被如下结构所包含的。

网管u家u.bitsCN.com

和do/while(0)技巧一样,这样可以使被封闭起来的代码能够像一个单元一样运行。这样的封闭代码就是一个独立的表达式,而不是一个独立的语句。也就是说,它可以求值以供其他更复杂的表达式使用。发生这种情况的原因主要在于一些不可移植的gcc特有代码的存在。通过使用这类技巧,一个程序块中的最后一个表达式的值将定义为整个程序块的最终值。当在表达式中使用wait_event_interruptible时,执行宏体后赋__ret的值为宏体的值(参见16873行)。对于有Lisp背景知识的程序员来说,这是个很常见的概念。但是如果你仅仅了解一点C和其他一些相关的过程性程序设计语言,你可能就会觉得比较奇怪。 中国网管论坛bbs.bitsCN.com

__wake_up 网管u家u.bitsCN.com

26829:该函数用来唤醒等待队列中正在休眠的进程。它由wake_up和wake_up_ interruptible调用(请分别参见16612行和16614行)。这些宏提供mode参数,只有状态满足mode所包含的状态之一的进程才可能被唤醒。

网管u家u.bitsCN.com

26833:正如将在第10章中详细讨论的那样,锁(lock)是用来限制对资源的访问,这在SMP逻辑单元中尤其重要,因为在这种情况下当一个CPU在修改某数据结构时,另一个CPU可能正在从该数据结构中读取数据,或者也有可能两个CPU同时对同一个数据结构进行修改,等等。在这种情况下,受保护的资源显然是等待队列。非常有趣的是所有的等待队列都使用同一个锁来保护。虽然这种方法要比为每一个等待队列定义一个新锁简单得多,但是这就意味着SMP逻辑单元可能经常会发现自己正在等待一个实际上并不必须的锁。

网管网www_bitscn_com

26838:本段代码遍历非空队列,为队列中正确状态的每一个进程调用wake_up_process(26356行)。如前所述,进程(队列节点)在此可能并没有从队列中移走。这在很大程度上是由于即使队列中的进程正在被唤醒,它仍然可能希望继续存在于等待队列中,这一点正如我们在__wait_event中发现的问题一样。 网管联盟bitsCN_com

2.2.3 内核模块 网管下载dl.bitscn.com

整个内核并不需要同时装入内存。应该确认,为保证系统能够正常运行,一些特定的内核必须总是驻留在内存中,例如,进程调度代码就必须常驻内存。但是内核其他部分,例如大部分的设备驱动就应该仅在内核需要的时候才装载,而在其他情况下则无需占用内存。 网管联盟bitsCN@com

举例来说,只有在内核真正和CD-ROM通讯时才需要使用完成内核与CD-ROM通讯的设备驱动程序,因此内核可以被设置为在和设备通讯之前才装载相应代码。内核完成和设备的通讯之后可以将这部分代码丢弃。也就是说,一旦代码不再需要,就可以从内存中移走。系统运行过程中可以增减的这部分内核称为内核模块。

网管u家u.bitscn@com

内核模块的优点是可以简化内核自身的开发。假设你购买了一个新的高速CD-ROM驱动器,但是现有的CD-ROM驱动程序并不支持该设备。你自然就希望增加对这种高速模式的支持以提高系统光驱设备的性能。如果作为内核模块来编译驱动程序,你的工作将会方便得多:编译驱动程序、加载到内核、测试、卸载驱动程序、修改驱动程序、再次加载驱动程序到内核、测试,如此周而复始。如果你的驱动程序是直接编辑在内核中的,那么你就必须重新编译整个内核并且在每次修改驱动程序之后重新启动机器。这样慢得很多。

网管下载dl.bitscn.com

自然,你也必须留意内核模块。对于指明其他内核模块在磁盘上的驻留位置的那些模块,一定不能从内存中卸载,否则,内核将只能通过访问磁盘来装载处理磁盘访问的内核模块,这是不可能实现的。这也是我们要选择把部分内核作为模块编译还是直接编译进内核使其常驻内存的又一个原因。知道自己系统的设置方式,因而也就可以选择正确使用的方式(如果为了确保安全,可以简单的忽略内核模块系统的优点,而把所有的内容都编译到内核里面)。

网管u家u.bitsCN.com

内核模块会带来一些速度上的损失,这是因为一些必需的代码现在并不在RAM中,必需要从磁盘读入。但是整个系统的性能通常会有所提高,这主要是因为通过丢弃暂时不使用的模块可以释放出额外的RAM供应用程序使用。如果这部分内存被内核所占用,应用程序将只能更加频繁地进行磁盘交换,而这种磁盘交换会显著地降低应用程序的性能(磁盘交换将在第8章中讨论)。

中国网管联盟bitsCN.com

内核模块还会带来因复杂度的增加所造成的开销,这是因为在系统运行的过程中,移进移出部分内核需要额外的代码。然而,复杂度的开销是可以管理的。通过使用外部程序来代理一些必需的工作还可以更进一步降低复杂度的开销(更为确切的说法是,这样做不是减少了复杂度的开销,而是把复杂度的开销重新分配了一下)。这是对内核模块原理的一个小小的扩展:即使是内核的支持模块,对于内核来说也只是外部的、部分可用的,只有在需要的时候才被装入内存。 网管网www_bitscn_com

通常用于这种目的程序称为modprobe。有关的modprobe代码超出了本书的范围,但是在Linux的每个发行版本中都包含有它。本节的剩余部分将讨论同modprobe协同工作,以装载内核模块的内核代码。 中国网管联盟bitsCN.com

1. request_module 网管u家u.bitsCN.com

24432:作为函数说明之前的注释,request_module是一个函数。内核的其他模块在需要装载其他内核模块的时候,都必须调用这个函数。就像内核处理其他工作一样,这种调用也是为当前运行的进程进行的。从进程的角度来看,这种调用的请求通常是隐含的—正在执行进程其他请求的内核可能会发现,必须调入一个模块才能够完成该请求。例如,请参见10070行,这里是一些将在第7章中讨论的代码。

网管网www_bitscn_com

24446:以内核中的一个独立进程的形式执行exec_modprobe函数(24384行)。这并不能只通过函数的简单调用实现,因为exec_modprobe要继续调用exec来执行一个程序。因此,对函数exec_modprobe的简单调用将永远不会有返回。 网管联盟bitsCN@com

这和使用fork以准备exec调用十分类似,你可以认为kernel_thread对内核来说就是较低版本的fork,虽然两者有很大不同。fork是从指定函数开始执行新的进程,而不是从调用者的当前位置开始运行。正如fork一样,kernel_thread返回的值是新进程的进程号。

网管联盟bitsCN@com

24448:和fork一样,从kernel_thread返回的负值表示内部错误。

网管网www.bitscn.com

24455:正如函数中论述的一样,大部分的信号将因当前进程而被暂时阻塞。 网管网www_bitscn_com

24462:等待exec_modprobe执行完毕,同时指出所需要的模块是已经成功装入内存,还是装载失败了。

网管u家u.bitsCN.com

24465:结束运行,恢复信号。如果exec_modprobe返回错误代码,则打印错误消息。 网管下载dl.bitscn.com

2. exec_modprobe 网管u家u.bitscn@com

24384:exec_modprobe运行为内核增加内核模块的程序。这里的模块名是一个void*的指针,而不是char*的指针。原因简单说来就是kernel_thread 产生的函数通常都使用void*指针参数。

网管u家u.bitsCN.com

24386:设置modprobe的参数列表和环境。modprobe_path(24363行)用来定位modprobe程序的位置。它可以通过内核的sysctl特性来修改,这一点将在第11章中介绍(参见30388行)。这意味着root可以动态选择不同于/sbin/modprobe的程序来运行,以适应当modprobe被安装到其他地方或者使用修改过的modprobe替换掉了原有的modprobe之类的情况。

网管网www_bitscn_com


TAGs   分析   详细   源代码   操作系统   内核   使用   代码   一个   可以      
 上一篇:没有了   下一篇:内核基于嵌入式Linux的PocketIX系统
Linux操作系统源代码详细分析 评论:
loading.. 评论加载中…
评论:请自觉遵守互联网相关政策法规,评论不得超过250字。

验证码: 注册用户
本类热门排行:
最新推荐文章:
网管论坛交流: