
本书是针对计算机专业“操作系统”课程而编写的教材,课程所需总学时为85~96学时。本书由3篇组成。第1篇针对大纲要求,包括了课堂教学应涉及的主要知识点,并针对重点概念辅以例证。第2篇在第1篇的理论基础上,对具体的操作系统Linux-2.4.20-8版本,进行深入的内核分析。第3篇立足于Linux提供的用户界面,设置了若干难易适度的实验,与第1篇各章的教学同步进行。本书从用户界面,进程的创建、通信与同步,文件系统调用,设备驱动,内核修改直至多线程与网络TCP通信的综合应用,逐步深入,可以满足本课程对应用系统设计与开发能力的要求。
本书适于作为大专院校计算机及相关专业操作系统课程的教材,也可以作为Linux系统开发与内核分析的参考书。
课件07年7月6日更新
操作系统是计算机专业必修的核心专业课程,其重要性主要体现在以下几个方面:
(1)本课程在计算机学科知识体系中处于硬件知识与软件知识的结合点。
(2)本课程中关于进程和线程的概念是多任务应用程序设计的理论基础。
(3)操作系统所提供的系统调用界面是应用程序设计所必需的支撑环境。
(4)操作系统作为一个重要的系统软件,它用来解决各种复杂问题的思路和算法 对于计算机专业技术人员分析问题、解决问题和动手设计能力的培养有着深远的意义。
作为教材,其内容的设置除了需要考虑学生要形成的基本知识结构以外,还必须结合各高校的培养目标来设计各门课程的教学重点。对于绝大多数高校而言,其计算机类专业学生的培养目标大都定位在“基于应用系统的设计与开发的应用型人才”上。基于这个目标,操作系统课程实践的重点应该放在对操作系统所提供的支撑环境的使用上。
为此,我们按照以下思路编排本书:
第1篇为课堂教学内容,其深度能够满足大纲要求,其广度可以满足60~74学时课堂教学的所需内容。本附表中的学时安排可作为教师制定教学计划的参考。该篇以操作系统原理和UNIX为主线进行介绍,是本课程考核的重点。
第2篇在第1篇的基础上,以具体的操作系统Linux-2.4.20-8版本为平台,对其进行深入一步的剖析,目的在于与已经掌握了操作系统原理的读者以及对Linux感兴趣的读者一起对Linux操作系统做深入一步的探讨。
第3篇为实验内容,这个环节以Red Hat Linux 9为平台,内容立足于Linux所提供的各种用户界面,并与各章概念密切结合,目的在于加深对概念的理解。其中重点加强了进程、进程间通信和进程同步的实验,使读者能够在理论的指导下进一步深刻地理解进程和线程,掌握使用进程或线程实现多任务并发的程序设计思想和方法。实验内容基本与第1篇的各章同步(除第5章外,其他各章都安排了相应的实验)。实验1~8中,除实验5外,其他实验序号都与第1篇中对应的章号相同。此外还提供了两个综合性应用实验(实验9和实验10)作为课程设计的课题——修改系统内核和基于多线程的网络Socket编程,旨在进一步提高读者修改操作系统内核的能力和综合其他知识进行多线程程序设计的能力。
使用本书需要80~96学时(按照共16周、每周5~6学时计算),其中理论教学为60~74学时,其余用于实验。理论课只讲第1~2篇,各节标题上加有*标记的内容作
为参考,可以不讲。第3篇的实验内容可以根据各校情况选择全部或部分实验,建议每周1次,每次2学时。其中实验8、实验9和实验10的内容综合性较强,需要学时较多,可以作为课程设计或者短学期实习的课题。
为了方便实验与各章的同步,在第1篇各章的最后给出了与该章同步的实验名称供选择,而实验的内容和指导则集中放在第3篇中。每个实验的内容都在相关的章节中提供了类似的例证,并给出了算法框架、源代码、注释、运行结果以及结果分析。请读者在做每个实验之前预习有关章节的内容,这样,在做实验时就会感到轻松许多。
作者从事计算机操作系统课程的教学已有二十余年,深感缺少一本适合于培养应用型人才的、能够理论联系实际且难易适度、学时数且不涉及后继课程知识点的操作系统教材。经过多年的努力和实践,本书中的实验已经由计算机专业本科学生连续使用了5届,教学实践和多数学生毕业后的工作实践已证明效果非常好。主要是:敢于动手进行系统编程和修改内核;在多任务环境下能够主动使用多线程来解决多任务之间的同步或异步问题,而不是将多个任务放在一个任务中去解决。
本书包括13章和与各章有关的16个实验,其中胡明庆负责编写第1~8章,高巍负责编写第9章和第10章,钟梅负责编写第11章和第12章,高巍和钟梅合作编写第13章。第3篇中,除实验8由高巍编写之外,其余实验由胡明庆编写。
在本书的编写过程中得到了许多朋友的关心和帮助,朱定华教授、张钧良教授和赵一鸣教授对本书提出了很多宝贵的意见,陆静老师给出了第3篇部分实验的参考答案,张川老师在网络通信方面、贺贯中教授在数据结构方面给予了指导,计算机专业的学生赵振华、吴俊熳实现了Linux下的网络TCP通信,还有部分学生的实习报告也作为参考资料提交给读者参考。在此对所有支持本书出版的领导、老师、学生和朋友们表示衷心的感谢。
由于时间紧迫,加之笔者水平有限,错误和笔误在所难免,敬请广大读者批评指正。几位编者的联系方式如下:mingqhu@gmail.com(胡明庆),alexgaowei@gmail.com(高巍),camellia2006@gmail.com(钟梅)。
附表
章
学时
1
2
3
4
5
6
7
8
小计
6
2
14~18
4~8
6
8~10
12~14
8~10
总计
60~74学时
编 者
2006年8月
第1篇 操作系统原理
第1章 操作系统概述 2
1.1 操作系统的定义及其功能 2
1.2 操作系统的分类 4
1.2.1 多道程序设计技术与批处理系统 5
1.2.2 分时操作系统 6
1.2.3 实时操作系统 6
1.2.4 网络操作系统 6
1.2.5 分布式操作系统 7
1.2.6 个人操作系统 7
1.3 操作系统的特性 7
1.3.1 并发性 7
1.3.2 共享性 7
1.3.3 不确定性 8
1.3.4 虚拟性 8
1.4 操作系统的性能评价 8
1.5 操作系统的逻辑结构 9
1.5.1 模块化结构 9
1.5.2 层次化结构 9
1.5.3 虚拟机结构 9
1.5.4 客户/服务器结构 10
1.5.5 面向对象结构 10
1.6 支持操作系统的基本硬件结构 10
1.6.1 处理机的态 10
1.6.2 特权指令与处理机态的转换 10
1.6.3 时钟 11
1.6.4 中断机制 12
1.6.5 80386的寄存器组 16
1.6.6 80386的工作模式和特权级保护 20
习题1 24
第2章 用户界面 25
2.1 操作系统提供的用户界面 25
2.1.1 操作命令界面 25
2.1.2 系统调用界面 27
2.1.3 两种界面之间的关系 27
2.2 系统调用 27
2.2.1 系统调用的类型 27
2.2.2 系统调用的实现 28
2.2.3 系统调用与子程序调用的区别 29
2.3 Linux的系统调用 30
习题2 31
第3章 进程 32
3.1 进程的概念 32
3.1.1 多道程序并发执行 33
3.1.2 进程的定义 36
3.1.3 进程与程序的区别与联系 37
3.1.4 进程的类型 38
3.1.5 进程映像 38
3.1.6 进程状态及其变迁 43
3.2 进程控制 44
3.2.1 进程创建 45
3.2.2 进程撤销 51
3.2.3 进程睡眠 52
3.2.4 进程唤醒 53
3.3 进程同步与互斥 53
3.3.1 问题的提出 53
3.3.2 临界资源与临界区 54
3.3.3 互斥问题与同步问题 54
3.3.4 信号量及其P、V操作 56
3.3.5 用P、V操作实现进程同步与互斥 57
3.3.6 用P、V操作实现进程互斥与同步举例 57
3.3.7 管程的概念 67
3.4 Linux进程 68
3.4.1 Linux进程家族树 68
3.4.2 Linux中父进程等待子进程的同步 70
3.4.3 Linux中子进程映像的重新装入 73
3.5 线程 77
3.5.1 问题的提出 77
3.5.2 线程及其特征 78
3.5.3 线程的状态与线程控制块 79
3.5.4 线程的分类 79
3.5.5 线程与进程的关系 80
3.5.6 线程的优缺点 80
3.5.7 线程的适用范围 81
3.5.8 Linux线程的特点 82
3.5.9 线程举例 82
习题3 86
第4章 进程间通信 89
4.1 Linux软中断信号机制 89
4.1.1 软中断信号 89
4.1.2 软中断信号的使用方法 91
4.1.3 软中断信号的系统调用 92
4.1.4 应用举例 93
4.1.5 使用软中断实现父子进程同步 94
4.2 Linux管道通信 97
4.2.1 无名管道与命名管道 97
4.2.2 无名管道的实现方法 98
4.2.3 无名管道应用举例 100
*4.2.4 命名管道 101
4.3 Linux的IPC机制 101
4.4 Linux消息缓冲通信 103
4.4.1 消息缓冲通信概述 103
4.4.2 Linux消息缓冲通信的系统调用 107
4.4.3 消息缓冲通信应用举例 109
4.5 Linux共享内存通信 113
4.5.1 共享内存通信概述 113
4.5.2 共享内存通信的数据结构 113
4.5.3 共享内存通信的系统调用 114
4.5.4 共享内存通信实现方法 117
4.5.5 共享内存通信应用举例 118
4.6 几种通信方式小结 124
4.7 Linux信号量 124
4.7.1 Linux信号量的结构 124
4.7.2 有关信号量的系统调用函数 126
4.7.3 信号量及其P、V操作的实现 130
4.7.4 应用举例 131
习题4 143
第5章 资源分配与处理机调度 144
5.1 资源分配 144
5.2 死锁 144
5.2.1 死锁的概念 144
5.2.2 死锁的起因 145
5.2.3 产生死锁的必要条件 147
5.2.4 规避死锁的方法 147
5.3 处理机的多级调度 150
5.4 作业调度 151
5.4.1 作业的状态 151
5.4.2 作业控制块 152
5.4.3 作业调度目标与性能评价 152
5.4.4 调度算法 153
5.5 进程调度 156
5.5.1 进程上下文 156
5.5.2 进程调度的功能 157
5.5.3 进程调度的时机 158
5.5.4 进程调度策略 158
5.5.5 UNIX进程调度 159
习题5 162
第6章 内存管理 164
6.1 内存管理概述 165
6.1.1 计算机系统存储结构 165
6.1.2 操作系统内存管理与硬件系统的关系 165
6.1.3 操作系统内存管理的任务 166
6.2 分区内存管理 171
6.2.1 分区管理概述 171
6.2.2 动态分区的数据结构 173
6.2.3 动态分区的分配与回收 173
6.2.4 几种基本的放置策略 175
6.2.5 分区管理的虚拟存储的实现 177
6.2.6 碎片问题与拼接技术 177
6.3 分页内存管理 177
6.3.1 分页管理的基本原理 178
6.3.2 静态分页管理 180
6.3.3 请求分页管理与虚拟存储 181
6.3.4 请求分页的页表 182
6.3.5 请求分页管理的页面置换算法 182
6.3.6 抖动 184
6.3.7 分页管理的存储保护 185
6.3.8 快表 185
6.3.9 分页管理的优缺点 186
6.4 分段内存管理 186
6.4.1 段式管理的基本原理 187
6.4.2 分段管理的内存分配与回收 188
6.4.3 段的共享与保护 188
6.4.4 分段管理的优缺点 189
6.5 段页式内存管理 190
6.5.1 段页式管理中虚地址的构成 190
6.5.2 段表和页表 190
6.5.3 动态地址映射 191
6.6 UNIX的内存管理 191
6.6.1 UNIX内存管理概述 191
6.6.2 UNIX交换区及其管理 191
6.6.3 UNIX地址映射 193
6.6.4 UNIX请求分页的数据结构 194
6.6.5 UNIX的请求调页技术与页面错 196
6.6.6 UNIX的偷页进程 197
6.6.7 UNIX共享的实现 198
习题6 199
第7章 文件管理 200
7.1 文件管理概述 200
7.1.1 几个基本概念 200
7.1.2 文件的逻辑结构及其存取方式 203
7.1.3 文件的物理结构与存储设备 204
7.1.4 文件存储空间的管理 209
7.1.5 文件管理 210
7.1.6 文件完整性 218
7.1.7 文件操作 219
7.1.8 文件系统的层次模型 220
7.2 UNIX文件系统 221
7.2.1 UNIX文件系统的特点 221
7.2.2 UNIX文件i结点 222
7.2.3 UNIX文件的物理结构 222
7.2.4 UNIX文件结构 224
7.2.5 UNIX打开文件管理机构 224
7.2.6 UNIX存储空间的管理 228
习题7 232
第8章 设备管理 233
8.1 设备管理概述 233
8.1.1 设备的分类 234
8.1.2 设备管理的任务 234
8.1.3 设备独立性 234
8.1.4 缓冲技术 235
8.1.5 设备分配 236
8.1.6 输入输出控制 238
8.1.7 设备管理的数据结构 242
8.1.8 设备驱动程序 245
8.2 UNIX设备管理 245
8.2.1 UNIX块设备管理的数据结构 246
8.2.2 UNIX块设备缓冲区管理 248
8.2.3 UNIX设备驱动程序接口 257
*8.2.4 UNIX块设备驱动 259
*8.2.5 UNIX字符设备缓冲区管理 260
习题8 263
第2篇 Linux操作系统
第9章 Linux应用基础 266
9.1 Linux简介 266
9.1.1 UNIX的兴起 266
9.1.2 Linux的诞生 266
9.1.3 开源、自由和Linux 267
9.1.4 Linux操作系统的应用前景与未来 268
9.1.5 Linux操作系统的特点 269
9.1.6 Linux的发行版 270
9.1.7 Linux的应用软件 274
9.1.8 Linux资源 276
9.2 Linux的安装 277
9.2.1 Red Hat Linux 9的获得 277
9.2.2 计算机硬件准备 278
9.2.3 硬盘空间准备 279
9.2.4 安装方式选择 283
9.2.5 安装前配置 285
9.2.6 进行安装 297
9.2.7 安装后配置 298
9.2.8 安装完成 300
9.2.9 恢复被Windows破坏的GRUB引导程序 300
9.2.10 删除已安装的Red Hat Linux 9 301
9.3 Red Hat Linux的启动 302
9.3.1 Red Hat Linux启动菜单 302
9.3.2 系统登录、注销和关机 302
9.3.3 文本模式与图形模式的切换 306
9.4 Linux文本编辑器Vi的使用 307
9.4.1 执行与结束Vi 307
9.4.2 Vi的3种模式及相互切换 308
9.4.3 编辑模式下的操作 309
9.4.4 命令模式下的操作 311
9.5 Linux中的C语言编译器GCC的使用 312
9.5.1 使用GCC 313
9.5.2 GCC 选项 314
9.6 Linux主要介绍 315
9.6.1 Linux系统 315
9.6.2 /usr子 315
9.6.3 /etc子 316
9.6.4 /usr/src/linux子 316
第10章 Linux的操作命令界面与内核编译 317
10.1 Linux键盘命令 317
10.1.1 通配符 317
10.1.2 登录和退出Linux系统 318
10.1.3 操作 319
10.1.4 文件操作 322
10.1.5 时间和帮助 334
10.1.6 用户管理 335
10.1.7 磁盘管理 338
10.1.8 系统管理 340
10.2 Red Hat Linux图形界面基本操作 341
10.2.1 GNOME简介 341
10.2.2 GNOME的组成 341
10.2.3 GNOME的基本使用方法 342
10.2.4 GNOME与KDE互换 351
10.3 Linux批处理作业控制语言(shell编程) 352
10.3.1 制作并运行作业控制程序 352
10.3.2 作业控制语句 354
10.4 Linux系统模块的安装与连接 359
10.4.1 makefile模块之间的关系 359
10.4.2 make实现模块的编译连接 360
10.5 Linux中内核修改与内核重新编译 360
10.5.1 内核重新编译 360
10.5.2 在Linux内核中增加一个系统调用举例 361
第11章 Linux任务管理与内存管理 366
11.1 Linux任务管理 366
11.1.1 进程的数据结构 366
11.1.2 Linux进程状态及其变迁 373
11.1.3 Linux进程创建 374
11.1.4 Linux进程调度 375
11.2 80386体系结构提供的内存管理机制 382
11.2.1 80386 CPU提供的工作模式与地址映射机制 382
11.2.2 80386实模式下的地址映射 382
11.2.3 80386 CPU提供的保护模式 383
11.2.4 80386的cache 385
11.3 Linux地址映射与页表 385
11.3.1 Linux地址映射 385
11.3.2 Linux页数据结构 387
11.4 Linux内存管理 389
11.4.1 Linux用户进程虚拟地址空间 390
11.4.2 Linux的物理内存管理 395
11.4.3 Linux内存映射与缺页中断 403
11.4.4 Linux页交换 405
11.4.5 Linux内存分配策略和系统调用 407
第12章 Linux文件管理 410
12.1 Linux的ext2文件系统 411
12.1.1 ext2文件系统的主要特点 411
12.1.2 ext2文件系统的逻辑结构与物理结构 412
12.1.3 ext2文件系统对存储空间的管理 415
12.1.4 ext2文件与文件共享 420
12.2 Linux的虚拟文件系统VFS 422
12.2.1 VFS文件系统的主要功能 422
12.2.2 VFS的通用文件模型 423
12.3 进程与文件系统的关系 430
12.3.1 相关的数据结构 430
12.3.2 进程与文件系统的关系 431
12.4 VFS打开文件管理机构 431
12.4.1 VFS打开文件管理机构的组成 431
12.4.2 3个打开文件数据结构之间的关系 432
12.5 Linux文件系统的各种缓存 434
12.6 Linux文件系统调用 435
12.6.1 文件的打开和关闭 435
12.6.2 文件的读写 437
12.6.3 文件的随机存取 439
12.6.4 文件的保护和控制 440
12.6.5 文件管理 444
12.6.6 文件信息查询 446
第13章 Linux设备管理 447
13.1 Linux设备管理概述 447
13.1.1 Linux的设备分类 448
13.1.2 Linux的设备文件 449
13.1.3 设备驱动程序接口 451
13.1.4 块设备的设备文件接口 452
13.2 设备管理与注册 456
13.2.1 字符设备管理 456
13.2.2 块设备管理 459
13.3 块设备的请求队列与读写访问 464
13.3.1 Linux块设备的缓冲机制 464
13.3.2 块设备请求队列的相关数据结构 467
13.3.3 请求队列的初始化与清除 470
13.3.4 块设备读写请求提交过程 470
13.4 设备文件系统 471
13.4.1 devfs的基本概念 471
13.4.2 启用devfs 472
13.4.3 devfs的关键数据结构 473
13.4.4 devfs结点注册函数 476
13.5 设备驱动程序框架 478
13.5.1 设备驱动程序简介 478
13.5.2 设备驱动程序的注册与注销 479
13.5.3 设备的打开与释放 479
13.5.4 设备的读写操作 479
13.5.5 设备的控制操作 480
13.5.6 设备中断与循环查询处理 480
13.6 字符设备驱动程序实例分析 480
13.6.1 编写字符设备驱动程序mydriver.c 481
13.6.2 编译设备驱动模块mydriver 483
13.6.3 设备驱动模块mydriver的装载 483
13.6.4 创建字符设备文件mydriver 484
13.6.5 编写测试程序test.c 484
13.6.6 编译和执行测试程序 485
13.6.7 卸载驱动模块并删除字符设备文件 486
第3篇 实 验
实验1 Linux的安装 488
实验2-1 Linux的键盘命令 489
实验2-2 Linux的图形界面 492
实验2-3 Linux的批处理 493
实验3-1 Linux进程的创建与父子进程同步 495
实验3-2 Linux子进程映像的重新加载 497
实验4-1 Linux软中断通信 498
实验4-2 Linux管道通信 500
实验4-3 Linux消息缓冲通信 501
实验4-4 Linux共享存储通信 503
实验5 Linux信号量与P、V操作 505
实验6 动态申请内存 507
实验7 Linux文件系统调用 508
实验8 Linux字符设备驱动 509
实验9 在Linux中增加一个新的系统调用函数 510
实验10 网络聊天室的设计 511
参考文献 525
VIII
操作系统教程与实验
XV