Linux 课后练习题

第一章 概述

一、判断题
1、Linux 内核是单内核结构,执行效率高,可维护性好。( × )

1
2
为什么要使用模块?
linux内核之所以提供模块机制,是因为它本身是一个单内核。而单内核的最大优点就是效率高,因为所有的内容都集成在一起,但其缺点是可扩展性和可维护性相对较差,模块机制就是为了弥补这一缺陷。

2、Linux 内核模块不属于 Linux 的子系统。( √ )

1
2
3
4
5
6
7
Linux 内核主要由5个子系统组成:进程调度(SCHED),内存管理(MM),虚拟文件系统(VFS),网络接口(NET),进程间通信(IPC)。内核模块是linux内核向外部提供的一个插口,是内核的一部分,但是并没有被编译到内核里面去,其全称为动态可加载内核模块(Loadable Kernel Module,LKM),简称模块。
(1)进程调度-控制着进程对CPU的访问。当需要选择一个进程运行时,由调度程序选择最值得运行的进程。Linux 使用了比较简单的基于优先级和时间片的进程调度算法选择新的进程。
(2)内存管理-允许多个进程安全地共享主内存区域 。Linux的内存管理支持虚拟内存,即在计算机中运行的程序,其代码、数据和堆栈的总量可以超过实际内存的大小,操作系统只将当前使用的程序块保留在内存中,其余的程序块则保留在磁盘上。必要时,操作系统负责在磁盘和内存之间交换程序块。因为虚拟内存管理需要硬件支持,因此内存管理从逻辑上可以分为硬件无关的部分和硬件相关的部分。详细内容看第四章。
(3)虚拟文件系统-隐藏各种不同硬件的具体细节,为所有设备提供统一的接口。虚拟文件系统支持多达数十种不同的文件系统,这也是Linux较有特色的一部分。虚拟文件系统可分为逻辑文件系统和设备驱动程序。逻辑文件系统指Linux所支持的文件系统,如ext2, fat等,设备驱动程序指为每一种硬件控制器所编写的设备驱动程序模块。详细内容参看第八章和第九章。
(4)网络-提供了对各种网络标准协议的存取和各种网络硬件的支持。网络子系统可分为网络协议和网络驱动程序两部分。网络协议部分负责实现每一种可能的网络传输协议,网络设备驱动程序负责与硬件设备进行通信,每一种可能的硬件设备都有相应的设备驱动程序。因为这部分内容相对独立和复杂,本书不做详细介绍。
(5)进程间通信(IPC)- 支持进程间各种通信机制,包括共享内存、消息队列及管道等。这部分内容也相对独立,本书不做详细介绍。
处于中心位置的是进程调度,所有其它的子系统都依赖于它,因为每个子系统都需要挂起或恢复进程。一般情况下,当一个进程等待硬件操作完成时,它被挂起;当操作真正完成时,进程恢复执行。例如,当一个进程通过网络发送一条消息时,发送进程被挂起,一直到硬件成功地完成消息的发送。其它子系统(内存管理,虚拟文件系统及进程间通信)以相似的理由依赖于进程调度。

3、当一个操作系统满足 POSIX 标准时,在该系统上写的应用程序都能在任何 UNIX 系统中运行。( √ )

1
POSIX 表示可移植操作系统接口(Portable Operating System Interface)。任何操作系统只有符合这一标准,才有可能运行Unix程序。

4、硬件性价比比较低的时候,操作系统设计追求低成本高性能。( √ )
5、硬件性价比比较高以后,操作系统设计不再考虑硬件成本需求,着力在充分利用硬件的性能上。( × )

1
2
在硬件的性价比较低的时候,操作系统设计完成了追求硬件使用率的理论探索,从批处理到分时系统
在硬件性价比越来越高后,操作系统的设计开始追求系统的可靠和稳定,出现了多处理器系统和分布式系统。

6、Linux 系统的设备管理功能通过虚拟文件系统实现。( √ )

二、单选题
1、(d)不属于 Linux 的子系统。
A 进程管理 B 内存管理 C 文件系统 D 模块
2、Linux 操作系统遵循(c)标准。
A GNU B GPL C POSIX D MMU
3、struct list_head 无法表达(b)种数据结构。
A 队列和堆栈 B 图 C 树 D 集合

第二章 内存寻址

一、判断题

1
2
3
4
5
6
intel的80286处理器于1982年问世,地址总线位数增加到了24位,从此开始引进了一个全新理念—保护模式:访问内存时不能直接从段寄存器中获得段的起始地址了,而需要经过额外转换和检查 。段寄存器中存放段号,而不是基地址。80286处理器一些致命的缺陷注定不能长久,它很快被天资卓越的兄弟——80386代替了。80386是一个32位的CPU,其寻址能力达到4GB 。Intel选择了在段寄存器的基础上构筑保护模式,并且保留段寄存器16位 。在保护模式下,它的段范围不再受限于64K,可以达到4G。

为什么能达到保护这些对象的目的?
访问内存时不能直接从段寄存器中获得段的起始地址,而需要经过额外的转换和检查。
保护模式的实现:通过分页机制及CR0~CR3控制寄存器的设置

1、操作系统启动时,处理器处于保护模式。( × )

2、分页机制是在保护模式下开启的。( √ )

3、在保护模式下,段的大小可以达到 4GB。( √ )

4、CR3 寄存器存放的是页目录基地址。( √ )

5、X86 的保护模式就是来保护操作系统的。( × )

1
2
保护模式保护物理内存的访问。
Linux操作系统引入保护模式,是因为实模式下从段寄存器中可以获得段的起始地址,不能保护保护对物理内存的访问,因此需要保护模式。

6、分页的原理使得每个进程可以拥有自己独立的虚拟内存空间。( √ )

1
Linux主要采用分页机制来实现虚拟存储器管理,因为Linux的分段机制使得所有的进程都使用相同的段寄存器值,这就使得内存管理变得简单,也就是说,所有的进程都使用同样的线性地址空间(0~4G)。

7、Linux 之所以巧妙地绕过了段机制,主要是因为将段的基地址设为 0,即偏移量等于线性地址。( √ )

1
在x86上,设计者要求必须使用段机制,而Linux为了可移植性,巧妙的绕过段机制,将段机制和分页机制合并。主要设定如下完成:设定段的基地址为0,段的界限设为4GB,这时段内偏移地址就等于线性地址。

8、在 X86 中,启用分页机制是通过启用保护允许位 PE 达到的。( × )

9、链接以后形成的地址空间是虚拟地址空间。( √ )

1
一个程序编译连接后形成的地址空间是一个虚拟地址空间,但是程序最终还是要运行在物理内存中。因此,应用程序所给出的任何虚地址最终必须被转化为物理地址,所以,虚拟地址空间必须被映射到物理内存空间中,这个映射关系需要通过硬件体系结构所规定的数据结构来建立。这就是我们所说的段描述符表和页表,Linux主要通过页表来进行映射。

10、CPU 访问的是虚拟地址。( √ )

1
CPU发出对虚拟地址的数据访问,虚拟地址经过MMU转换成物理地址,最终从这个物理地址读取数据。因此cache的硬件设计既可以采用虚拟地址也可以采用物理地址甚至是取两者地址部分组合作为查找cache的依据。

11、80X86 的控制寄存器主要用于分段机制。( × )

12、80X86 的分段机制是必选的,分页机制是可选的。( √ )

13、页面高速缓存是一种硬件机制,专门用来支持地址转换的。( × )

1
由于在分页情况下,页表是放在内存中的,这使CPU在每次存取一个数据时,都要至少两次访问内存,从而大大降低了访问速度。所以,为了提高速度,在IA32中设置一个最近存取页的高速缓存硬件机制,它自动保持32项处理器最近使用的页表项,因此,可以覆盖128K字节的内存地址。当访问线性地址空间的某个地址时,先检查对应的页表项是否在高速缓存中,如果在,就不必经过两级访问了,如果不在,再进行两级访问。平均来说,页面高速缓存大约有90%的命中率,也就是说每次访问存储器时,只有10%的情况必须访问两级分页机构。这就大大加快了速度,

14、Intel 的保护模式是在 80386 处理器中首次出现的。( × )

15、虚拟地址是程序访问存储器所使用的逻辑地址,线性地址是逻辑地址到物理地址变换的中间层,物理地址是每一个字节单元的一个唯一的存储器地址。( √ )

1
2
Linux采用分页存储管理。虚拟地址空间划分成固定大小的“页”,由MMU在运行时将虚拟地址映射(变换)成某个物理页面中的地址 
IA32的MMU对程序中的虚拟地址先进行段式映射(虚拟地址转换为线性地址),然后才能进行页式映射(线性地址转换为物理地址)

二、单选题

1、一个 32 位的虚拟地址分为 a,b,c 三个域,其中 a,b 用于一个二级页表系统,c 为页内偏移地址,则页面数为(D)

A a+b B axb C 2^a+b D 2^(a+b)

2、以下(C)处理器不是冯。诺依曼体系结构。

A Intel X86 B AMD C ARM D MIPS

1
图灵机模型分为冯诺依曼结构和哈佛结构,其中ARM属于哈佛结构。

3、“段:偏移量”的形式描述的是(B)。

A 物理地址 B 虚拟地址 C 线性地址 D 段地址

1
2
3
硬件地址:将主板上的物理内存条所提供的内存空间定义为物理内存空间,其中每个内存单元的实际地址就是物理地址
虚拟地址:将应用程序员看到的内存空间定义为虚拟地址空间(或地址空间),其中的地址就叫虚拟地址(或虚地址), 一般用“段:偏移量”的形式来描述
线性地址:线性地址空间是指一段连续的,不分段的,范围为0到4GB的地址空间,一个线性地址就是线性地址空间的一个绝对地址。

4、在 80x86 中,可供一般用户访问的寄存器:(A)

A 段寄存器 B 调试寄存器 C 系统地址寄存器 D 测试寄存器

5、分页机制中页的大小由(A)决定。

A 硬件设计者 B 操作系统设计者 C 用户 D A 和 B

第三章 进程

一、判断题

1、进程上下文是指进程的执行环境。( √ )

1
Linux是多任务操作系统,也就是说可以有多个程序同时装入内存并运行,操作系统为每个程序建立一个运行环境即创建进程。从逻辑上说,每个进程拥有它自己的虚拟CPU。当然,实际上真正的CPU在各进程之间来回切换。但如果我们想研究这种系统,而去跟踪CPU如何在程序间来回切换将会是一件相当复杂的事情,于是换个角度,集中考虑在(伪)并行情况下运行的进程集就使问题变得简单、清晰得多。这种快速的切换称作多道程序执行。在一些Unix书籍中,又把“进程切换”(Process Switching)称为“环境切换”或“上下文切换”(Context Switching)。这里“进程的上下文”就是指进程的执行环境。

2、进程处于浅度睡眠状态不可由其他进程通过信号和时钟中断唤醒。 ( × )

1
2
3
4
5
6
内核实现了操作系统的三大功能,分别为进程管理、内存管理和文件系统。Linux会用一个数据结构来描述进程,这个数据结构包括进程的状态,进程的pid,父进程等信息,Linux会维护这一个数据结构来实现对进程的状态管理。而每个进程都由其父进程来创建,最初的父进程由Linux的内核创建。Linux进程状态有以下五种:
可运行态:运行态和就绪态的合并,表示进程正在运行或准备运行,Linux 中使用 TASK_RUNNING 宏表示此状态。
浅度睡眠态:进程正在睡眠(被阻塞),等待资源到来是唤醒,也可以通过其他进程信号或时钟中断唤醒,进入运行队列。Linux 使用 TASK_INTERRUPTIBLE 宏表示此状态。
深度睡眠态:其和浅度睡眠基本类似,但有一点就是不可其他进程信号或时钟中断唤醒。Linux 使用TASK_UNINTERRUPTIBLE 宏表示此状态。
暂停状态:进程暂停执行接受某种处理。如正在接受调试的进程处于这种状态,Linux 使用 TASK_STOPPED 宏表示此状态。
僵死状态:进程已经结束但未释放PCB,Linux 使用 TASK_ZOMBIE 宏表示此状态。

3、fork() 后,写时复制技术发生时,主要完成复制父进程的页表工作。 ( √ )

1
2
3
写时复制技术:指在创建新进程时没有把全部的父进程资源给子进程复制一份,而是将这些内容设置为只读状态,当父进程或子进程试图修改某些内容时,内核才在修改前将要修改的部分拷贝出来。当父子进程共享的资源越多时,写时复制技术越有优势。
子进程请求父进程把所有资源给自己复制一份 ,父进程只是假装复制一下,用一个指针指过去,等真正需要时需要利用写时复制技术。父子进程,不管谁想写一个页面,这个页面都要被复制一份。父进程并不是把自己的所有东西马上都给儿子,而是直到儿子真正需要时才给它。也就是当父进程或子进程试图修改某些内容时,内核才在修改之前将被修改的部分进行拷贝-这叫做写时复制。
fork()的实际开销就是复制父进程的页表以及给子进程创建唯一的PCB。

4、当进程处于就绪态,还需要被唤醒才能执行。 ( × )

1
2
3
4
5
6
7
8
9
10
11
为了对进程从产生到消亡的这个动态变化过程进行捕获和描述,就需要定义进程各种状态并制定相应的状态转换策略,以此来控制进程的运行。因为不同操作系统对进程的管理方式和对进程的状态解释可以不同,所以不同操作系统中描述进程状态的数量和命名也会有所不同,但最基本的进程状态有三种:
(1) 运行态: 进程占有CPU,并在CPU上运行。
(2) 就绪态: 进程已经具备运行条件, 但由于CPU忙而暂时不能运行
(3) 阻塞态(或等待态): 进程因等待某种事件的发生而暂时不能运行。(即使CPU空闲, 进程也不可运行)。
进程在生命期内处于且仅处于三种基本状态之一,如图3.2。
这三种状态之间有四种可能的转换关系:
① 运行态->阻塞态: 进程发现它不能运行下去时发生这种转换。这是因为进程发生I/O请求或等待某件事情。
② 运行态->就绪态:在系统认为运行进程占用CPU的时间已经过长,决定让其它进程占用CPU时发生这种转换。这是由调度程序引起的。调度程序是操作系统的一部分,进程甚至感觉不到它的存在。
③ 就绪态->运行态:运行进程已经用完分给它的CPU时间,调度程序从处于就绪态的进程中选择一个投入运行。
④ 阻塞态->就绪态:当一个进程等待的一个外部事件发生时(例如输入数据到达),则发生这种转换。如果这时没有其它进程运行,则转换③立即被触发,该进程便开始运行。
调度程序的主要工作是决定哪个进程应当运行,以及它应当运行多长时间。

5、用户进程执行时处于用户态。 ( × )

1
在执行系统调用前,用户进程运行在用户态;在执行系统调用过程中,用户进程运行在核心态。

6、调度程序的作用是从磁盘上选取一个进程占用 CPU,并分配其占用 CPU 的时间。 ( √ )

1
调度程序的主要工作是决定哪个进程应当运行,以及它应当运行多长时间。

7、一个进程一旦创建就可以为其分配 CPU 并运行。 ( × )

1
2
进程执行时的间断性决定了进程可能具有多种状态,最基本的三种状态如下
① 就绪状态,当进程已分配到除CPU以外的所有必要资源后,只要再获得CPU,就可以立即运行,进程这时的状态称为就绪状态。在一个系统中可能多个进程处于就绪状态,通常将它们排成一个队列,称为就绪队列。

8、用户进程一旦建立,就将所有程序和数据装入内存。 ( × )

9、进程的等待队列不是共享队列,因此不需要保护。 ( × )

10、Linux 的调度器采用机制与策略分析的机制。 ( √ )

二、单选题

1、进程的上下文属于进程控制的(D)类型信息。

A 状态 B 链接 C 虚拟内存 D 处理器环境

2、(B)进程可以充当所有进程的养父。

A 进程 0 B 进程 1 C kswapd D kflushd

3、Linux 创建一个进程采用的是(B)技术。

A 请求调页 B 写时复制 C 分页 D 分段

4、在支持多线程的系统中,进程 P 创建的若干个线程不能共享的是(D)。

A 进程 P 的代码段 B 进程 P 中打开的文件

C 进程 P 的全局变量 D 进程 P 中某线程的栈指针

5、创建(D)不调用 do_fork().

A 进程 B 用户态线程 C 内核线程 D 协程

第四章 内存管理

一、判断题

1、一个进程的用户地址空间主要由 mm_struct 结构和 vm_block_struct 结构来描述。( × )

1
2
 Linux把进程的用户空间划分为一个个区间,这是因为每个虚存区可能来源不同,有的可能来自可执行映像,有的可能来自共享库,而有的则可能是动态分配的内存区,对不同的区间可能具有不同的访问权限,也可能有不同的操作。因此Linux 把进程的用户空间分割管理,并利用了虚存区处理函数(vm_ops)来抽象对不同来源虚存区的处理方法。
一个进程的用户地址空间主要由mm_struct结构和vm_area_structs结构来描述。mm_struct结构对进程整个用户空间进行描述,vm_area_structs结构对用户空间中各个区间(简称虚存区)进行描述。

2、用户可以通过 lscpu 命令来查看内存的层次结构。( ✓ )

3、每个进程拥有 4GB 的虚拟地址空间,0~3GB 是各进程私有用户空间,对其他进程不可见。 ( ✓ )

image-20211117080708726

1
2
线性空间在32位平台上为4GB的固定大小,也就是Linux的虚拟地址空间也这么大。Linux内核将这4G字节的空间分为两部分。最高的1G字节(从虚地址0xC0000000到0xFFFFFFFF)供内核使用,称为“内核空间”,其中存放的是内核代码和数据,即“内核映象”。而较低的3G字节(从虚地址0x00000000到0xBFFFFFFF),供各个进程使用,称为“用户空间”。存放的是用户程序的代码和数据。
因为每个进程可以通过系统调用进入内核,因此,Linux内核空间由系统内的所有进程共享。于是,从具体进程的角度来看,每个进程可以拥有4G字节的虚拟地址空间(也叫虚拟内存) 。每个进程有各自的私有用户空间(0~3G),这个空间对系统中的其他进程是不可见的。最高的1GB内核空间则为所有进程以及内核所共享。

4、每个程序编译链接后形成的二进制映像文件有一个代码段和数据段,进程要映射的文件被映射到内存映射区。 ( ✓ )

image-20211117075624392

1
2
3
4
每个进程经编译、链接后形成的二进制映像文件有一个代码段和数据段。进程运行时须有如图所示的独占堆栈空间。由图可以看出,堆栈段安排在用户空间的顶部,运行时由顶向下延伸;代码段和数据段则在低部,运行时并不向上延伸。从数据段的顶部到堆栈段地址的下沿这个区间是一个巨大的空洞,这就是进程在运行时调用malloc()可以动态分配的空间,也叫动态内存或堆。
尽管每个进程拥有3GB的用户空间,但是其中的地址都是虚地址,因此,用户进程在这个虚拟内存中并不能真正地运行起来,必须把用户空间中的虚地址最终映射到物理存储空间才行,而这种映射的建立和管理是由内核完成的。所谓向内核申请一块空间,实际上是指请求内核分配一块虚存区间和相应的若干物理页面,并建立起映射关系。
内核在创建进时并不是为整个用户空间都分配好相应的物理空间,而是根据需要才真正分配一些物理页面并建立映射。在后面我们会看到,系统利用了请页机制来避免对物理内存的过分使用。因为进程访问的用户空间中的页可能当前不在物理内存中,这时,操作系统通过请页机制把数据从磁盘装入到物理内存。为此,系统需要修改进程的页表,以便标志用户空间中的页已经装入到物理页面中。由于上面这些原因,Linux 采用了比较复杂的数据结构跟踪进程的用户地址空间。
调用malloc分配的内存在堆空间中。用户空间的每个划分区域可以叫做虚存区。
image-20211117081849021

5、进程运行时,CPU 访问的是用户空间的物理地址。 ( × )

1
2
进程运行时,CPU访问的是用户空间的虚地址。
请页机制:Linux仅把当前要使用的用户空间中的少量页面装入内存,需要时再通过请页机制将特定的页面调入内存。当要访问的虚页不在内存时,产生一个页故障并报告故障原因。

6、伙伴算法的核心思想是回收时进行相邻块的合并。 ( × )

1
2
3
4
5
6
7
8
Linux使用伙伴算法有效地分配和回收物理页块。该算法试图分配由一个或多个连续物理页面组成的内存块,其大小为1页,2页,或4页等。只要系统有满足需要的足够的空闲页面,就会在free_area数组中查找满足需要大小的一个页块。
Linux的伙伴算法把所有的空闲页面分为10个块链表,每个链表中的一个块含有2的幂次个页面(叫做“页块”或简称“块”)
大小相同、物理地址连续的两个页块被称为伙伴。
工作原理:首先在大小满足要求的块链表中查找是否有空闲块,若有则直接分配,否则在更大的块中查找。其逆过程就是块的释放,此时会把满足伙伴关系的块合并。
伙伴算法为什么能减少碎片?
(1)在分配时,根据需要,分配与所需内存大小最相近稍大的块,这样碎片最少;
(2)在回收时,检查相邻的伙伴块,实时对释放的伙伴块进行合并;
综合以上原因,伙伴算法的关键是对不同大小的连续空闲页面进行了分区(块)的管理。

7、把虚地址转换成物理地址的过程是由硬件机制完成的,操作系统只是协助者。 ( ✓ )

8、伙伴算法负责大块物理内存的分配和释放,以页框为单位。 ( × )

9、缺页异常发生时会调用伙伴算法分配物理页面。 ( × )

1
2
3
4
页故障的产生有三种原因:
(1)程序出现错误,例如,要访问的虚地址在PAGE_OFFSET(3GB)之外,则该地址无效, Linux 将向进程发送一个信号并终止进程的运行;
(2)虚地址有效,但其所对应的页当前不在物理内存中,即缺页异常,这时,操作系统必须从磁盘或交换文件(此页被换出)中将其装入物理内存。这是本节要讨论的主要内容。
(3)要访问的虚地址被写保护,即保护错误,这时,操作系统必须判断:如果是某个用户进程正在写当前进程的地址空间,则发送一个信号并终止进程的运行。但是,如果错误发生在一旧的共享页上时,则处理方法有所不同,也就是要对这一共享页进行复制,这就是曾经描述过的“写时复制”技术。

10、Linux 内核对用户空间的管理是以虚存区为单位的。 ( ✓ )

1
2
3
4
Linux把进程的用户空间划分为一个个区间,便于管理。
一个进程的用户地址空间主要由mm_struct结构和vm_area_structs结构来描述。
mm_struct结构对进程整个用户空间进行描述
vm_area_structs结构对用户空间中各个区间(简称虚存区)进行描述

11、在 Linux 内核中为一个数据结构分配空间调用 kmalloc( ) 函数。 ( ✓ )

1
2
3
4
在内核空间中调用kmalloc()分配连续物理空间,而调用vmalloc()分配非物理连续空间。
我们把kmalloc()所分配内核空间中的地址称为内核逻辑地址
把vmalloc()分配的内核空间中的地址称为内核虚拟地址
当一个数据结构的使用不频繁、或其大小不足一个页面时,没有必要给其分配专用缓冲区 ,可调用函数kmalloc() 分配通用缓冲区

二、单选题

1、Linux 内核调用(C)为进程创建虚存区。

A VMA( ) B do_vma( ) C mmap( ) D do_mmap( )

1
2
mmap():在进程的用户空间内创建一个新的虚存区。
do_mmap():虚存映射都是通过mmap()系统调用对应的内核函数do_mmap() 来实现的。
image-20211117082813336

2、内核线程拥有的地址空间为(B)

A 0(3G-1)B B 3GB(4G-1)B C 0~(4G-1)B D 内核栈

3、 (B)系统调用为用户空间创建了一个新的虚存区。

A fork( ) B mmap( ) C munmap( ) D exe( )

4、用户进程向系统申请物理内存空间,Linux 内核通过调用(C)函数实现物理内存的分配。

A vmalloc( ) B kmalloc( ) C get_free_page( ) D malloc( )

1
2
3
内核在执行过程中使用的页面要经过动态分配,但永驻内存,此类页面根据其内容和性质可以分为两类:
内核调用kmalloc()或vmalloc()为内核中临时使用的数据结构而分配的页用完立即释放。但是,由于一个页面中存放有多个同种类型的数据结构,所以要到整个页面都空闲时才把该页面释放。
内核中通过调用__get_free_pages为某些临时使用和管理目的而分配的页面,例如,每个进程的内核栈所占的两个页面、从内核空间复制参数时所使用的页面等等,这些页面也是一旦使用完毕便无保存价值,所以立即释放。

5、内核为频繁使用的数据结构分配物理内存采用的是(C)

A 伙伴算法 B slab 机制 C vmalloc 机制 D Per-CPU 页框高速缓存

1
vmalloc()函数给内核分配一个非连续的内存区

第五章 中断和异常

一、判断题

1、中断分为上下两部分处理的原因是为了避免关中断太长导致中断的丢失,因此内核希望尽可能早些完成中断请求,尽量将更多可以推后的任务推后处理。( √ )

1
2
3
4
系统不能长时间关中断运行,因此内核应尽可能快的处理完中断请求,尽其所能把更多的处理向后推迟
内核把中断处理分为两部分:上半部(top half)和下半部(bottom half),上半部内核立即执行,而下半部留着稍后处理
中断服务例程在中断请求关闭的条件下执行,即执行上半部,避免嵌套使中断控制复杂化
下半部运行时是允许中断请求的,而上半部运行时是关中断的,这是二者之间的主要区别。

2、IDT 是指中断描述符表,是存放中断处理程序入口地址的一种表。 ( √ )

1
2
3
中断描述符表(IDT):即中断向量表,每个中断占据一个表项。在实地址模式中,CPU把内存中从0开始的1K字节作为一个中断向量表。表中的每个表项占四个字节,由两个字节的段地址和两个字节的偏移量组成,这样构成的地址便是相应中断处理程序的入口地址。
中断向量-每个中断源都被分配一个8位无符号整数作为类型码,即中断向量,Intel x86系列微机共支持256种向量中断.
所有256种中断可分为两大类:中断和异常。

3、jiffies 表示系统自启动以来的时间。 ( × )

1
2
3
4
5
OS时钟是由可编程定时/计数器产生的输出脉冲触发中断而产生的
操作系统的“时间基准” 由设计者决定,Linux的时间基准是1970年1月1日凌晨0点
OS时钟记录的时间就是系统时间。系统时间以“时钟节拍”为单位
Linux中用全局变量jiffies表示系统自启动以来的时钟节拍数目
实际时间存放在内核的xtime中,系统启动时内核通过读取RTC来初始化实际时间

4、中断的引入是为了支持设备和设备之间的并行操作。 ( × )

5、中断模型是一种 C/S 结构。 ( √ )

1
中断是CPU对系统发生某个时间做出的一种反应(what), 中断的引入是为了支持CPU和设备之间的并行操作(why),CPU在收到中断信号以后,并不立即执行响应,而是在执行每条指令周期的最后一个时钟周期,一旦检测到中断信号有效,并且中断允许位置1的时候,CPU才在当前指令执行完以后转入中断响应周期(when)。中断是一种C/S结构,当外设产生中断后并不是立刻传给CPU而是用中断控制器进行收集,然后分发给某个CPU进行处理并且应答(how)。

6、对中断的上半部分和下半部分执行的函数都为 do_irq。 ( √ )

1
所有的中断服务程序最后都要跳转到do_IRQ()函数并由它来依次执行中断服务队列中的ISR。

7、中断子系统由三个部分组成,分别为硬件无关的代码,CPU 体系结构相关的中断处理和中断控制器的驱动代码。 ( √ )

8、CPU 正在执行内核态的代码时被中断则堆栈不发生切换。 ( √ )

1
当中断发生在用户态(特权级为3),而中断处理程序运行在内核态(特权级为0),特权级发生了变化,所以会引起堆栈的更换。也就是说,从用户堆栈切换到内核堆栈。而当中断发生在内核态时,即CPU在内核中运行时,则不会更换堆栈。

9、CPU 在每个时钟周期都检查是否有中断。( × )

10、中断描述符表是段描述符表的一种。( × )

11、小任务不能睡眠,不能在小任务中使用信号量。( √ )

1
2
内核下半部实现机制是软中断(SOFTIRQ)机制,常用的是小任务机制和工作队列机制。小任务是指对要推迟执行的函数进行组织的一种方式。其数据结构为tasklet_struct,每个结构代表一个独立的小任务。小任务既可以静态地创建,也可以动态地创建。
小任务不能睡眠,不能在小任务中使用信号量或者其它产生阻塞的函数。但它运行时可以响应中断。

12、“时钟中断”是整个操作系统的脉搏。( √ )

13、中断请求队列的建立是为了解决中断线的共享问题。( √ )

二、单选题

1、注册中断处理程序是为了(D)。

​ A 将中断处理程序挂入中断请求队列 B 初始化 IDT

​ C 从中断返回 D 执行中断处理程序

2、操作系统启动以后,(B)时钟不再被使用。

​ A CMOS 时钟 B RTC C OS 时钟 D jiffies

3、操作系统启动后,使用的时钟是(C)。

​ A CMOS 时钟 B RTC C OS 时钟 D jiffies

1
2
3
大部分PC机中有两个时钟源,分别是实时时钟(RTC)和操作系统(OS)时钟。实时时钟也叫硬件时钟,它靠电池供电,即使系统断电,也可以维持日期和时间。RTC和OS时钟之间的关系通常也被称作操作系统的时钟运作机制。一般来说,RTC是OS时钟的时间基准,操作系统通过读取RTC来初始化OS时钟,此后二者保持同步运行,共同维持着系统时间。所谓同步,是指操作系统在运行过程中,每隔一个固定时间会刷新或校正RTC中的信息。
实时时钟:RTC时钟,用于提供年、月、日、时、分、秒和星期等的实时时间信息,由后备电池供电,当你晚上关闭系统和早上开启系统时,RTC仍然会保持正确的时间和日期。
系统时钟:是一个存储于系统内存中的逻辑时钟。用于系统的计算,比如超时产生的中断异常,超时计算就是由系统时钟计算的。这种时钟在系统掉电或重新启动时每次会被清除。

4、在中断上下文中,用(B)加锁。

​ A 信号量 B 自旋锁 C 原子操作 D 锁操作

1
2
3
自旋锁在内核中主要用来防止多处理器中并发访问临界区,防止内核抢占造成的竞争。 另外自旋锁不允许任务睡眠 ( 持有自旋锁的任务睡眠会造成自死锁 —— 因为睡眠有可能造成持有锁的内核任务被重新调度,而再次申请自己已持有的锁 ) ,它能够在中断上下文中使用 。
Lnux 中的信号量是一种睡眠锁。如果有一个任务试图获得一个已被持有的信号量时,信号量会将其推入等待队列,然后让其睡眠。这时处理器获得自由去执行其它代码。当持有信号量的进程将信号量释放后,在等待队列中的一个任务将被唤醒,从而便可以获得这个信号量。
如果代码需要睡眠,这往往是发生在和用户空间同步时,使用信号量是唯一的选择。由于不受睡眠的限制,使用信号量通常来说更加简单一些。如果需要在自旋锁和信号量中作选择,应该取决于锁被持有的时间长短。理想情况是所有的锁都应该尽可能短的被持有,但是如果锁的持有时间较长的话,使用信号量是更好的选择。另外,信号量不同于自旋锁,它不会关闭内核抢占 ,所以持有信号量的代码可以被抢占。这意味者信号量不会对影响调度反应时间带来负面影响。

5、中断描述符表初始化时,(C)的 DPL 域被置为 3。

​ A 中断门 B 陷阱门 C 系统门 D 以上三种门

1
2
3
4
5
6
7
8
9
在实地址模式中,CPU把内存中从0开始的1K字节作为一个中断向量表。表中的每个表项占四个字节,由两个字节的段地址和两个字节的偏移量组成,这样构成的地址便是相应中断处理程序的入口地址。但是,在保护模式下,由四字节的表项构成的中断向量表显然满足不了要求。这是因为,除了两个字节的段描述符,偏移量必用四字节来表示;要有反映模式切换的信息。因此,在保护模式下,中断向量表中的表项由8个字节组成,如图5.2所示,中断向量表也改叫做中断描述符表IDT(Interrupt Descriptor Table)。其中的每个表项叫做一个门描述符(gate descriptor),“门”的含义是当中断发生时必须先通过这些门,然后才能进入相应的处理程序。 
其中类型占3位,表示门描述符的类型,主要门描述符为:
(1)中断门(Interrupt gate)
其类型码为110,中断门包含了一个中断或异常处理程序所在段的选择符和段内偏移量。当控制权通过中断门进入中断处理程序时,处理器清IF标志,即关中断,以避免嵌套中断的发生。中断门中的请求特权级(DPL)为0,因此,用户态的进程不能访问Intel的中断门。所有的中断处理程序都由中断门激活,并全部限制在内核态。
(2)陷阱门(Trap gate)
其类型码为111,与中断门类似,其唯一的区别是,控制权通过陷阱门进入处理程序时维持IF标志位不变,也就是说,不关中断。
(3)系统门(System gate)
这是Linux内核特别设置的,用来让用户态的进程访问Intel的陷阱门,因此,门描述符的DPL为3。系统调用就是通过系统门进入内核的。
最后,在保护模式下,中断描述符表在内存的位置不再限于从地址0开始的地方,而是可以放在内存的任何地方。为此,CPU中增设了一个中断描述符表寄存器IDTR,用来存放中断描述符表在内存的起始地址。中断描述符表寄存器IDTR是一个48位的寄存器,其低16位保存中断描述符表的大小,高32位保存中断描述符表的基址

6、内核初始化时,中断描述符表的地址存放在(B)寄存器。

​ A GDTR B IDTR C LDTR D CR0

第六章 系统调用

一、判断题
1、从程序的角度看,实际上不直接与系统调用打交道,而是跟 API 打交道,API 是对系统调用的封装。( √ )
2、库函数以及应用程序怎样使用系统调用,内核并不关心,内核只跟系统调用打交道,而且是实现系统调用的大场景。 ( √ )
3、系统调用抽象出了用于完成某种特殊目的函数,至于这些函数怎么用,内核并不关心。这是机制与策略分离的具体体现。 ( √ )
4、用户空间的程序不能直接执行内核代码,它们不能直接调用内核空间中的函数,因为内核函数驻留在受保护的地址空间上。如果进程可以直接在内核的地址空间上读写的话,系统的安全性和稳定性将不复存在。 ( √ )
5、Linux 系统调用接口是指内核中所有已实现和可用系统调用的集合。 ( √ )
6、系统调用的实现与 CPU 体系结构无关。 ( × )
7、尽管内核版本不同,但其内核 API 是相同的。 ( √ )
8、对系统调用进行优化,是因为系统调用的实现从用户态切换到内核态,执行完系统调用程序后又从内核态切换回用户态,代价很大。 ( √ )
9、尽管系统调用号唯一的标识每个系统调用,但用户调用系统调用时并不需要知道系统调用号。( × )
10、ls 命令可以跟踪一个应用程序所调用的系统调用。( × )

二、单选题
1、(B)不属于系统调用处理程序所做的事情。
A 在内核栈保存大多数寄存器的内容 B 传递系统调用号
C 调用系统调用服务例程来处理系统调用
D 通过 iret 或者 sysexit 汇编指令从系统调用返回
2、系统调用是通过(A)进入其处理程序的。
A 中断门 B 陷阱门 C 系统门 D IDT
3、中断、异常和系统调用的相同点是(D)。
A 源头 B 响应方式 C 处理机制 D 都用 IDT 表描述
4、系统调用号是(A)传入给 eax 寄存器的。
A 在 lib 库中 B 通过 int 0x80 陷入内核后
C 在 IDT 表中 D 在 sys_call_table 中
5、(A)属于内核态。
A 系统调用表 B 应用程序 C glibc 库 D int 0x80

第七章 内核中的同步

一、判断题

1、竞争条件会导致各种难以调试的错误是因为可执行上下文在 CPU 上被调度的顺序受诸多因素的影响。( √ )

2、临界资源是访问和操作共享数据的代码段。 ( × )

1
临界资源是一种系统资源,需要不同进程互斥访问,而临界区则是每个进程中访问临界资源的一段代码,是属于对应进程的,临界区前后需要设置进入区和退出区以进行检查和恢复。临界区和临界资源是不同的,临界资源是必须互斥访问的资源,这种资源同时只能被一个进程所使用,但需要这种资源的进程不止一个,因此需要对使用临界资源的进程进行管理,这也就产生了临界区的概念。

3、为了避免对临界区进行并发访问,编程者必须保证临界区代码被原子地执行。 ( √ )

1
临界区(critical regions)就是访问和操作共享数据的代码段,这段代码必须被原子地执行。

4、中断屏蔽的缺点是有可能造成数据丢失甚至系统崩溃。 ( √ )

1
2
3
4
5
6
中断屏蔽:在进入临界区之前屏蔽系统的中断,从而保证正在执行的内核任务不被中断处理程序所抢占,防止某些静态条件的发生。在退出临界区后,重新打开中断。 
中断屏蔽的缺点:
(1)local_irq_disable()和local_irq_enable()
这两个函数都只能禁止和开启本地CPU内的中断,并不能解决多处理器引发的竞态(并行)
(2)在屏蔽中断期间所有的中断都无法得到处理
因此长时间屏蔽中断是很危险的,有可能造成数据丢失甚至系统崩溃。

5、自旋锁是专为防止多处理器并发而引入的一种锁,它在内核中大量应用于中断处理等部分,自旋锁可以被多个内核任务持有。 ( × )

1
2
自旋锁是专为防止多处理器并发而引入的一种锁,它在内核中大量应用于中断处理等部分,而对于单处理器来说,可简单采用关闭中断的方式防止中断处理程序的并发执行。自旋锁最多只能被一个内核任务持有,若一个内核任务试图请求一个已被持有的自旋锁,那么这个任务就会一直进行忙循环,也就是旋转,等待锁重新可用。
自旋锁不允许任务睡眠,持有自旋锁的任务睡眠会造成自死锁,因此自旋锁能够在中断上下文中使用。

6、在多核系统中遇到原子操作,在系统层面上原子操作还是原子操作的,在核级就不是原子的。 ( × )

7、在单 CPU 上,假设一个系统调用和一个中断服务程序并发执行,则对共享变量 V 的加 1 操作不会出现错误。 ( × )

8、使用嵌套锁时,获取锁的顺序无关紧要。 ( × )

9、对于临界区,进程之间可同时进行修改操作。( × )

10、如果数据只会被特定的进程访问,也无需加锁。( √ )

11、持有锁时需要睡眠和调度,优先考虑自旋锁。( × )

1
Linux中的信号量是一种睡眠锁。若有一个任务试图获得一个已被持有的信号量时,信号量会将其推入等待队列,然后让其睡眠。这时处理器获得自由而去执行其它代码。当持有信号量的进程将信号量释放后,在等待队列中的一个任务将被唤醒,从而便可以获得这个信号量。信号量具有睡眠特性,适用于锁会被长时间持有的情况,只能在进程上下文中使用。

二、单选题

1、并发执行的原因不包括(C)。

​ A 中断 B 内核抢占 C 自旋锁 D 睡眠

1
2
3
4
中断——中断几乎可以在任何时刻异步发生,也可能随时打断正在执行的代码。
内核抢占——若内核具有抢占性,内核中的任务就可能会被另一任务抢占。
睡眠及与用户空间的同步——在内核执行的进程可能会睡眠,这将唤醒调度程序,导致调度一个新的用户进程执行。
对称多处理——两个或多个处理器可以同时执行代码。

2、(D)不是内核的同步措施。

​ A 中断屏蔽 B 原子操作 C 自旋锁 D 临界区

1
为了避免并发,防止竞争。内核提供了一组同步方法来提供对共享数据的保护:中断屏蔽、原子操作、自旋锁、信号量。 

3、有两个并发执行的内核任务 t1 和 t2,共享初值为 1 的变量 x,t1 对 x 加 1,t2 对 x 减 1,两个操作完成后,x 的值为(C)。

​ A 可能为 -1 或 3 B 只能是 1 C 可能是 0,1,或 2 D 可能为 -1,0,1 或 2

image-20211117165542608

1
2
3
4
5
该操作可以转化成下面三条机器指令序列:
(1)得到当前变量i的值并拷贝到一个寄存器中
(2)将寄存器中的值加1
(3)把寄存器中i的新值写回到内存变量i中
将P1中3条语句依次编号为1、2、3;P2中3条语句依次编号为4、5、6。则依次执行1、2、3、4、5、6得结果1,依次执行1、2、4、5、6、3得结果2,执行4、5、1、2、3、6得结果0。结果-1不可能得出。

4、对共享变量 V 的加减赋值等操作,应该通过(A)完成。

​ A 原子操作 B 自旋锁 C 信号量 D RCU 锁

5、以相同的顺序获取嵌套锁,可阻止(B)的死锁。

​ A 拥抱类型 B 同步类型 C 异步类型 D 随机类型

6、内核避免死锁的算法是(B)

​ A 轮询算法 B 银行家算法 C 预测算法 D 电梯调度算法

第八章 文件系统

一、判断题

1、文件结构是文件存放在磁盘存储设备上的组织形式,主要体现在对文件和目录的组织上。( √ )

2、Linux 的目录结构为树型结构,每个分区是一个独立的文件系统,每个分区在这棵树上是一个叶子节点。 ( √ )

1
2
3
文件结构是文件存放在磁盘等存贮设备上的组织方法。主要体现在对文件和目录的组织上。 
Linux使用标准的目录结构-树型结构,无论操作系统管理几个磁盘分区,这样的目录树只有一个
制定这样一个固定的目录规划有助于对系统文件和不同的用户文件进行统一管理

3、Linux 文件系统使用索引节点不仅记录文件的结构数据,还存放文件的具体数据。 ( × )

1
2
文件系统:文件存在的物理空间,Linux系统中每个分区都是一个文件系统,都有自己的目录层次结构 
Linux文件系统使用索引节点来记录文件信息,系统给每个索引节点分配了一个号码,称为索引节点号。文件系统正是靠这个索引节点号来识别一个文件。

4、Linux 之所以能支持多种文件系统,并对其进行统一和高效的组织以及管理是因为虚拟文件系统,虚拟文件系统抽象出每个实际文件系统的共有属性,描述虚拟文件系统的数据结构是 super_block。 ( √ )

1
2
3
4
5
为了支持其他各种不同的文件系统,Linux提供了一种统一的框架,就是所谓的虚拟文件系统转换(Virtual Filesystem Switch),简称虚拟文件系统(VFS)。
级块(superblock)对象: 存放系统中已安装文件系统的有关信息。超级块用来描述整个文件系统的信息。每个具体的文件系统都有各自的超级块 VFS超级块是各种具体文件系统在安装时建立的,并在卸载时被自动删除,其数据结构是 super_block
索引节点(inode)对象: 存放关于具体文件的一般信息
目录项(dentry)对象: 存放目录项与对应文件进行链接的信息
文件(file)对象: 存放打开文件与进程之间进行交互的有关信息

5、虚拟文件系统所提供的抽象界面主要由一组标准的抽象操作构成,仅仅给出了函数的定义,并没有具体的实现,真正的实现是由具体的文件系统或者驱动程序完成的。 ( √ )

1
2
虚拟文件系统所提供的抽象界面主要由一组标准的、抽象的操作构成,例如read()、write()、lseek等,这些函数以系统调用的形式供用户程序调用。这样,用户程序调用这些系统调用时,根本无需关心所操作的文件属于哪个文件系统,这个文件系统是怎样设计和实现的。 
Linux的目录建立了一棵根目录为“/ ”的树。根目录包含在根文件系统中,在Linux 中,这个根文件系统通常就是 Ext2类型。其他所有的文件系统都可以被“安装”在根文件系统的子目录中。例如,用户可以通过“mount”命令,将DOS格式的磁盘分区(即FAT文件系统)安装到Linux系统中,然后,用户就可以像访问Ext2文件一样访问DOS的文件。

6、inode 和 file 数据结构的主要区别是:前者在文件建立时产生,存放于磁盘,后者在文件打开时才建立,存于内存。( √ )

1
2
inode 或i节点是指对文件的索引。如一个系统,所有文件是放在磁盘或flash上,就要编个目录来说明每个文件在什么地方,有什么属性,及大小等。就像书本的目录一样,便于查找和管理。这目录是操作系统需要的,用来找文件或叫管理文件。
在linux中,内核通过inode来找到每个文件,但一个文件可以被许多用户同时打开或一个用户同时打开多次。这就有一个问题,如何管理文件的当前位移量,因为可能每个用户打开文件后进行的操作都不一样,这样文件位移量也不同,当然还有其他的一些问题。所以linux又搞了一个文件描述符(file descriptor)这个东西,来分别为每一个用户服务。每个用户每次打开一个文件,就产生一个文件描述符,多次打开就产生多个文件描述符,一一对应,不管是同一个用户,还是多个用户。该文件描述符就记录了当前打开的文件的偏移量等数据。所以一个i节点可以有0个或多个文件描述符。多个文件描述符可以对应一个i节点。

7、虚拟文件系统各种对象的信息是存放在磁盘上的。 ( × )

1
文件(file)对象: 存放打开文件与进程之间进行交互的有关信息。这类信息仅当进程访问文件期间存在于内存中。 

8、一个进程要读取一个文件,同一个文件的内容存在了两份拷贝,一份是页缓存,一份是用户进程的堆空间对应的物理内存空间。这种方式有可能导致这两份数据的不一致。 ( √ )

9、一个 inode 对象对应多个 page 描述符,同一个文件拥有的所有 page 描述符都可以在该文件对应的基树中找到。 ( √ )

1
2
3
4
5
总结:address_space,inode,基树以及页描述符之间的关系
1、每个adrres_space对象对应一颗搜索树。他们之间的联系是通过address_space对象中的page_tree字段指向该address_space对象对应的基树。
2、一个inode节点对应一个address_space对象,其中inode节点对象的i_mapping和i_data字段指向相应的 address_space对象,而address_space对象的host字段指向对应的inode节点对象。
3、一般情况下一个inode节点对象对应的文件或者是块设备都会包含多个页面的内容,所以一个inode对象对应多个page描述符。同一个文件拥有的所有page描述符都可以在该文件对应的基树中找到。
因为一个文件可以被多个进程打开,所以多个文件表对象可以指向同一个文件节点,但多个文件表对象其对应的索引节点和目录项对象肯定是惟一的。一个inode(i节点)对应一个page cache对象,一个page cache对象包含多个物理page。

10、脏页集中到 page cache 中写回磁盘,虽然提高了性能,但当突然断电时,可能会导致内存与磁盘数据不一致性的问题。 ( √ )

二、单选题

1、当一个进程打开一个文件时, (B)数据结构才建立。

​ A fs_struct B file C dentry D inode

2、文件打开时形成的文件描述符 fd 存放在(C)数据结构中。

​ A fs_struct B file C files_struct D inode

1
文件描述符是用来描述打开的文件的。每个进程用一个files_struct结构来记录文件描述符的使用情况,这个files_struct结构称为用户打开文件表,它是进程的私有数据。

3、在文件的查找 look_up 操作中, (A)数据结构起关键作用。

​ A dentry B file C files_struct D inode

1
2
3
4
5
每个文件除了有一个索引节点inode数据结构外,还有一个目录项dentry数据结构。 
dentry结构代表的是逻辑意义上的文件,描述的是文件逻辑上的属性,目录项对象在磁盘上并没有对应的映像
inode结构代表的是物理意义上的文件,记录的是物理上的属性,对于一个具体的文件系统,其inode结构在磁盘上就有对应的映像
一个索引节点对象可能对应多个目录项对象
一个有效的dentry结构必定有一个inode结构,这是因为一个目录项要么代表着一个文件,要么代表着一个目录,而目录实际上也是文件。所以,只要dentry结构是有效的,则其指针d_inode必定指向一个inode结构。可是,反过来则不然,一个inode却可能对应着不止一个dentry结构;也就是说,一个文件可以有不止一个文件名或路径名。这是因为一个已经建立的文件可以被链接(link)到其他文件名。所以在inode结构中有一个队列i_dentry,凡是代表着同一个文件的所有目录项都通过其dentry结构中的d_alias域挂入相应inode结构中的i_dentry队列。

4、假设系统中安装了 4 个 ext4 文件系统,则系统中只有一个(A)结构。

​ A file_system_type B super_block C fs_struct D VFS mount

1
必须建立一个文件系统类型(file_system_type)来描述文件系统,它含有文件系统的名称、类型标志以及get_sb()等操作。

5、文件的树型结构是由(C)结构来描述的。

​ A fs_struct B file C dentry D inode

6、文件在磁盘上的存放位置是由(D)结构来描述的。

​ A fs_struct B file C dentry D inode

7、若 Linux 系统管理了 3 个磁盘分区,则该系统目录结构有(A)目录树。

​ A 1 个 B 2 个 C 3 个 D 4 个

第九章 设备驱动

一、判断题

1、文件操作是对设备操作的组织和抽象,而设备操作则是对文件操作的最终实现。( √ )

1
计算机中三个最基本的物质基础是CPU、内存和输入输出(I/O)设备,文件操作是对设备操作的组织和抽象,而设备操作则是对文件操作的最终实现。 

2、因为设备驱动程序完全隐藏了设备的工作细节,因此驱动程序的开发人员不需要了解硬件相关的细节。 ( × )

3、每个设备都对应一个文件名,在内核也就对应一个索引节点。 ( √ )

1
2
3
Linux操作系统把设备纳入文件系统的范畴来管理。
每个设备都对应一个文件名,在内核中也就对应一个索引节点。
对文件操作的系统调用大都适用于设备文件。

4、内核处理系统调用,根据设备文件类型和主设备号调用相应的设备驱动程序。 ( √ )

5、设备驱动直接与硬件通信。 ( √ )

1
设备驱动层直接与物理设备打交道,在实际的实现中则因系统的结构和具体设备的物理特性不同而有不同的驱动方式。

6、内存文件系统比如 proc 并不需要驱动程序。 ( × )

1
当用户进程发出输入输出时,系统把请求处理的权限放在文件系统,文件系统通过驱动程序提供的接口将任务下放到驱动程序,驱动程序根据需要对设备控制器进行操作,设备控制器再去控制设备本身。

7、网络设备与块设备和字符设备一样都在/dev 目录下对应一个设备文件。( × )

1
2
每一个字符设备或者块设备都在/dev目录下对应一个设备文件。读者可以通过查看/dev目录下的文件的属性,来区分设备是字符设备还是块设备。使用cd命令进入/dev目录,并执行ls -l命令就可以看到设备的属性。
网络设备是特殊设备的驱动,它负责接收和发送帧数据,可能是物理帧,也可能是ip数据包,这些特性都有网络驱动决定。它并不存在于/dev下面,所以与一般的设备不同。网络设备是一个net_device结构,并通过register_netdev注册到系统里,最后通过ifconfig -a的命令就能看到。

8、设备控制器是 CPU 与I/O设备之间的接口。 ( √ )

1
它是CPU与I/O设备之间的接口,它接收从CPU发来的命令,并去控制I/O设备工作,以使处理机从繁杂的设备控制事务中解脱出来。 设备控制器是一个可编址的设备,当它仅控制一个设备时,它只有一个唯一的设备地址;若控制可连接多个设备时,则应含有多个设备地址,并使每一个设备地址对应一个设备。

9、访问 I/O 接口的形式可分为 I/O 内存和 I/O 端口,访问 I/O内存用专用的I/O指令。( × )

10、可以把一个系统划分为应用、文件系统和设备驱动三个层次。( √ )

11、从应用程序的角度看,设备文件逻辑上的空间是一个线性空间(起始地址为 0,每读取一个字节加 1)。( √ )

1
从应用程序的角度看,设备文件逻辑上的空间是一个线性空间(起始地址为0,每读取一个字节加1)。从这个逻辑空间到具体设备物理空间(如磁盘的磁道、扇区)的映射则是由内核提供,并被划分为文件操作和设备驱动两个层次。

12、对 I/O 端口的访问和 I/O 空间的访问方式是一样的。( × )

13、网络驱动程序**同步**接受来自外部世界的数据包。( × )

14、Linux 设备模型将硬件设备归纳、分类,然后抽象出一套标准的数据结构和接口,驱动的开发就简化为对内核所规定的数据结构的填充和实现,这也是一种机制与策略分析思想的体现。 ( √ )

二、单选题

1、Linux 设备驱动模型使用一系列抽象, (D)不包括在其中。

​ A bus B device C driver D inode

2、用户程序发出磁盘 I/O 请求后,在系统处理流程中计算数据所在磁盘的柱面号、磁头号、扇区号的程序是(C)。

​ A 用户程序 B 系统调用程序 C 设备驱动程序 D 中断处理程序

3、字符设备驱动的编写中,(A)完成用户空间与内核空间数据的交换。

​ A 驱动的初始化 B 设备的操作 C 驱动的注销 D 硬件的初始化

4、Linux 内核中的驱动开发中,基本围绕(D)抽象进行。

​ A 总线 (bus) B 设备 (device) C 类 (class) D 驱动 (driver)

5、内核利用(B)层启动 I/O 操作来传达所请求的数据。

​ A VFS B 通用块 C I/O调度 D 块设备驱动程序

6、文件系统的读写单位是(B)。

​ A 字节 B 块 C 扇区 D 磁盘