《嵌入式系统第六章嵌入式Linux操作系统.ppt》由会员分享,可在线阅读,更多相关《嵌入式系统第六章嵌入式Linux操作系统.ppt(87页珍藏版)》请在三一办公上搜索。
1、第5章 嵌入式Linux操作系统,5.1 与Linux相关术语,GNUGUN项目(GNU Project)开始于1984年,主要由自由软件基金(Free Software FoundationFSF)资助的一个项目,目标是开发一个自由的、UNIX类型的操作系统,称为GNU系统。GNU是“GNUs Not UNIX”的首字母的递归缩写。GPL所有的GNU软件和派生工作均遵循GNU通用公共许可证,即GPL。,5.1 与Linux相关术语,GNU LGPL(Library General Public License程序库公共许可证)允许用户在自己的应用程序中使用程序库,即使不公开自己的源代码。用户
2、必须能够获得在应用程序中使用的程序库的源代码,并且允许用户对这些程序库进行修改。遵循LGPL的一种方法是,随应用程序一起发布目标代码以及可以将这些目标程序和受LGPL保护的程序库链接起来的makefile文件。遵循LGPL的另一种比较好的方法是使用动态链接。FSF:Free Software Foundation 自由软件基金会,5.2 嵌入式Linux操作系统,5.2.1 Linux介绍 技术上说Linux是一个内核。“内核”指的是一个提供硬件抽象层、磁盘及文件系统控制、多任务等功能的系统软件。一个内核不是一套完成的操作系统,还需要加载库文件、应用程序等,才可以形成完整的操作系统。一套基于L
3、inux内核的完整操作系统叫做Linux操作系统。Linux操作系统具备结构清晰、功能简介等特征,逐渐成为一个稳定可靠、功能完善的操作系统。作为一个操作系统,Linux几乎满足当今Unix操作系统的所有要求。,Linux具有的特点,1、完全免费2、开放型3、支持多用户访问和多任务编程 4、良好的用户界面5、支持多种文件系统 6、采用虚拟内存管理技术7、设备独立性8、丰富的网络功能9、可靠的系统安全10、良好的可移植性,完整的Linux架构图,作为一个完成的操作系统,Linux具有稳定而强大的功能,想要访问任何非自己的存储器空间的进程只能通过系统调用来达成。一般进程是处于用户模式底下,而运行系统
4、调用时会被切换成内核模式,所有的特殊指令只能在内核模式运行,此措施让内核可以完美管理系统内部与外部设备,并且拒绝无权限的进程提出的请求。因此理论上任何应用程序运行时的错误,都不可能让系统崩溃。,5.2.2 Linux作为嵌入式操作系统的优势1、支持多种硬件平台 2、占有较少的硬件资源3、高可定制性 4、具有实时处理能力 5、具备强大的网络功能 Linux作为嵌入式操作系统也存在着不足,主要表现在集成开发环境有待改善。,5.2.3 进程管理进程的基本概念 进程就是运行中的程序。一个运行着的程序,可能有多个进程。对于进程来说,可以看成是一个具有独立功能的程序关于某个数据集合的一次可以并发执行的运行
5、活动,是处于活动状态的计算机程序。,进程的属性 进程的定义:一个进程是一个程序的一次执行的过程;程序是静态的,它是一些保存在磁盘上的可执行的代码和数据集合;进程是一个动态的概念,它是Linux系统的基本的调度单位。一个进程由如下元素组成:程序读取的上下文,它表示程序读取执行的状态。程序当前执行的目录。程序服务的文件和目录。程序访问的权限。内存和其他分配给进程的系统资源。,Linux进程中最知名的属性就是它的进程号(Process Idenity Number,PID)和它的父进程号(Parent Process ID,PPID)。PID、PPID都是非零正整数。一个PID唯一地标识一个进程。一
6、个进程创建新进程称为创建了子进程(Child Process)。相反地,创建子进程的进程称为父进程。所有进程追溯其祖先最终都会落到进程号为1的进程身上,这个进程叫做init进程,是内核自举后第一个启动的进程。init进程扮演终结父进程的角色。因为init进程永远不会被终止,所以系统总是可以确信它的存在,并在必要的时候以它为参照。,Linux下进程的结构 代码段是存放了程序代码的数据,假如机器中有数个进程运行相同的一个程序,那么它们就可以使用同一个代码段。而数据段则存放程序的全局变量、常数及动态数据分配的数据空间。堆栈段存放的就是子程序的返回地址、子程序的参数及程序的局部变量。堆栈段包含在进程控
7、制块PCB(Process Control Block)中。PCB处于进程核心堆栈的底部,不需要额外分配空间。,进程状态进程在生存周期中的各种状态及状态的转换。Linux系统的进程状态模型的各种状态:用户状态:进程在用户状态下运行的状态。内核状态:进程在内核状态下运行的状态。内存中就绪:进程没有执行,但处于就绪状态,只要内核调度它,就可以执行。内存中睡眠:进程正在睡眠并且进程存储在内存中,没有被交换到SWAP设备。就绪且换出:进程处于就绪状态,但是必须把它换入内存,内核才能再次调度它运行。睡眠且换出:进程正在睡眠,且被换出内存。被抢先:进程从内核状态返回用户状态时,内核抢先于它做了上下文切换,
8、调度了另一个进程。原先这个进程就处于被抢先状态。创建状态:进程刚被创建。该进程存在,但既不是就绪状态,也不是睡眠状态。这个状态是除了进程0以外的所有进程的最初状态。僵死状态(zombie):进程调用exit结束,进程不再存在,但在进程表项中仍有记录,该记录可由父进程收集。,进程的创建与结束 在Linux系统中,通常使用fork()系统调用用来复制一个现有进程,从而创建一个全新的进程。被复制的进程被称为父进程,新产生的进程被称为子进程。为了方便用户处理父进程与子进程之间的一些事物,Linux允许父进程在创建了进程之后,通过调用wait()先进入等待状态,以使子进程先运行,然后再决定自己的进一步行
9、为,这成为父进程的阻塞方式。进程的结束可以使用exit()系统调用,无论在执行到什么位置,只要执行到exit系统调用,进程会停止所有操作并将其占用的资源释放掉。,进程的创建与结束有一个更简单的执行其他程序的函数system,参数string传递给一个命令解释器(一般为sh)执行,即string被解释为一条命令,由sh执行该命令。除了system之外,系统调用exec来执行一个可执行文件,来代替当前进程的执行映像。系统调用exit的功能是终止发出调用的进程。父进程和子进程的关系是管理和被管理的关系,当父进程终止时,子进程也随之而终止。但子进程终止时,父进程并不一定终止。,进程的组成,在Linux
10、中,进程是以进程号PID(Process ID)作为标示。任何对进程进行的操作都要给与其相应的PID号。每个进程都属于一个用户,进程要配备其所属的用户编号UID。此外,每个进程都属于多个用户组,所以进程还要配备其归属的用户组编号GID的数组。进程运行的环境成为进程上下文。Linux中进程的上下文由进程控制块PCB(Process Control Block)、正文段、数据段以及用户堆栈组成。其中,正文段存放该进程的可执行代码,数据段存放进程中静态产生的数据结构,而PCB包括进程的编号、状态、优先级以及正文段和数据段中数据分布的大概情况。一个称作进程表(Process Table)的链表结构将系
11、统中所有的PCB块联系起来。,启动一个进程有两个主要途径:手工启动和调度启动,后者是事先进行设置,根据用户要求自行启动。由用户输入命令,直接启动一个进程便是手工启动进程。但手工启动进程又可以分为很多种,根据启动的进程类型不同、性质不同,实际结果也不一样。(1)前台启动前台启动是手工启动一个进程的最常用的方式。用户键入一个命令“df”,就已经启动了一个进程,而且是一个前台的进程。(2)后台启动直接从后台手工启动一个进程用得比较少一些,除非是该进程甚为耗时,且用户也不急着需要结果。,进程的状态和调度 一般来说,所有进程都要经历三种状态,即运行态、就绪态和阻塞态,在Linux系统中将上述三种状态进行
12、重新组织,得到了Linux进程的几个状态:,进程的调度为了让Linux来管理系统中的进程,每个进程用一个task_struct数据结构来表示(任务与进程在Linux中可以混用)。数组task包含指向系统中所有task_struct结构的指针。这意味着系统中的最大进程数目受task数组大小的限制,缺省值一般为512。创建新进程时,Linux将从系统内存中分配一个task_struct结构并将其加入task数组。当前运行进程的结构用current指针来指示。,Linux还支持实时进程。这些进程必须对外部时间作出快速反应(这就是“实时”的意思),系统将区分对待这些进程和其他进程。虽然task_str
13、uct数据结构庞大而复杂,但它可以分成一些功能组成部分:State 进程在执行过程中会根据环境来改变state。SchedulingInformation 调度器需要这些信息以便判定系统中哪个进程最迫切需要运行。Identifiers 系统中每个进程都有进程标志。进程标志并不是task数组的索引,它仅仅是个数字。Inter-ProcessCommunication Linux支持经典的Unix IPC机制。Links Linux系统中所有进程都是相互联系的。TimesandTimers 核心需要记录进程的创建时间以及在其生命期中消耗的CPU时间。Filesystem 进程可以自由地打开或关闭文
14、件,进程的task_struct结构中包含一个指向每个打开文件描叙符的指针以及指向两个VFSinode的指针。Virtualmemory 多数进程都有一些虚拟内存(核心线程和后台进程没有),Linux核心必须跟踪虚拟内存与系统物理内存的映射关系。ProcessorSpecificContext 进程可以认为是系统当前状态的总和。,Linux使用用户和组标志符来检查对系统中文件和可执行映象的访问权限。Linux系统中所有的文件都有所有者和允许的权限,这些权限描叙了系统使用者对文件或者目录的使用权。基本的权限是读、写和可执行,这些权限被分配给三类用户:文件的所有者,属于相同组的进程以及系统中所有进
15、程。每类用户具有不同的权限,例如一个文件允许其拥有者读写,但是同组的只能读而其他进程不允许访问。,task_struct结构中有四对进程和组标志符:uid,gid 表示运行进程的用户标志符和组标志符。effectiveuidandgid 有些程序可以在执行过程中将执行进程的uid和gid改成其程序自身的uid和gid(保存在描叙可执行映象的VFSinode属性中)。这些程序被称为setuid程序,常在严格控制对某些服务的访问时使用,特别是那些为别的进程而运行的进程,例如网络后台进程。有效uid和gid是那些setuid执行过程在执行时变化出的uid和gid。当进程试图访问特权数据或代码时,核心
16、将检查进程的有效gid和uid。filesystemuidandgid 它们和有效uid和gid相似但用来检验进程的文件系统访问权限。如运行在用户模式下的NFS服务器存取文件时,NFS文件系统将使用这些标志符。此例中只有文件系统uid和gid发生了改变(而非有效uid和gid)。这样可以避免恶意用户向NFS服务器发送KILL信号。saveduidandgid POSIX标准中要求实现这两个标志符,它们被那些通过系统调用改变进程uid和gid的程序使用。当进程的原始uid和gid变化时,它们被用来保存真正的uid和gid。,进程调度机制的设计,还对系统复杂性有着极大的影响,常常会由于实现的复杂程
17、度而在功能和性能方面做出必要的权衡和让步。另外,进度调度的机制还要考虑到“公正性”,让系统所有进程都有机会向前推进,尽管其进度各有不同,并最终受到CPU速度和负载的影响。更重要的是,还要防止死锁的发生,以及防止对CPU能力的不合理使用,也就是说要防止CPU尚有能力且有进程等执行,却由于某种原因而长时间得不到执行的情况。一旦这些情况发生,调度机制还能识别与化解。,调度器必须选择最迫切需要运行而且可以执行的进程来执行。可运行进程是一个只等待CPU资源的进程。Linux使用基于优先级的简单调度算法来选择下一个运行进程。当选定新进程后,系统必须将当前进程的状态,处理器中的寄存器以及上下文状态保存到ta
18、sk_struct结构中。同时它将重新设置新进程的状态并将系统控制权交给此进程。为了将CPU时间合理的分配给系统中每个可执行进程,调度管理器必须将这些时间信息也保存在task_struct中。,在每个进程的task_struct结构中有以下四项:policy、priority、counter、rt_priority。这四项是选择进程的依据。其中,policy是进程的调度策略,用来区分实时进程和普通进程,实时进程优先于普通进程运行;priority是进程(包括实时和普通)的静态优先级;counter是进程剩余的时间片,它的起始值就是priority的值;由于counter在后面计算一个处于可运行
19、状态的进程值得运行的程度goodness时起重要作用,因此,counter也可以看作是进程的动态优先级。rt_priority是实时进程特有的,用于实时进程间的选择。,进程调度的核心在几个位置调用调度管理器。如当前进程被放入等待队列后运行或者系统调用结束时,以及从系统模式返回用户模式时。此时系统时钟将当前进程的counter值设为0以驱动调度管理器。每次调度管理器运行时将进行下列操作:kernelwork 调度管理器运行底层处理程序并处理调度任务队列。Currentprocess 当选定其他进程运行之前必须对当前进程进行一些处理。,如果当前进程的调度策略是时间片轮转,则它被放回到运行队列。如果
20、任务可中断且从上次被调度后接收到了一个信号,则它的状态变为运行态。如果当前进程的状态是Running,则状态保持不变。那些既不处于Running状态又不是可中断的进程将会从运行队列中删除。这意味着调度管理器选择运行进程时不会将这些进程考虑在内。调度器在运行队列中选择一个最迫切需要运行的进程。如果运行队列中存在实时进程(那些具有实时调度策略的进程),则它们比普通进程更多的优先级权值。在存在多个相同优先级进程的平衡系统中,每个进程被依次执行,这就是RoundRobin策略。然而由于进程经常需要等待某些资源,所以它们的运行顺序也常发变化。如果系统选择其他进程运行,则必须被挂起当前进程且开始执行新进程
21、。进程执行时将使用寄存器、物理内存以及CPU。每次调用子程序时,它将参数放在寄存器中并把返回地址放置在堆栈中,所以调度管理器总是运行在当前进程的上下文。,进程的切换发生在调度管理器运行之后。以前进程保存的上下文与当前进程加载时的上下文相同,包括进程程序计数器和寄存器内容。如果以前或者当前进程使用了虚拟内存,则系统必须更新其页表入口,这与具体体系结构有关。如果处理器使用了转换旁视缓冲或者缓冲了页表入口(如AlphaAXP),那么必须冲刷以前运行进程的页表入口。,5.2.4 存储管理在这里所说的存储管理一般指的是内存管理,在计算机业界,内存这个名词被广泛用来称呼 RAM(随机存取内存),计算机使用
22、随机存取内存来储存执行作业所须的暂时指令以及数据,以使计算机的 CPU能够更快速读取储存在内存的指令及数据。下面介绍Linux存储器管理几个基本概念:,存储管理的任务 存储管理是Linux中负责管理内存的模块。存储管理的任务有以下几点:屏蔽各种硬件的内存结构,并向上层返回同意的访问界面。Linux支持各种各样的硬件体系结构。对每种硬件结构,其内存的组织形式各不相同。然而,对于用户的应用程序来说,总是希望提供一个同意的界面以供调用。这样,存储模块就自然要担负这个屏蔽和转化的任务。解决进程状态下内存不足的问题,按需调页。随着硬件的发展,内存的增大,软件业相应地向着大规模方向发展。在一个多进程系统中
23、,所有进程所占用的内存总和往往会超过物理内存容量。这样就需要存储管理实现能够利用副存储器(比如硬盘)进行辅助存储的功能。存储管理机制甚至还能够处理单个进程所占用内存超过主存大小的情况。阻止进程肆意访问其他进程的地址空间和内核地址空间。由于并发执行的进程所在的地址空间都不能冲突,而进程太多,物理内存空间根本不够,故需要模拟出一个更大的虚拟逻辑空间提供给上层应用程序,并通过一个可靠的机制建立起逻辑空间到物理空间的映射关系。为进程中通信所需要的共享内存提供必要的基础。对于上层用户来讲,共享内存和普通内存是两种概念;然而对于存储管理系统来讲,这两者却都是内存中的一部分,所有内存空间的任一部分都可被划为
24、共享内存使用。因此,实现共享内存的任务就需要由存储管理模块来实现,虚拟内存 虚拟内存是现代操作系统的重要特征。对于一个多进程的操作系统来说,每个进程都要占据自己唯一的内存地址空间。虚拟内存的基本原理是将内存中一部分近期不需要的内容移出到外存上,从而让出一块内存空间,以供其他需要的内存使用。当要访问到那些已经被调出到外存的数据时,存储管理要将内存中一部分不常被访问的数据调出,让出一块空间以供需要的数据调入内存。,页面模式 页面为存储管理中调入调出的基本单位。在存储管理中,将内存划分为长度相等的页面。Linux将每个用户进程4GB长度的虚拟内存划分成固定大小的页面。其中,03GB是用户态空间,由各
25、进程独占;34GB是内核态空间,由所有进程共享,但只有内核态的进程才能访问。,按需调页 当进程访问到某个虚存地址,却发现该地址所对应的物理页面已经被换出内存时,系统会自动产生一个硬件中断,即缺页中断。在中断产生后,系统会自动调用相应的中断处理程序,来将所需的页面从外存调入,或者干脆新建一个空白页面。这个过程就叫做按需调页。,对换 对于虚拟内存页面来说,总是要将其改动过的内容写回到外存中,才能够将其丢弃。一个被更改过的内存页面,但还没有将其内容写到外存中,就称之为“脏页面”。在换入页面时,首先考虑的肯定是将“干净的”页面直接丢弃,然后将外存数据写进来,因为这样不会破坏数据的完整性。然而这是一个矛
26、盾,内存调用者希望尽可能少地进行外存的刷新,这个结果造成内存中“脏页面”不断增加,而换入程序又希望尽可能多一些“干净”页面,以便使它们可以很方便地将数据调入。于是,收拾垃圾的工作就由一个被称作“对换”(swap)的程序来完成。,Linux中存储器管理的相关概念及实现,伙伴算法Linux的伙伴算法把所有的空闲页面分为10个块组,每组中块的大小是2的幂次方个页面。工作原理:如果要求要求分配一个大小为M个页面的块,伙伴算法会先到与要求分配的M个页面大小最接近的空闲块链表中查找,看是否有这样的一个空闲块。如果有,就直接分配;如果没有,该算法就会到下一个更大的空闲块链表中查找一个空闲块,如果有,就将该空
27、闲块分为两等份,一份分配出去,另一份就挂入下一级的空闲块链表中;如果没有,就继续向更大的空闲块链表中查找,直到查找完所有更大的空闲块链表都没找到空闲块为止(空闲块链表最大为512个页面),如果没有的就放弃分配,并发出出错信息。以上过程的逆过程就是块的释放过程,这也是该算法名字的来由。满足以下条件的两个块称为伙伴:(1)两个块的大小相同;(2)两个块的物理地址连续。,slab Slab是Linux操作系统的一种内存分配机制。Slab中引入了对象这个概念,所谓对象就是存放一组数据结构的内存区,其方法就是构造或析构函数,构造函数用于初始化数据结构所在的内存区,而析构函数收回相应的内存区。实际上,Li
28、nux中对Slab分配模式有所改进,它对内存区的处理并不需要进行初始化或回收。出于效率的考虑,Linux并不调用对象的构造或析构函数,而是把指向这两个函数的指针都置为空。Linux中引入slab的丰要目的是为了减少对伙伴算法的调用次数。缓冲区就是主存中的一片区域,把这片区域划分为多个块,每块就是一个Slab,每个Slab由一个或多个页面组成,每个Slab中存放的就是对象。对于小对象,就把slab的描述结构slab_t放在该slab中;对于大对象,则把slab结构游离出来,集中存放。关于slab中的着色区再给予具体描述。,缓冲区每个缓冲区还有一个轮转锁(spinlock),在对链表进行修改时用这
29、个轮转锁进行同步。缓冲区只有在一下两个条件都成立的的时候才能分配到Slab:(1)已发出个分配新对象的请求;(2)缓冲区不包含任何空闲对象。在内核中当初始化开销不大的数据结构可以合用一个通用的缓冲区。,地址映射机制 顾名思义地址映射就是建立几种存储媒介(内存,辅存,虚存)间的关联,完成地址间的相互转换,它既包括磁盘文件到虚拟内存的映射,也包括虚拟内存到物理内存的映射。,进程的虚拟空间堆栈区位于进程虚拟空间的顶部,运行时由顶向下延伸。数据和代码段位于虚拟空间的底部,运行时不向上延伸。中间的空洞是进程在运行时可以动态分配的空间(也叫动态内存)。,页故障的产生(1)一是程序出现错误(2)另一种情况是
30、,虚拟地址有效,但其所对应的也当前不在物理内存中,即缺页错误(3)最后一种情况是,要访问的虚拟地址被写保护,即保护错误,交换机制 当物理内存出现不足时,Linux内存管理子系统需要释放部分物理内存页面。这一任务由内核的交换守护进程kswapd完成,该内核守护进程实际是一个内核线程,它在内核初始化时启动,并周期地运行。它的任务就是保证系统中具有足够的空闲页面,从而使内存管理子系统能够有效运行。页面交换策略:策略一:需要时才交换策略二:系统空闲时交换策略三:换出但不立即释放策略四:把页面换出推迟到不能再推迟为止,Linux中新页框的分配方案请求调页(demand paging):是在类UNIX操作
31、系统中使用较为普遍的一种动态内存分配技术。所谓动态内存分配技术就是指进程运行所需要的页框不是一开始就全部分配给进程,而是当内核执行进程的一个指令所需的页面不在内存时,再由CPU的控制单元引起一个缺页异常,这时再由异常处理程序调入内存。写时拷贝(copy_on_write):把一个页面标记为只读,而把代表它的VMA标记为可写。因此任何对页面的写操作都会造成页面写访问异常,同样会引起缺页中断。,缓冲区高速缓存 缓冲区高速缓存由设备标识号和块标号索引,因此可以快速找出数据块。缓冲区高速缓存的大小可以变化。当需要新缓冲区而现在又没有可用的缓冲区时,就按需分配页面。,刷新机制 采取的解决办法是为计算机装
32、备一个不需要经过页表就能把虚拟地址映射成物理地址的小的硬件设备,这个设备叫做TLB(翻译后援存储器,Translation Lookside Buffer),有时也叫做相联存储器(Associative Memov),它通常在MMU内部,条目的数量较少。每一个TLB寄存器的每个条目包含一个页面的信息:有效位、虚页面号、修改位、保护码和页面所在的物理页面号,它们和页面表中的表项一一对应。在Linux中刷新机制(包括TLB的刷新和缓存的刷新)主要完成以下两项工作:(1)保证在任何时刻内存管理硬件所看到的进程的内核映射与内核页表一致。(2)如果负责内存管理的内核代码对用户进程页进行了修改,那么用户进
33、程在被允许继续执行前必须在缓存中看到正确的数据。,5.2.5 文件系统文件系统是对一个存储设备上的数据和元数据进行组织的机制,Linux文件系统接口为分层的体系结构,从而将用户接口层、文件系统实现和操作存储设备的驱动程序分隔开。,Linux操作系统下的文件系统结构,虚拟文件系统VFS是物理文件系统与服务之间的一个接口层,对用户程序隐去各种不同文件系统的实现细节,为用户程序提供一个统一、抽象、虚拟的文件系统界面。VFS的功能包括:记录可用的文件系统的类型;将设备同对应的文件系统联系起来;处理一些面向文件的通用操作。,嵌入式文件系统存储Linux启动时,第一个必须挂载的是根文件系统,若系统不能从指
34、定设备上挂载根文件系统,则系统会出错而退出启动。启动之后可以自动或手动挂载其他的文件系统。因此,一个系统中可以同时存在不同的文件系统。不同的文件系统类型有不同的特点,因而根据存储设备的硬件特性、系统需求等有不同的应用场合。在嵌入式Linux应用中,主要的存储设备为RAM(DRAM,SDRAM)和ROM(常采用FLASH存储器),常用的基于存储设备的文件系统类型包括:jffs2,yaffs,cramfs,romfs,ramdisk,ramfs/tmpfs等。,嵌入式文件系统,(1)ext2、ext3文件系统(2)基于FLASH的文件系统 jffs2;yaffs;Cramfs;Romfs(3)基于
35、RAM的文件系统Ramdisk;ramfs/tmpfs(4)网络文件系统NFS(Network File System),文件系统的目录结构,Linux的目录结构树型目录结构dir1/-dir2/-file12|-dir3/-|-dir4|.根目录组织/-root/:超级用户目录 包括桌面管理等|-home/:用户目录 包括用户信息等|-bin/:执行目录可执行文件常用命令|-sbin/:执行目录不提供给用户使用的命令|-boot/:引导目录引导系统使用的文件|-etc/:配置目录 系统配置时使用,|-dev/:设备目录 通过它访问外设|-mnt/:安装目录 管理员设备临时安装点|-opt/:
36、安装目录 管理员软件包放置点|-lib/:库目录 命令执行时使用|-usr/:共享目录 所有用户的共享文件|-var/:数据目录 系统运行时要修改数据|-tmp/:数据目录 系统运行时要修改数据|-proc/:虚拟目录 文件系统内存产生|-lost+found/:空目录,5.2.6 设备管理设备管理是操作系统诸多管理中最复杂的部分。与Unix系统一样,Linux系统采用设备文件统一管理硬件设备,从而将硬件设备的特性及管理细节对用户隐藏起来,实现用户程序与设备无关性。,设备分类 按设备的所属关系可以将I/O设备分为以下两类:(1)系统设备(2)用户设备按设备的信息交换的单位可将I/O设备分为以下
37、两类:(1)字符设备(2)块设备按设备的共享属性可将I/O设备分为以下三类:(1)独占设备(2)共享设备(3)虚拟设备根据设备的用途,可以把设备分为存储设备与输入/输出设备两大类。,设备管理的任务(1)选择和分配I/O设备以便进行数据传输操作。(2)控制I/O设备和CPU(或内存)之间交换数据。(3)为用户提供一个友好的透明接口,把用户和设备硬件特性分开,使得用户在编制应用程序时不必涉及具体设备,由系统按用户的要求来对设备的工作进行控制。另外,这个接口还为新增加的用户设备提供一个和系统核心相连接的入口,以便用户开发新的设备管理程序。(4)提高设备和设备之间、CPU和设备之间以及进程和进程之间的
38、并行操作程度,以使操作系统获得最佳效率。,设备管理程序一般要提供的功能:(1)提供和进程管理系统的接口(2)进行设备分配(3)实现设备和设备、设备和CPU等之间的并行操作(4)进行缓冲管理(5)设备控制与驱动,设备控制器 设备控制器是CPU与I/O设备之间的接口,它接收从CPU发来的命令并去控制I/O设备工作。大多数设备控制器都由以下三部分组成。(1)设备控制器与处理机的接口(2)设备控制器与设备的接口(3)I/O逻辑,I/O通道 设置I/O通道的目的是使一些原来由CPU处理的I/O任务转由通道来承担,从而把CPU从繁杂的I/O任务中解脱出来。通道有两种基本类型:选择通道和多路通道。选择通道又
39、称高速通道,在物理上它可以连接多个设备,但是这些设备不能同时工作,在某一段时间内通道只能选择一个设备进行工作。多路通道又分为数组多路通道和字节多路通道。数组多路通道的基本思想是指,当某设备进行数据传送时,通道只为该设备服务;当设备在执行寻址等控制性动作时,通道暂时断开与这个设备的连接,挂起该设备的通道程序,去为其他设备服务,即执行其他设备的通道程序。字节多路通道主要用于连接大量的低速设备,因此通道在传送两个字节之间有很多空闲时间,字节多路通道正是利用这个空闲时间为其他设备服务。,Linux的I/O控制 Linux的I/O控制方式常用的有三种:查询等待方式、中断方式和DMA(内存直接存取)方式。
40、,(1)查询等待方式查询等待方式又称轮询方式(polling mode)。对于不支持中断方式的机器只能采用这种方式来控制I/O过程,所以Linux中也配备了查询等待方式。(2)中断方式在硬件支持中断的情况下,驱动程序可以使用中断方式控制I/O过程。对I/O过程控制使用的中断是硬件中断,当某个设备需要服务时就向CPU发出一个中断脉冲信号,CPU接收到信号后根据中断请求号IRQ启动中断服务例程。(3)DMA方式内存直接存取技术是指数据在内存与I/O设备间自己接进行成块传输。DMA有两个技术特征:首先是直接传送,其次是块传送。所谓直接传送,即在内存与I/O设备间传送一个数据库的过程中,不需要CPU的
41、任何中间干涉,只需要CPU在过程开始时向设备发出“传送块数据”的命令,然后通过中断来得知过程是否结束和下次操作是否就绪。一个完整的DMA过程包括初始化、DMA请求、DMA响应、DMA传输、DMA结束5个阶段。(4)通道方式也是一种I/O控制方式,但是这种方式是利用一个独立于CPU以外的、专门管理I/O的处理机来控制输入和输出,它控制设备与内存直接进行数据交换,有着自己的通道指令,这些通道指令由CPU启动,并在结束时向CPU发出中断信号。,设备驱动 设备驱动程序的处理过程:(1)将抽象要求转换为具体要求(2)检查I/O请求的合法性(3)读出和检查设备的状态(4)传送必要的参数(5)工作方式的设置
42、(6)启动I/O设备,Linux设备管理的设备 在Linux系统中,硬件设备分为两种,即块设备和字符设备。1)特别文件用户是通过文件系统与设备接口的,所有设备都作为特别文件,从而在管理上就具有一些共性。,设备驱动的分层结构,对于一般文件(即磁盘文件),要进行空间的映射:从普通文件的逻辑空间映射到设备的逻辑空间,然后在设备驱动层做进一步映射:从设备的逻辑空间映射到物理空间(即设备的物理地址空间),进而驱动底层物理设备工作。对于设备文件,则文件的逻辑空间通常就等价于设备的逻辑空间,然后从设备的逻辑空间映射到设备的物理空间,再驱动底层的物理设备工作。,2)设备驱动程序和内核之间的接口Linux系统和
43、设备驱动程序之间使用标准的交互接口。无论是字符设备、块设备还是网络设备的驱动程序,当内核请求它们提供服务时,都使用同样的接口。在应用程序界面上,利用内核提供的系统调用来实现可安装模块的动态安装和拆卸。但通常情况下,用户是利用系统提供的插入模块工具和移走模块工具来装卸可安装模块。插入模块的工作主要如下:(1)打开要安装的模块,把它读到用户空间。这种“模块”就是经过编译但尚未连接的.o文件。(2)必须把模块内涉及对外访问的符号(函数名或变量名)连接到内核,即把这些符号在内核映像中的地址填入该模块需要访问这些符号的指令及数据结构中。(3)在内核创建一个module数据结构,并申请所需的系统空间。(4
44、)最后,把用户空间中完成了连接的模块映像装入内核空间,并在内核中“登记”本模块的有关数据结构(如file_operations结构),其中有指向执行相关操作函数的指针。,3)字符设备在Linux 系统中,打印机、终端等字符设备都作为字符特别文件出现在用户面前。用户对字符设备的使用就和存取普通文件一样。在应用程序中,使用标准的系统调用来打 开、关闭、读写字符设备。当字符设备初始化时,其设备驱动程序被添加到由device_struct结构组成的chrdevs结构数组中。device_struct 结构由两项构成,一个是指向已登记的设备驱动程序名的指针,另一个是指向file_operations结构
45、的指针。而file_operations结 构的成分几乎全是函数指针,分别指向实现文件操作的入口函数。设备的主设备号用来对chrdevs数组进行索引。,4)块设备对块设备的存取和对文件的存取方式一样,其实现机制也和字符设备使用的机制相同。Linux系统中有一个名为blkdevs的结构数组,它描述了一系列在系统中登记的块设备。数组blkdevs也使用设备的主设备号作为索引,其元素类型是device_struct结构。该结构中包括指向已登记的设备驱动程序名的指针和指向block_device_operations结构的指针。,Linux字符设备的驱动 主要通过介绍字符设备scull(Simple
46、Character Utility for Loading Localities,区域装载的简单字符工具)的驱动程序编写,来学习Linux设备驱动的基本知识。scull可以为真正的设备驱动程序提供样板。1)主设备号和次设备号2)一些重要的数据结构3)字符设备的注册4)scull模型的内存使用5)open和release 6)read和write 7)对于scull设备有时需要用到scull pipe设备,scull pipe设备是针对一片内存,实现了一个circular buffer(循环缓冲),5.2.7 嵌入式Linux引导过程在嵌入式系统中,首先要考虑的就是启动问题,即系统如何告知CPU
47、启动位置以及启动方法。一般来说,嵌入式系统会提供多种启动方法。具备Flash ROM的系统具备有Flash启动的方式,也有直接从RAM中启动的方法。这些启动部分的工作主要由一个被称为bootloader的程序完成。运行Linux的目标机在重新启动后要经过几个步骤才能出现系统提示符。最初的步骤是与微处理器硬件相关的。内核本身包含了微处理器体系结构相关的初始化代码,这些代码首先被执行。该初始化代码为保护模式的运算配置微处理器的寄存器,然后调用微处理器体系结构无关的称为start_kernel的内核开始点。此后,内核的引导过程对于所有微处理器体系结构都是完全相同的。,Linux的引导过程包括下列步骤
48、:1)处理器重新启动之后,执行ROM启动代码。2)ROM启动代码初始化CPU、内存控制器以及片上设备,然后配置存储映射。ROM启动代码随后执行一个引导装载程序bootloader。3)引导装载程序将Linux内核从Flash或者TFTP服务器解压到RAM中。然后跳到内存的第一天指令处执行。内核首先配置微处理器的寄存器,然后调用start_kernal,它是体系结构无关的开始点。4)内核初始化告诉缓存和各种硬件设备。5)内核挂装根文件系统。6)内核执行init进程。7)正在执行的init进程装载运行时的共享库。8)init读取其配置文件/etc/inittab并执行执行脚本。一般而言,init执
49、行一个启动脚本rc.d/rcs,该脚本配置并启动网络和其他系统服务。9)init进入运行级别,在该级别下可以执行系统任务或开始登陆进程,最后进入用户会话阶段。,嵌入式Linux引导过程中概念简介1)bootloader程序bootloader的作用:(1)初始化处理器。(2)初始化必备的硬件。(3)下载系统映像。(4)初始化操作系统并准备运行。,2)嵌入式系统内核对于使用操作系统的嵌入式系统而言,操作系统一般是以内核映像的形式下载到目标系统中。以Linux为例子,在系统开发完成之后,将整个操作系统部分做成压缩或者没有压缩过的内核映像文件,与文件系统一起传送到目标系统中。通过bootloader
50、指定地址运行Linux内核,启动嵌入式Linux系统;然后再通过操作系统解开文件系统,运行应用程序。在内核中通常必须的部件是进程管理、进程间通信、内存管理部分,其他部件,如文件系统、驱动程序、网络协议等,都可以配置,并以相关的方式实现。,3)根文件系统在嵌入式系统中的“硬盘”概念一般都以ramdisk的方式实现。因为Falsh这样断电后还能继续保存数据的设备,其价格相对昂贵;然而系统中又无法使用像硬盘这样的大型设备,因此,需要长久使用的文件系统数据,尤其是应用程序的可执行文件、运行库等,运行时都放在RAM中。常用的方式就是从RAM中划分出一块内存虚拟成“硬盘”,对它的操作与对永久存储器操作一样