⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 (ldd) ch01-linux内核简介(转载).txt

📁 献给ARM初学者
💻 TXT
📖 第 1 页 / 共 2 页
字号:
(LDD) Ch01-Linux内核简介(转载)
      第1章 Linux内核简介
       
       
      世界各地都有人在钻研Linux内核,大多是在写设备驱动程序。尽管每个驱动程序都不一
      样,而且你还要知道自己设备的特殊性,但是这些设备驱动程序的许多原则和基本技术
      技巧都是一样的。通过本书,可以学会写自己的设备驱动程序,并且可以钻研内核的相
      关部分。本书涉及到的是设备无关编程技巧,不会将例子跟特殊设备绑定在一起。
       
      本章没有实际编写代码。但我要介绍一些关于Linux内核的背景概念,这样到我们稍后开
      始介绍实际编程时,就很顺利了。
       
      当你学习编写驱动程序的时候,你也会发现很多关于Linux内核的知识,这对理解你机器
      怎么工作很有帮助,并且还可以知道为什么你的机器没有希望的那么快,或者为什么不
      按照你象要它做的那样做。我们会逐渐介绍一些新概念,先从简单的驱动程序开始,每
      介绍一些新概念都会看到相关例子代码,这些代码都不需要特殊硬件。

      介绍一些新概念都会看到相关例子代码,这些代码都不需要特殊硬件。
       
      驱动程序作者的作用
      作为一个程序员,你可以选择自己的驱动程序,在编程所需时间和结果的灵活性之间做
      个可以接受的权衡。尽管说驱动程序的灵活性看起来有那么点怪,我喜欢这个词是因为
      它强调了设备驱动程序提供的是机制,而不是策略。
       
      机制和策略之间的差别是Unix设计背后最好的点子之一。实际编程中遇到的大多数问题
      都可以被划分成两个部分:“需要作什么”(机制)和“这个程序怎么用”(策略)。
      如果这两个主题是由程序不同部分来承担的,或者是由不同的程序组合一起承担的,那
      么这个软件包就很容易开发,也很适合特殊需求。
       
      举个例子,Unix的图形显示管理在X服务器和窗口管理器之间划了一道线,X服务器了解
      硬件并给用户程序提供唯一的接口,而窗口管理器实现特殊的策略并不需要知道硬件的
      任何信息。人们可以在不同硬件上使用同样的窗口管理器,并且不同用户在同一台工作
      站上可以使用不同的设置。另一个例子是TCP/IP的网络分层结构:操作系统提供抽象的
      套接字操作,是设备无关的,不同服务器主管这个服务。另外,ftpd服务器提供文件传
      输机制,而用户可以使用任何客户端程序;命令行的客户端和图形化界面的客户端都存
      在,并且谁都可以为传输文件写一个新的用户界面。
       
      只要涉及到驱动程序,就会运用这样的功能划分。软盘驱动程序是设备无关的——这不
      仅表现在磁盘是一个连续读写的字节数组上。如何使用设备是应用程序要做的事:tar要
      连续地写数据,而mkfs则为要安装的设备做准备工作,mcopy依赖于设备上存在的特殊数

      连续地写数据,而mkfs则为要安装的设备做准备工作,mcopy依赖于设备上存在的特殊数
      据结构。
       
      在写驱动程序时,程序员应该特别留心这样的基本问题:我们要写内核代码访问硬件,
      但由于不同用户有不同需要,我们不能强迫用户采用什么样的特定策略。设备驱动程序
      应该仅仅处理硬件,将如何使用硬件的问题留给应用程序。如果在提供获得硬件能力的
      同时没有增加限制,我们就说驱动程序是灵活的。不过,有时必须要作一些策略决策。
       
      可以从不同侧面来看你的驱动程序:它是位于应用层和实际设备之间的软件。驱动程序
      的程序员可以选择这个设备应该怎样实现:不同的驱动程序可以提供不同的能力,甚至
      相同的设备也可以提供不同能力。实际驱动程序设计应该是在众多需求之间的一个平衡
      。例如,不同程序可以同时使用同一个设备,而驱动程序的开发者可以完全自由地决定
      如何处理同步机制。你可以实现到设备上的内存映射,而完成独立于硬件的具体能力,
      或者你可以提供给用户函数库,帮助应用程序的程序员在可用原语的基础上实现新策略
      ,或者诸如此类的方法。一个很重要需要考虑的问题就是,如何在提供给用户尽可能多
      的选项,平衡你需要编写所花费的时间,以及为使错误尽可能少而保持代码简单之间的
      平衡。
       
      如果即为同步又为异步操作设计驱动程序,如果允许同时打开多次,并且如果能够发掘
      所有硬件功能,而不用增加软件层“去简化事情”——例如将二进制数据转换成文本或
      者策略相关的操作——那就很容易编写而且很好维护了。达成“策略无关”实际上是软
      件设计的共同目标。
       

       
      实际上,大多数设备驱动程序是和用户程序一起发布的,这些程序可以帮助完成对目标
      设备的配置和访问。这些程序可以是从简单的配置程序到完整的图形应用。通常还要提
      供一个客户端库文件。
       
      本书讨论范围是内核,所以我们不考虑策略问题,也不考虑应用程序或支持库。有时,
      我们会讨论不同策略,以及如何支持这些策略,但我们不会深入到使用一定策略或设备
      编程需要的细节问题。不过你应该可以理解,用户程序是一个软件包的内核,就算策略
      无关的软件包也会和配置文件一起发布,这些文件提供了基本机制上的缺省行为。
       
      划分内核
      在Unix系统中,若干并发进程会参加不同的任务。每个进程都要求获得系统资源,可以
      是计算、内存、网络连接或别的资源。内核是一整块可执行代码,用它来负责处理所有
      这样的请求。尽管在不同的内核任务之间的区别不是总能清楚地标识出来,内核的作用
      还是可以被划分的。如图1-1所示,划分为如下这些部分:
       
      进程管理
       
      内核负责创建和终止进程,并且处理它们和外部世界的联系(输入和输出)。对整个系
      统功能来讲,不同进程之间的通信(通过信号,管道,进程间通信原语)是基本的,这
      也是由内核来处理的。另外,调度器,可能是整个操作系统中最关键的例程,是进程管
      理中的一部分。更广广义的说,内核的进程管理活动实现了在一个CPU上多个进程的抽象
      概念。

      概念。
       
      内存管理
       
      计算机内存是主要资源,而使用内存的策略是影响整个系统性能的关键。内核为每个进
      程在有限可利用的资源上建立了虚拟地址空间。内核不同部分通过一组函数与内存管理
      子系统交互,这些包括从简单的malloc/free到更稀奇古怪的功能。
       
      (图1-1)
       
      文件系统
       
      Unix系统是建立在文件系统这个概念上的;Unix里几乎所有东西都可以看作文件。内核
      在非结构的硬件上建立了结构化的文件系统,这个抽象的文件被系统广泛应用。另外,L
      inux支持多文件系统类型,即,物理介质上对数据的不同组织方法。
       
      设备控制
       
      几乎每种系统操作最后都要映射到物理设备上。除了处理器,内存和少数其他实体外,
      几乎所有设备的控制操作都由设备相关的代码来实现。这些代码就是设备驱动程序。内
      核必须为每个外部设备嵌入设备驱动程序,从硬盘驱动器到键盘和磁带。内核的这方面
      功能就是本书的着眼点。
       

       
      网络
       
      网络必须由操作系统来管理,由于大多数网络操作不是针对于进程的:接收数据包是异
      步事件。数据包必须在进程处理它们以前就被收集,确认和分发。系统通过程序和网络
      接口发送数据包,并且应该可以正确地让程序睡眠,并唤醒等待网络数据的进程。另外
      ,所有路由和地址解析问题是在内核里实现的。
       
      在本书结尾部分的第16章“内核源码的物理布局”里,您可以看到Linux内核的路标,但
      现在这里的话应该足够了。
       
      Linux的一个很好的特征就是,它可以在运行的时候扩展内核代码,也就是说在系统运行
      的时候你可以增加系统的功能。
       
      每个可以增加到内核中的代码称为一个模块。Linux内核支持相当多的模块的类型(或“
      类”),但不仅仅只局限于设备驱动程序。每个模块由目标代码组成(没有连接成完整
      的可执行文件),通过insmod程序它们可以动态连接到运行着的内核中,而通过rmmod程
      序就可以去除这些模块。
       
      在图1-1中,你可以标别出处理不同任务的不同模块类别——根据模块提供的功能,每个
      模块属于一个特定的类。
       
      设备类和模块

      设备类和模块
      在3类设备中,Unix看待设备的方式有所区别,每种方式是为了不同的任务。Linux可以
      以模块的形式加载每种设备类型,因此允许用户在最新版本的内核上实验新硬件,跟随
      内核的开发过程。
       
      一考虑到模块,每个模块通常只实现一个驱动程序,因此是可以分类的。例如,字符设
      备模块,或块设备模块。将模块分成不同的类型或类并不是固定不变的;程序员可以选
      择在单独一整块代码中创建一个模块实现不同的驱动程序。不过好的程序员会为他们实
      现的每一个新功能创建不同模块。
       
      现在回到驱动程序,有如下三种类型:
       
      字符设备
       
      可以象文件一样访问字符设备,字符设备驱动程序负责实现这些行为。这样的驱动程序
      通常会实现open,close,read和write系统调用。系统控制台和并口就是字符设备的例
      子,它们可以很好地用流概念描述。通过文件系统节点可以访问字符设备,例如/dev/tt
      y1和/dev/lp1。在字符设备和普通文件系统间的唯一区别是:普通文件允许在其上来回
      读写,而大多数字符设备仅仅是数据通道,只能顺序读写。当然,也存在这样的字符设
      备,看起来象个数据区,可以来回读取其中的数据。
       
      块设备
       

       
      块设备是文件系统的宿主,如磁盘。在大多数Unix系统中,只能将块设备看作多个块进
      行访问为,一个块设备通常是1K字节数据。Linux允许你象字符设备那样读取块设备——
      允许一次传输任意数目的字节。结果是,块设备和字符设备只在内核内部的管理上有所
      区别,因此也就是在内核/驱动程序间的软件接口上有所区别。就象字符设备一样,每个
      块设备也通过文件系统节点来读写数据,它们之间的不同对用户来说是透明的。块设备
      驱动程序和内核的接口和字符设备驱动程序的接口是一样的,它也通过一个传统的面向
      块的接口与内核通信,但这个接口对用户来说时不可见的。
       
      网络接口
       
      任何网络事务处理都是通过接口实现的,即,可以和其他宿主交换数据的设备。通常,
      接口是一个硬件设备,但也可以象loopback(回路)接口一样是软件工具。网络接口是
      由内核网络子系统驱动的,它负责发送和接收数据包,而且无需了解每次事务是如何映
      射到实际被发送的数据包。尽管“telnet”和“ftp”连接都是面向流的,它们使用同样
      的设备进行传输;但设备并没有看到任何流,仅看到数据报。
       
      由于不是面向流的设备,所以网络接口不能象/dev/tty1那样简单地映射到文件系统的节
      点上。Unix调用这些接口的方式是给它们分配一个独立的名字(如eth0)。这样的名字
      在文件系统中并没有对应项。内核和网络设备驱动程序之间的通信与字符设备驱动程序
      和块设备驱动程序与内核间的通信是完全不一样的。内核不再调用read,write,它调用
      与数据包传送相关的函数。
       

       
      事实上,Linux中还有一类“设备驱动程序模块”:SCSI*设备驱动程序。尽管每个连接
      到SCSI总线上的外设在/dev目录中不是字符设备就是块设备,但软件的内部组织并不完
      全同。
       
      正如网络接口给网络子系统提供硬件相关的功能一样,SCSI控制器提供给SCSI子系统如
      何访问实际接口电缆。SCSI是计算机和外设之间的通信协议,每种SCSI设备都响应相同
      的协议,与计算机插的是哪种控制板没有关系。因此,Linux内核嵌入一个所谓SCSI“实
      现”(即,文件操作到SCSI通信协议的映射)。驱动程序编写人员必须在SCSI抽象层和
      物理电缆之间实现这种映射。这种映射依赖于SCSI控制器,却与SCSI电缆上连接的设备
      无关。
       
      除了设备驱动程序,还有一些别的模块化加载到核心中的驱动程序,可以是软件,也可
      以时硬件。并非实现驱动程序的模块中最重要的一类是文件系统。文件系统类型是与为
      了表示目录和文件等实体的信息的组织方式相关的。因此这种实体不是“设备驱动程序

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -