1 / 35

13.3.2 设备驱动程序的实现

13.3.2 设备驱动程序的实现. 1 .块设备 块设备主要包括硬盘、软盘等存储设备,前面已经提到过,块设备驱动程序有一部分是相同的,不同的主要是真正的 I/O 操作的那部分。 设备驱动程序一共可能有 6 种操作: OPEN: 验证设备是否可用; CLOSE: 确保把采用延迟写方式处理的数据真正写到设备上; READ: 将数据从设备读到调用进程所在的内存区域; WRITE: 与 READ 执行的操作相反; IOCTL: 负责对 I/O 设备的操作参数进行检查和修改; SCATTERED_IO: 允许执行同时读写多个块的操作。. 13.3.2 设备驱动程序的实现.

anais
Download Presentation

13.3.2 设备驱动程序的实现

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 13.3.2 设备驱动程序的实现 1.块设备 • 块设备主要包括硬盘、软盘等存储设备,前面已经提到过,块设备驱动程序有一部分是相同的,不同的主要是真正的I/O操作的那部分。 • 设备驱动程序一共可能有6种操作: • OPEN: 验证设备是否可用; • CLOSE:确保把采用延迟写方式处理的数据真正写到设备上; • READ: 将数据从设备读到调用进程所在的内存区域; • WRITE:与READ执行的操作相反; • IOCTL:负责对I/O设备的操作参数进行检查和修改; • SCATTERED_IO:允许执行同时读写多个块的操作。

  2. 13.3.2 设备驱动程序的实现 • ① 块设备驱动程序软件。 MINIX在头文件driver.h中定义了块设备驱动程序需要用到的结构定义,它们包括: • driver结构:保存各驱动程序执行I/O操作所需调用函数的地址; • device结构:以字节为单位保存基地址、长度等与分区相关的主要信息。

  3. 13.3.2 设备驱动程序的实现 • ② 驱动程序库 • 可移植性是在MINIX中得到了相当的重视,MINIX的目标是当它被移植到一台机器上时,应该能够使用这台机器上原先运行的操作系统采用的分区表格式。 • 在IBM兼容机上,硬盘分区的标准由MS-DOS的fdisk命令确定。 • MINIX包含了支持IBM兼容机分区的源代码,为了方便移植,这些与平台有关但是与具体硬件无关的代码没有被放在driver.c文件中,而是单独的放在drvlib.h和drvlib.c文件中。

  4. 13.3.2 设备驱动程序的实现 • ③ RAM盘 在MINIX中存在一个RAM盘的概念,简而言之就是保留一部分内存作为磁盘来使用,对于用户来说,它就像一个磁盘一样。 RAM盘的驱动程序实际上由四个紧密联系的部分组成,也就是具有以下四个次设备: • 0:/dev/ram:真正的RAM盘,它的大小和基址在MINIX启动时由FS确定; • 1:/dev/mem:用于读写物理内存,通常读出的是起始于内存零地址的内容,写操作则会改写中断向量; • 2:/dev/kmem:用于读写内核内存,与1的功能类似; • 3:/dev/null:负责接收数据并把数据抛弃掉。

  5. 13.3.2 设备驱动程序的实现 2.MINIX的系统任务 • MINIX中将文件管理和内存管理摒弃在内核之外,禁止它们把信息写入内核.所以,如果内存管理系统想把消息通知给内核时,就需要借助于一个第三者——对内核表拥有存取权的内核任务——的帮助,这个任务一般被称之为系统任务。 • 系统任务和I/O任务十分类似,它们都实现了一个接口,具有相同的权限,都被链入内核中,所不同的仅仅是系统任务不控制具体I/O设备,它所服务的对象是系统中大部分的内部组件。

  6. 13.3.2 设备驱动程序的实现 系统任务的18种消息:

  7. 13.4 内存管理 13.4.1内存管理概述 由于MINIX是专门设计在IBM兼容机等微型机上运行的操作系统,因此它的内存管理(MM)是比较简单的,不分页,也不交换: • MM保存一张按照地址顺序排列的空闲地址列表,当系统调用FORK和EXEC请求内存时,MM利用首次适配算法找到一块足够大的空闲内存分配给程序使用。 • 而一旦程序装入内存则一直在原位置运行到结束。 • 可以说,内存管理的主要工作就是操作进程表和空闲地址列表这两张表格,以及处理系统调用FORK和EXEC。

  8. 13.4.1内存管理概述 1.内存的消息处理 • 和I/O相仿,MM在系统初始化以后进入自己的主循环,等待消息,一旦收到消息就进行处理并发送应答消息。

  9. 13.4.1内存管理概述 与MM通信的消息类型、入口参数和应答:

  10. 13.4.1内存管理概述 2.系统调用 • 下面我们来看看系统调用FORK、EXEC和BRK的处理过程。 ① FORK。 • 执行FORK的过程很简单,收到FORK调用的请求后,MM就检查进程表中是否存在空闲位置,如果存在,就尝试为新建立的子进程分配内存,随后就将内存地址等信息填入一个空闲的进程表项,最后发出通知公布建立了一个新进程。 • 进程的终止则更复杂一些,当进程自己退出(或被信号杀死)并且被父进程通过WAIT调用观察到以后,该进程才会真正被删除,如果第二个条件没有满足,子进程就会被挂起,这种状态在MINIX中称为“僵死”。

  11. 13.4.1内存管理概述 ② EXEC。这个调用负责内存映像的更新,包括设置新堆栈,它也是MINIX中最复杂的系统调用。EXEC的复杂主要是由两个方面的因素决定的: • 次数众多的检测:EXEC执行时十分谨慎,为了保证有足够内存容纳新映像,必须进行检测。 • 设置初始堆栈:我们通常用库函数execve来调用EXEC,这个函数包含三个参数:被执行文件名的地址指针;一个指针数组的地址指针,数组中的元素分别指向一个参数;第三个参数同样是一个指针数组的地址指针。

  12. 13.4.1内存管理概述 ③ BRK。BRK调用可以调整数据段的上限。有两个过程都可以调用BRK: • brk过程以数据段的绝对长度为参数; • sbrk以当前长度的增量为参数,计算出绝对长度后调用BRK。 执行BRK所完成的工作就是检查地址空间是否够用,并根据情况调整表格,然后通知内核。

  13. 13.4.1内存管理概述 3. 内存数据结构 主要了解两个关键的数据结构:进程表和空闲表。 • ① 进程表。MINIX中,内核、FS和MM都拥有各自的进程表,每部分的进程表包含本部分必需的域,同时,三张进程表是对应的,也就是说,三张表的第n个表项指的都是同一个进程。也正是由于这个原因,三张表必须被同步更新。 • ② 空闲表。定义在alloc.h文件中的空闲表按照内存地址递增的顺序列出空闲块。 空闲表的表项主要包含三个域:空闲块组的基地址、空闲块组的大小及指向下一个空闲块组的指针。 表项以单向链表的形式链接。

  14. 13.4.2 实现 1. 头文件与主程序 • MM中的table.c文件的主要作用是为全局变量服务,在table.c被编译时,它会自动为下面将介绍到的一些全局变量保留存储空间。 • 内存管理部分有许多自己使用的头文件,这些头文件有的和其它部分的头文件具有相同的名字,但由于它们位于不同的目录下为不同的部分服务,所以编译使用时不会出现错误。

  15. 13.4.2 实现 • ① 头文件。在内存管理器MM中存在着一个私有的头文件mm.h,可以将它理解为MM范围内的主控头文件,它囊括了位于/usr/include及其子目录中的所有头文件,以及/kernel/kernel.h中包含的大部分头文件。MM中每个文件的编译都需要引用mm.h。 • ② 主程序。MM的主程序也位于main.c中,执行的过程和I/O任务的主程序类似。首先调用mm_init,mm_init通过过程sys_getmap来获得内核的内存使用信息,为所有第二层及第三层的进程初始化进程表项,同时也为init进程初始化进程表项。

  16. 13.4.2 实现 2. 系统调用的实现 • ① FORK。FORK调用由文件forkexit.c中的do_fork过程来实现。 • ② EXIT。由过程do_mm_exit接收调用,然后具体工作交由mm_exit完成。 • ③ WAIT。WAIT和WAITPID调用都由过程do_waitpid完成。 • ④ EXEC。过程do_exec负责执行本调用。 • ⑤ BRK。BRK调用的处理代码位于break.c中,由过程do_brk完成。

  17. 13.4.2 实现 3.信号处理的实现 MINIX中所有信号及与信号有关的系统调用都被包含在文件signal.c中,具体功能如下所示: • ALARM:经过一段时间后向自己发送ALARM消息; • KILL:给别的进程发出信号指示其下一步的动作; • PAUSE:在收到下一个信号前挂起自己; • REBOOT:发出信号终止所有的进程; • SIGACTION:改变调用进程对将来收到信号的响应方式; • SIGPROCMASK:改变阻塞信号的集合; • SIGSUSPEND:改变阻塞信号集合后执行PAUSE调用; • SIGPENDING:对未处理的阻塞信号进行检查; • SIGRETURN:处理完信号后进行清理工作。

  18. 13.4.2 实现 4.其它的系统调用 MM还有几个很简单但是又必需的系统调用,MINIX把它们单独放在一个文件getset.c中,由过程do_getset执行: • GETUID:返回有效的用户标号; • GETGID:返回有效的分组号; • GETPID:返回父子进程的进程号; • SETUID:设置调用者有效的用户号; • SETGID:设置调用者的有效分组号; • SETSID:创建新的会话并返回进程号; • GETPGRP:返回进程的分组标识。

  19. 13.5 文件系统 13.5.1文件系统概述 MINIX文件系统(FS)的功能包括两个方面的内容: • 站在用户的角度,文件系统使得用户可以知道文件由什么组成、如何命名以及可以怎样操作文件。可以理解为文件系统为用户和文件间提供了一个接口。 • 从系统的角度来考虑,文件系统的功能包括:决定以怎样的方式存储文件和目录,包括分配空间和释放空间的过程;管理磁盘空间,比如是以链接表或是以位图的方式记录空闲存储空间等等。本节中将详细介绍以上这些功能怎样实现。

  20. 13.5.1文件系统概述 1.消息 MINIX文件系统接收的消息种类比较多,一共有39种,其中两个是异常消息。其中下图列出的前面31种来自用户进程。后面6种来自系统调用,它们由MM先处理,然后调用FS完成其余工作。

  21. 13.5.1文件系统概述

  22. 13.5.1文件系统概述

  23. 13.5.1文件系统概述 2. i节点和位图 • 在MINIX里为了改进顺序读取文件时的性能,要确保同一文件的所有磁盘块都位于同一个柱面上,为此引入了区段的概念,一个区段包含了多个块。 • MINIX中为每个文件建立了一个索引表,表中存储了文件属性和各个块在磁盘上的地址,这个索引表被称为i节点。 • MINIX使用位图来记录空闲的i节点和区段,保存位图的磁盘块被称为位图块。当创建一个文件时,FS在位图块中查找第一个空闲的i节点,在这个i节点被分配后,就修改指针指向下一个节点。

  24. 13.5.1文件系统概述 3. 目录管理 目录管理是文件系统的一个重要功能,我们查找一个文件,实际上就是先在目录树中找到文件名,然后通过对应的i节点在磁盘上找到文件数据。 目录查找过程:

  25. 13.5.1文件系统概述 4.管道和设备文件 • 管道和设备文件与普通文件的最大不同在于,普通文件的操作通常很快就能完成,而管道有时则需要等待几个小时才能有进程把数据写进来。而调用设备文件的进程,为了等待终端或其它设备上的I/O,时间也是不能确定的。 • FS通过不发送信号的方式使得等待应答信号的调用进程被阻塞,一旦有别的进程修改了管道的状态使得被挂起的进程可以运行,FS就会设置一个标志。到下一次主循环时,FS提取以前保存在进程表中的各项参数,继续执行先前被挂起的进程。

  26. 13.5.2 实现 1.头文件及全局变量 FS使用的数据结构和表,这些在头文件中得到定义。 • const.h:定义了表长、标志位等一些文件系统中使用的常量的值; • glo.h:和内存管理中的glo.h文件一样,定义了一些全局变量; • proto.h:提供了ANSI标准C编译器所支持的函数原型; • type.h:定义了i节点在磁盘上的组织结构。

  27. 13.5.2 实现 2.表格管理及其使用 • 块、超级块及i节点是文件系统中最重要的存储结构,对它们的管理和使用是通过一系列的过程来实现的。 • 用于管理块的过程有: • alloc_zone:用于在区段位图中查找空闲区段,并将其分配给文件; • flushall:通常被系统调用SYNC所调用,刷新某设备的缓冲,同时将其中内容写回设备; • get_block:取要读写的块,先检查高速缓存,若找到就直接返回指针,否则就将其读入缓存; • put_block:释放由get_block请求得到的块;

  28. 13.5.2 实现 • free_zone:负责将不再使用的区段归还给空闲区段位图,以区段位图和位号为参数调用free_bit; • rw_block:提供了一个简单的磁盘界面,负责在内存和磁盘间传送块; • invalidate:删除某个设备在高速缓存中用过的所有块; • rw_scattered:以设备标志符、缓冲区指针数组的指针、数组长度及读写标志为参数,执行在设备上读/写分散数据的任务; • rm_lru:只被get_block调用,负责从LRU链中删除一个块。

  29. 13.5.2 实现 • 用于超级块管理的过程略少一些,下面的五个过程用于超级块和位图的管理: • alloc_bit:从区段位图或i节点位图中分配一位,通常被alloc_inode或alloc_zone以循环嵌套的方式调用; • free_bit:从区段位图或i节点位图中释放一位,首先计算哪一个位图块包含了要释放的位,调用get_block将这个位图块读入内存,将相应位置0,再调用put_block将该块写回磁盘; • get_super:用于在超级块表中搜索特定设备; • mounted:关闭块设备时调用,以一个指向设备i节点的指针为参数,返回报告这个i节点是否在被挂装的文件系统上。 • Read_super:在读超级块时调用,检查所读出的文件系统的版本号,并进行相应的转换。

  30. 13.5.2 实现 • 用于管理i节点的过程有: • get_inode:将一个i节点读入内存,首先搜索inode表,若找到则将指针返回;若不在内存中则调用rw_inode将其读入; • put_inode:返回不再使用的i节点,并把计数器icount减1; • alloc_inode:为新文件分配i节点; • wipe_inode:将i节点中某些域清除,同时也负责部分初始化i节点的工作; • free_inode:释放i节点; • update_times:从系统时钟获得时间,同步修改i节点中的时间域; • rw_inode:负责在内存和磁盘间传送i节点; • old_icopy:转换要执行写操作的i节点内容; • new_icopy:对由i节点读入的数据进行转换; • dup_inode:向其它进程标明某个进程正在使用i节点。

  31. 13.5.2 实现 3.管道 • 管道文件的代码在文件pipe.c中,它和普通文件在很多方面都类似,我们主要看看它们的不同之处。 • PIPE调用通过过程do_pipe创建一个拥有权属于系统的管道,并保存在指定的管道设备上。Do_pipe负责为管道分配一个i节点,同时返回两个文件描述符。 • Pipe_check过程利用release过程来判断能否唤醒那些被挂起的过程。除此之外,它也利用函数suspend将调用参数保存在进程表中同时将dont_reply置为TRUE,从而使进程挂起,以便进行各种检查,保证对管道的操作能够完成。 • 过程do_unpause用于处理MM向FS发送的消息,若这条消息的目标进程被阻塞,则do_unpause负责将进程唤醒。

  32. 13.5.2 实现 4.主程序 • FS的主循环包含在main.c中,它的结构和内核类似,首先它将进行以下的设置: • who:全局变量,调用进程的进程表插槽号; • fs_call:全局变量,待执行的系统调用的编号; • fp:指向调用者的进程表表项入口; • super_user:标明调用者是否为超级用户; • dont_reply:标志位,标明是否发送回答信号。 • 主循环设置完变量后就执行系统调用的过程,用fs_call作为参数选定被调用的进程。 • 重新回到主循环后,如果dont_reply被设置,那么就不发送应答信号,否则送回一个应答消息。

  33. 13.5.2 实现 5.对文件的操作 • ① 创建文件。过程common_open负责执行创建文件的调用CREAT,具体工作由过程new_node完成。 • ② 打开文件。打开文件调用OPEN也由common_open来完成。首先要检查文件的类型和模式,这个工作由过程forbidden对rwx位进行检查来完成。

  34. 13.5.2 实现 • ③ 关闭文件。关闭文件通过过程do_close完成,对于正规文件,我们要减少filp计数器的值并检查该计数器是否为0,若为0则表示文件不再被使用,调用put_inode来收回i节点。 • ④ 读文件。读操作由do_read接收请求,但具体的操作则是通过设置READING标志调用公共过程read_write来实现的。 • ⑤ 写文件。和读文件类似,do_write过程所做的工作也只是以WRITING标志调用read_write。

  35. 13.5.2 实现 6.目录与路径 MINIX中通常要先把路径名转换为i节点。路径名的分析是在文件path.c中进行。首先在过程eat_path中调用了两个函数,这两个函数分别是: • last_dir:检查路径名以判断是相对路径还是绝对路径。 • advance:用来取得路径的最后一个部分,它以目录指针和字符串为参数,在目录中进行查找,一旦找到匹配的路径名(和参数串匹配),就返回相应i节点的指针。

More Related