计算机操作系统简介
目标
- 了解操作系统的发展历史
- 知道 Linux 内核及发行版的区别
- 知道 Linux 的应用领域
任何计算机都必须在加载相应的操作系统之后,才能构成一个可以运转的、完整的计算机系统。操作系统的功能是否强大,决定了计算机系统的综合能力;操作系统的性能高低,决定了整个计算机系统的性能;操作系统本身的安全可靠程度,决定了整个计算机系统的安全性和可靠性。操作系统是软件技术的核心和基础运行平台。因此,计算机科学技术专业的学生需要学习和掌握操作系统的基本原理和专业知识。
本课程的教学目标是:
1.掌握操作系统的基本概念、功能组成、系统结构及运行环境;
2.熟悉并运用操作系统工作原理、设计方法和实现技术,理解有代表性、典型的操作系统实例(如UNIX、Linux和Windows);
3.了解操作系统的演化过程、发展研究动向、新技术以及新思想,为后续相关课程的学习打下良好基础,为后续职业发展奠定基石。
1. 操作系统的发展历史
1.1 Unix
1965 年之前的时候,电脑并不像现在一样普遍,它可不是一般人能碰的起的,除非是军事或者学院的研究机构,而且当时大型主机至多能提供30台终端(30个键盘、显示器),连接一台电脑:

为了解决数量不够用的问题
- 1965 年左后由 贝尔实验室 加入了 麻省理工学院 以及 通用电气 合作的计划 —— 该计划要建立一套 多使用者(multi-user)、多任务(multi-processor)、多层次(multi-level) 的 MULTICS 操作系统,想让大型主机支持 300 台终端
- 1969 年前后这个项目进度缓慢,资金短缺,贝尔实验室退出了研究
- 1969 年从这个项目中退出的 Ken Thompson 当时在实验室无聊时,为了让一台空闲的电脑上能够运行 "星际旅行(Space Travel)" 游行,在 8 月份左右趁着其妻子探亲的时间,用了 1 个月的时间,使用汇编写出了 Unix 操作系统的原型
- 1970 年,美国贝尔实验室的 Ken Thompson,以 BCPL 语言为基础,设计出很简单且很接近硬件的 B 语言(取BCPL的首字母),并且他用 B 语言 写了第一个 UNIX 操作系统
- 1971 年,同样酷爱 "星际旅行(Space Travel)" 的 Dennis M.Ritchie 为了能早点儿玩上游戏,加入了 Thompson 的开发项目,合作开发 UNIX,他的主要工作是改造 B 语言,因为B 语言 的跨平台性较差
- 1972 年,Dennis M.Ritchie 在 B 语言 的基础上最终设计出了一种新的语言,他取了 BCPL 的第二个字母作为这种语言的名字,这就是 C 语言
- 1973 年初,C 语言的主体完成,Thompson 和 Ritchie 迫不及待地开始用它完全重写了现在大名鼎鼎的 Unix 操作系统

肯·汤普逊(左)和丹尼斯·里奇(右)
C 语言
- 在把 UNIX 移植到其他类型的计算机上使用时,C 语言强大的移植性(Portability)在此显现
- 机器语言和汇编语言都不具有移植性,为 x86 开发的程序,不可能在 Alpha,SPARC 和 ARM 等机器上运行
- 而 C 语言程序则可以使用在任意架构的处理器上,只要那种架构的处理器具有对应的 C 语言编译器和库,然后将 C 源代码编译、连接成目标二进制文件之后即可运行
Unix 家谱

1.2 Minix
- 因为 AT&T(通用电气) 的政策改变,在 Version 7 Unix 推出之后,发布新的使用条款,将 UNIX 源代码私有化,在大学中不再能使用 UNIX 源代码
- Andrew S. Tanenbaum(塔能鲍姆) 教授为了能 在课堂上教授学生操作系统运作的细节,决定在不使用任何 AT&T 的源代码前提下,自行开发与 UNIX 兼容的操作系统,以避免版权上的争议
- 以 小型 UNIX(mini-UNIX)之意,将它称为 MINIX
1.3 Linux
- 1991 年 林纳斯(Linus) 就读于赫尔辛基大学期间,对 Unix 产生浓厚兴趣,尝试着在Minix 上做一些开发工作
- 因为 Minix 只是教学使用,因此功能并不强,林纳斯 经常要用他的终端 仿真器(Terminal Emulator) 去访问大学主机上的新闻组和邮件,为了方便读写和下载文件,他自己编写了磁盘驱动程序和文件系统,这些在后来成为了 Linux 第一个内核的雏形,当时,他年仅 21 岁!
-
林纳斯 利用 GNU 的 bash 当做开发环境,gcc 当做编译工具,编写了 Linux 内核,一开始 Linux 并不能兼容 Unix
- 即 Unix 上跑的应用程序不能在 Linux 上跑,即应用程序与内核之间的接口不一致
- 一开始 Linux 只适用于 386,后来经过全世界的网友的帮助,最终能够兼容多种硬件

2. Linux 内核及发行版
2.1 Linux 内核版本
- 内核(kernel)是系统的心脏,是运行程序和管理像磁盘和打印机等硬件设备的核心程序,它提供了一个在裸设备与应用程序间的抽象层
- Linux 内核版本又分为 稳定版 和 开发版,两种版本是相互关联,相互循环
- 稳定版:具有工业级强度,可以广泛地应用和部署。新的稳定版相对于较旧的只是修正一些 bug 或加入一些新的驱动程序
- 开发版:由于要试验各种解决方案,所以变化很快
- 内核源码网址:http://www.kernel.org
所有来自全世界的对 Linux 源码的修改最终都会汇总到这个网站,由 Linus 领导的开源社区对其进行甄别和修改最终决定是否进入到 Linux 主线内核源码中
2.2 Linux 发行版本
- Linux 发行版(也被叫做 GNU/Linux 发行版)通常包含了包括桌面环境、办公套件、媒体播放器、数据库等应用软件
-
常见的发行版本如下:
- Ubuntu
- Redhat
- Fedora
- openSUSE
- Linux Mint
- Debian
- Manjaro
- Mageia
- CentOS
- Arch
-
十大 Linux 服务器发行版排行榜:http://os.51cto.com/art/201612/526126.htm
在几乎每一份与 Linux 有关的榜单上,基于 Debian 的 Ubuntu 都占有一席之位。Canonical 的Ubuntu 胜过其他所有的 Linux 服务器发行版 ―― 从简单安装、出色的硬件发现,到世界级的商业支持,Ubuntu确立了难以企及的严格标准
3. Linux 的应用领域
3.1 服务器领域
- Linux 在服务器领域的应用是其重要分支
- Linux 免费、稳定、高效等特点在这里得到了很好的体现
- 早期因为维护、运行等原因同样受到了很大的限制
- 近些年来 Linux 服务器市场得到了飞速的提升,尤其在一些高端领域尤为广泛
3.2 嵌入式领域
- 近些年来 Linux 在嵌入式领域的应用得到了飞速的提高
- Linux 运行稳定、对网络的良好支持性、低成本,且可以根据需要进行软件裁剪,内核最小可以达到几百 KB 等特点,使其近些年来在嵌入式领域的应用得到非常大的提高
主要应用:机顶盒、数字电视、网络电话、程控交换机、手机、PDA、等都是其应用领域,得到了 Google、三星、摩托罗拉、NEC 等公司的大力推广
3.3 个人桌面领域
- 此领域是传统 Linux 应用最薄弱的环节
- 传统 Linux 由于界面简单、操作复杂、应用软件少的缺点,一直被 Windows 所压制
- 近些年来随着 Ubuntu、Fedora 等优秀桌面环境的兴起,同时各大硬件厂商对其支持的加大,Linux 在个人桌面领域的占有率在逐渐的提高。
4.操作系统的架构
UNIX
UNIX 与 Linux 之间的关系是一个很有意思的话题。在目前主流的服务器端操作系统中,UNIX 诞生于 20 世纪 60 年代末,Windows 诞生于 20 世纪 80 年代中期,Linux 诞生于 20 世纪 90 年代初,可以说 UNIX 是操作系统中的"老大哥",后来的 Windows 和 Linux 都参考了 UNIX。
UNIX是一个多用户、多任务的操作系统。 UNIX系统由硬件、内核、Shell和应用程序组成。 用户通过shell向内核发出命令。 UNIX文件系统是树状层次结构。
诞生
1965年时,贝尔实验室(Bell Labs)加入一项由通用电气(General Electric)和麻省理工学院(MIT)合作
图1-1 PDP-7计算机
的计划;该计划要建立一套多使用者、多任务、多层次(multi-user、multi-processor、multi-level)的MULTICS操作系统 [1] 。直到1969年,因MULTICS计划的工作进度太慢,该计划被停了下来。当时,Ken Thompson(后被称为UNIX之父)已经有一个称为"星际旅行"的程序在GE-635的机器上跑,但是反应非常慢,正巧被他发现了一部被闲置的PDP-7(Digital的主机),Ken Thompson和Dernis Ritchie就将"星际旅行"的程序移植到PDP-7上。而这部PDP-7(如图1-1所示)就此在整个计算机历史上留下了芳名。
MULTICS其实是"Multiplexed Information and Computing Service"的缩写,在1970年时,那部PDP-7却只能支持两个使用者,当时,Brian Kernighan就开玩笑地称他们的系统其实是:"UNiplexed Information and Computing Service",缩写为"UNICS",后来,大家取其谐音,就称其为"UNIX"了。1970年可称为"UNIX元年"。
流行
1971年,Ken Thompson写了充分长篇的申请报告,申请到了一台PDP-11/24的机器。于是Unix第一版出来了。在一台PDP-11/24的机器上完成。这台电脑只有24KB的物理内存和500K磁盘空间。Unix占用了12KB的内存,剩下的一半内存可以支持两用户进行Space Travel的游戏。而著名的fork()系统调用也就是在这时出现的。
到了1973年的时候,Ken Thompson 与Dennis Ritchie感到用汇编语言做移植太过于头痛,他们想用高级语言来完成第三版,对于当时完全以汇编语言来开发程序的年代,他们的想法算是相当的疯狂。一开始他们想尝试用Fortran,可是失败了。后来他们用一个叫BCPL(Basic Combined Programming Language)的语言开发,他们整合了BCPL形成B语言,后来Dennis Ritchie觉得B语言还是不能满足要求,于是就改良了B语言,这就是大名鼎鼎的C语言。于是,Ken Thompson 与Dennis Ritchie成功地用C语言重
Unix
写了Unix的第三版内核。至此,Unix这个操作系统修改、移植相当便利,为Unix日后的普及打下了坚实的基础。而Unix和C结合成为一个统一体,C与Unix很快成为世界的主导。
Unix的第一篇文章 “The UNIX Time Sharing System”由Ken Thompson和Dennis Ritchie于1974年7月的 The Communications of the ACM发表。这是UNIX与外界的首次接触。结果引起了学术界的广泛兴趣并对其源码索取,所以,Unix第五版就以“仅用于教育目的”的协议,提供给各大学作为教学之用,成为当时操作系统课程中的范例教材。各大学公司开始通过Unix源码对Unix进行了各种各样的改进和扩展。于是,Unix开始广泛流行。
在严格意义上,可将操作系统定义为一种软件,它控制计算机硬件资源,提供程序运行环境,一般而言,我们称此种软件为内核(kenel),它相对较小,位于环境的中心。
内核的接口被称为系统调用(system call)。公用函数库构建在系统调用接口之上,应用软件既可使用公用函数库,也可以使用系统调用。
Shell是一种特殊的应用程序,它提供接口来运行其他的应用程序。
广义上来说,操作系统是内核和所有其他的软件的集合,其让一个计算机变得有用以及给计算机以个性。其他的软件包括系统工具,应用程序,shells,通用函数库等等。
Unix文件系统是对存储设备上的数据和元数据进行组织的机制。UNIX文件系统是UNIX系统的心脏部分,提供了层次结构的目录和文件。
Unix内核基本上是按模块进行设计的,比如文件子系统,进程控制子系统等等,各个子系统相对比较独立,但在有必要的时候又可以进行彼此的沟通交流。下图就说明了早期Unix的系统内核框架。
文件子系统概要
什么是文件系统?
文件系统是一个逻辑(看不见,摸不着)上的概念,而磁盘是一个物理(真实存在,看得见,摸得着)上的概念。
一套系统装置可以有若干个物理磁盘设备,每一个物理设备上可以包含一个或者多个文件系统(如下图所示),当然也可以不包含任何文件系统(那你买它干啥?)。下面涉及到的文件系统都是在 Unix 上的。
Unix内核在逻辑上只涉及文件系统,屏蔽了磁盘,一个文件系统就是一一个逻辑设备,每个逻辑设备(或文件系统)由一个逻辑设备号进行标识。这些逻辑设备被映射到物理设备(磁盘)上,由磁盘驱动程序负责将逻辑设备地址映射到物理设备地址。一个物理设备(磁盘)可以被分成好几个逻辑设备,可以使我们更好的管理我们的数据。
一个文件系统由一个逻辑块序列组成,块大小可以为512字节、1024字节等(n*512字节)。一个文件系统中的每个逻辑块大小是相同的,而不同的文件系统间的逻辑块大小可能会因为系统的配置而各不相同(如下图所示)。内核在磁盘操作中以块大小为基本单位进行数据的传输,而不是以磁盘上的扇区为基本单位。
一个文件系统的结构包括引导块(boot block)、超级块(super block)、索引节点表(inode list)以及数据块(data blocks)(如下图所示)。
引导块:在文件系统的开头,典型地一般为一个扇区。如果操作系统装在该文件系统中,则该块包含了引导或初启操作系统的引导代码。如果没该文件系统没安装操作系统,则这个块的内容可能是空的。
超级块:相当于是保存了文件系统的元数据信息,描述文件系统的状态,比如它有多大,何处有空闲空间以及其他一些信息等等。(可通过 $ tune2fs -l 文件系统来查看文件系统的超级块的内容,需要root权限)
索引节点表:相当于是索引节点的一个数组,内核所引用的索引节点号即是索引节点在该数组中的下标大小。类似于文件的元数据信息。每个文件都有一个索引节点,但是一个索引节点可以对应几个文件名字,每个名字被称为一个链接(link)。内核实现文件名到索引节点的解析。
数据块:真正存放数据的地方。目录(PS:也是一个文件)在数据块中保存的数据是一系列的索引节点 <-> 文件名的 item。
内核中维护着三种表结构,分别是用户文件描述符表(user file descriptor table)、文件表(file table)和索引节点表(inode table)。
用户文件描述符表:每个进程被单独分配一个。该表标识着一个进程的所有打开的文件。对于系统调用 open和系统调用 creat,内核返回一个文件描述符(file descriptor),它是在用户文件描述符表中的索引值(每次调用这两个函数中的任意一个时,内核返回该用户文件描述表中可用的最小的表项的索引值,如果调用系统调用close时,内核会释放传递给close的文件描述符所对应的表项,使该表项重新可用)。0、1和2这三个文件描述符分别表示标准输入文件、标准输出文件和标准错误输出文件。
文件表:是一个全局核心结构。文件表保存着文件中的字节偏移量(下一次读或写的位置),并保存着对打开的进程所允许的存取权限。
索引节点表:也是一个全局核心结构。索引节点被存储在文件系统中(磁盘上),但是当操纵文件的时候,内核把它们读到内存索引节点表中。
当一个进程打开或创建一个文件时,内核在每个表中为相应于该文件的索引节点分配一个表项,用这三种结构表中的表项来维护文件的状态及用户对它的存取。使用这三张表,可以实现对一个文件的不同程度的存取共享。下图表示了这三张表即它们之间的相互关系。
Linux
随后出现了各种版本的 UNIX 系统,目前常见的有 Sun Solaris、FreeBSD、IBM AIX、HP-UX 等。
Solaris 和 FreeBSD
我们重点介绍一下 Solaris,它是 UNIX 系统的一个重要分支。Solaris 除可以运行在 SPARC CPU 平台上外,还可以运行在 x86 CPU 平台上。在服务器市场上,Sun 的硬件平台具有高可用性和高可靠性,是市场上处于支配地位的 UNIX 系统。
对于难以接触到 Sun SPARC 架构计算机的用户来说,可以通过使用 Solaris x86 来体验世界知名大厂的商业 UNIX 风采。当然,Solaris x86 也可以用于实际生产应用的服务器,在遵守 Sun 的有关许可条款的情况下,Solaris x86 可以免费用于学习研究或商业应用。
FreeBSD 源于美国加利福尼亚大学伯克利分校开发的 UNIX 版本,它由来自世界各地的志愿者开发和维护,为不同架构的计算机系统提供了不同程度的支持。FreeBSD 在 BSD 许可协议下发布,允许任何人在保留版权和许可协议信息的前提下随意使用和发行,并不限制将 FreeBSD 的代码在另一协议下发行,因此商业公司可以*地将 FreeBSD 代码融入它们的产品中。苹果公司的 OS X 就是基于 FreeBSD 的操作系统。
FreeBSD 与 Linux 的用户群有相当一部分是重合的,二者支持的硬件环境也比较一致,所采用的软件也比较类似。FreeBSD 的最大特点就是稳定和高效,是作为服务器操作系统的不错选择;但其对硬件的支持没有 Linux 完备,所以并不适合作为桌面系统。
Linux 的那些往事
Linux操作系统的诞生、发展和成长过程始终依赖着五个重要支柱:Unix操作系统、MINIX操作系统、GNU计划、POSIX标准和Internet网络。
20世纪80年代,计算机硬件的性能不断提高,PC的市场不断扩大,当时可供计算机选用的操作系统主要有Unix、DOS和MacOS这几种。Unix价格昂贵,不能运行于PC;DOS显得简陋,且源代码被软件厂商严格保密;
MacOS是一种专门用于苹果计算机的操作系统。此时,计算机科学领域迫切需要一个更加完善、强大、廉价和完全开放的操作系统。由于供教学使用的典型操作系统很少,因此当时在荷兰当教授的美国人AndrewS.Tanenbaum编写了一个操作系统,名为MINIX,为了向学生讲述操作系统内部工作原理。MINIX虽然很好,但只是一个用于教学目的的简单操作系统,而不是一个强有力的实用操作系统,然而最大的好处就是公开源代码。
全世界学计算机的学生都通过钻研MINIX源代码来了解电脑里运行的MINIX操作系统,芬兰赫尔辛基大学大学二年级的学生Linus Torvalds就是其中一个,在吸收了MINIX精华的基础上,Linus于1991年写出了属于自己的Linux操作系统,版本为Linux0.01,是Linux时代开始的标志。他利用Unix的核心,去除繁杂的核心程序,改写成适用于一般计算机的x86系统,并放在网络上供大家下载,1994年推出完整的核心Version1.0,至此,Linux逐渐成为功能完善、稳定的操作系统,并被广泛使用。
Linux 内核最初是由李纳斯•托瓦兹(Linus Torvalds)在赫尔辛基大学读书时出于个人爱好而编写的,当时他觉得教学用的迷你版 UNIX 操作系统 Minix 太难用了,于是决定自己开发一个操作系统。第 1 版本于 1991 年 9 月发布,当时仅有 10 000 行代码。
李纳斯•托瓦兹没有保留 Linux 源代码的版权,公开了代码,并邀请他人一起完善 Linux。与 Windows 及其他有专利权的操作系统不同,Linux 开放源代码,任何人都可以免费使用它。
据估计,现在只有 2% 的 Linux 核心代码是由李纳斯•托瓦兹自己编写的,虽然他仍然拥有 Linux 内核(操作系统的核心部分),并且保留了选择新代码和需要合并的新方法的最终裁定权。现在大家所使用的 Linux,我更倾向于说是由李纳斯•托瓦兹和后来陆续加入的众多 Linux 好者共同开发完成的。
李纳斯•托瓦兹无疑是这个世界上最伟大的程序员之一,何况,他还搞出了全世界最大的程序员交友社区 GitHub (开源代码库及版本控制系统)。
关于 Linux Logo 的由来是一个很有意思的话题,它是一只企鹅。
为什么选择企鹅,而不是选择狮子、老虎或者小白兔?有人说因为李纳斯•托瓦兹是芬兰人,所以选择企鹅,有人说因为其他动物图案都被用光了,李纳斯•托瓦兹只好选择企鹅。
我更愿意相信以下说法,企鹅是南极洲的标志性动物,根据国际公约,南极洲为全人类共同所有,不属于世界上的任何国家,可国家都无权将南极洲纳入其版图。Linux 选择企鹅图案作为 Logo,其含义是:开放源代码的 Linux 为全人类共同所有,可公司无权将其私有。
UNIX与Linux的亲密关系
二者的关系,不是大哥和小弟,"UNIX 是 Linux 的父亲"这个说法更怡当。之所以要介绍它们的关系,是因为要告诉读者,在学习的时候,其实 Linux 与 UNIX 有很多的共通之处,简单地说,如果你已经熟练掌握了 Linux,那么再上手使用 UNIX 会非常容易。
二者也有两个大的区别:
- UNIX 系统大多是与硬件配套的,也就是说,大多数 UNIX 系统如 AIX、HP-UX 等是无法安装在 x86 服务器和个人计算机上的,而 Linux 则可以运行在多种硬件平台上;
- UNIX 是商业软件,而 Linux 是开源软件,是免费、公开源代码的。
Linux 受至旷大计算机爱好者的喜爱,主要原因也有两个:
- 它属于开源软件,用户不用支付可费用就可以获得它和它的源代码,并且可以根据自己的需要对它进行必要的修改,无偿使用,无约束地继续传播;
- 它具有 UNIX 的全部功能,任何使用 UNIX 操作系统或想要学习 UNIX 操作系统的人都可以从 Linux 中获益。
开源软件是不同于商业软件的一种模式,从字面上理解,就是开放源代码,大家不用担心里面会搞什么猫腻,这会带来软件的革新和安全。
另外,开源其实并不等同于免费,而是一种新的软件盈利模式。目前很多软件都是开源软件,对计算机行业与互联网影响深远。
近年来,Linux 已经青出于蓝而胜于蓝,以超常的速度发展,从一个丑小鸭变成了一个拥有庞大用户群的真正优秀的、值得信赖的操作系统。历史的车轮让 Linux 成为 UNIX 最优秀的传承者。
总结一下 Linux 和 UNIX 的关系/区别
Linux 是一个类似 Unix 的操作系统,Unix 要早于 Linux,Linux 的初衷就是要替代 UNIX,并在功能和用户体验上进行优化,所以 Linux 模仿了 UNIX(但并没有抄袭 UNIX 的源码),使得 Linux 在外观和交互上与 UNIX 非常类似。
说模仿可能会被人喷,你也可以说微创新或者改进。
相比于 UNIX,Linux 最大的创新是开源免费,这是它能够蓬勃发展的最重要原因;而目前的 UNIX 大部分都是收费的,小公司和个人都难以承受。
正是由于 Linux 和 UNIX 有着千丝万缕的联系,所以人们把 Linux 叫做“类UNIX系统”,下节我们将会着重讲解。
UNIX/Linux系统结构
UNIX/Linux 系统可以粗糙地抽象为 3 个层次(所谓粗糙,就是不够细致、精准,但是便于初学者抓住重点理解),如图所示。底层是 UNIX/Linux 操作系统,即系统内核(Kernel);中间层是 Shell 层,即命令解释层;高层则是应用层。
UNIX/Linux 系统结掏层次概要
1) 内核层
内核层是 UNIX/Linux 系统的核心和基础,它直接附着在硬件平台之上,控制和管理系统内各种资源(硬件资源和软件资源),有效地组织进程的运行,从而扩展硬件的功能,提高资源的利用效率,为用户提供方便、高效、安全、可靠的应用环境。
2) Shell层
Shell 层是与用户直接交互的界面。用户可以在提示符下输入命令行,由 Shell 解释执行并输出相应结果或者有关信息,所以我们也把 Shell 称作命令解释器,利用系统提供的丰富命令可以快捷而简便地完成许多工作。
3) 应用层
应用层提供基于 X Window 协议的图形环境。X Window 协议定义了一个系统所必须具备的功能(就如同 TCP/IP 是一个协议,定义软件所应具备的功能),可系统能满足此协议及符合 X 协会其他的规范,便可称为 X Window。
现在大多数的 UNIX 系统上(包括 Solaris、HP-UX、AIX 等)都可以运行 CDE (Common Desktop Environment,通用桌面环境,是运行于 UNIX 的商业桌面环境)的用户界面;而在 Linux 上广泛应用的有 Gnome、KDE 等。
Gnome图形界面
X Window 与微软的 Windows 图形环境有很大的区别:
- UNIX/Linux 系统与 X Window 没有必然捆绑的关系,也就是说,UNIX/Linux 可以安装 X Window,也可以不安装;而微软的 Windows 图形环境与内核捆绑密切。
- UNIX/Linux 系统不依赖图形环境,依然可以通过命令行完成 100% 的功能,而且因为不使用图形环境还会节省大量的系统资源。
Linux 的发行版
Linux 的发行版说简单点就是将 Linux 内核与应用软件做一个打包。
目前市面上较知名的发行版有:Ubuntu、RedHat、CentOS、Debian、Fedora、SuSE、OpenSUSE、Arch Linux、SolusOS 等。
Linux 应用领域:
今天各种场合都有使用各种 Linux 发行版,从嵌入式设备到超级计算机,并且在服务器领域确定了地位
Linux 文件系统
尽管大多数文件系统代码在内核中(后面讨论的用户空间文件系统除外),但是图 1 所示的体系结构显示了用户空间和内核中与文件系统相关的主要组件之间的关系。
图 1. Linux 文件系统组件的体系结构
用户空间包含一些应用程序(例如,文件系统的使用者)和 GNU C 库(glibc),它们为文件系统调用(打开、读取、写和关闭)提供用户接口。系统调用接口的作用就像是交换器,它将系统调用从用户空间发送到内核空间中的适当端点。
VFS 是底层文件系统的主要接口。这个组件导出一组接口,然后将它们抽象到各个文件系统,各个文件系统的行为可能差异很大。有两个针对文件系统对象的缓存(inode 和 dentry)。它们缓存最近使用过的文件系统对象。
每个文件系统实现(比如 ext2、JFS 等等)导出一组通用接口,供 VFS 使用。缓冲区缓存会缓存文件系统和相关块设备之间的请求。例如,对底层设备驱动程序的读写请求会通过缓冲区缓存来传递。这就允许在其中缓存请求,减少访问物理设备的次数,加快访问速度。以最近使用(LRU)列表的形式管理缓冲区缓存。注意,可以使用 sync
命令将缓冲区缓存中的请求发送到存储媒体(迫使所有未写的数据发送到设备驱动程序,进而发送到存储设备)。
这就是 VFS 和文件系统组件的高层情况。现在,讨论实现这个子系统的主要结构。
主要结构
Linux 以一组通用对象的角度看待所有文件系统。这些对象是超级块(superblock)、inode、dentry 和文件。超级块在每个文件系统的根上,超级块描述和维护文件系统的状态。文件系统中管理的每个对象(文件或目录)在 Linux 中表示为一个 inode。inode 包含管理文件系统中的对象所需的所有元数据(包括可以在对象上执行的操作)。另一组结构称为 dentry,它们用来实现名称和 inode 之间的映射,有一个目录缓存用来保存最近使用的 dentry。dentry 还维护目录和文件之间的关系,从而支持在文件系统中移动。最后,VFS 文件表示一个打开的文件(保存打开的文件的状态,比如写偏移量等等)。
虚拟文件系统层
VFS 作为文件系统接口的根层。VFS 记录当前支持的文件系统以及当前挂装的文件系统。
可以使用一组注册函数在 Linux 中动态地添加或删除文件系统。内核保存当前支持的文件系统的列表,可以通过 /proc 文件系统在用户空间中查看这个列表。这个虚拟文件还显示当前与这些文件系统相关联的设备。在 Linux 中添加新文件系统的方法是调用 register_filesystem
。这个函数的参数定义一个文件系统结构(file_system_type
)的引用,这个结构定义文件系统的名称、一组属性和两个超级块函数。也可以注销文件系统。
在注册新的文件系统时,会把这个文件系统和它的相关信息添加到 file_systems 列表中(见图 2 和 linux/include/linux/mount.h)。这个列表定义可以支持的文件系统。在命令行上输入 cat /proc/filesystems
,就可以查看这个列表。
图 2. 向内核注册的文件系统
VFS 中维护的另一个结构是挂装的文件系统(见图 3)。这个结构提供当前挂装的文件系统(见 linux/include/linux/fs.h)。它链接下面讨论的超级块结构。
图 3. 挂装的文件系统列表
超级块
超级块结构表示一个文件系统。它包含管理文件系统所需的信息,包括文件系统名称(比如 ext2)、文件系统的大小和状态、块设备的引用和元数据信息(比如空闲列表等等)。超级块通常存储在存储媒体上,但是如果超级块不存在,也可以实时创建它。可以在 ./linux/include/linux/fs.h 中找到超级块结构(见图 4)。
图 4. 超级块结构和 inode 操作
超级块中的一个重要元素是超级块操作的定义。这个结构定义一组用来管理这个文件系统中的 inode 的函数。例如,可以用 alloc_inode
分配 inode,用 destroy_inode
删除 inode。可以用 read_inode
和 write_inode
读写 inode,用 sync_fs
执行文件系统同步。可以在 ./linux/include/linux/fs.h 中找到 super_operations
结构。每个文件系统提供自己的 inode 方法,这些方法实现操作并向 VFS 层提供通用的抽象。
inode 和 dentry
inode 表示文件系统中的一个对象,它具有惟一标识符。各个文件系统提供将文件名映射为惟一 inode 标识符和 inode 引用的方法。图 5 显示 inode 结构的一部分以及两个相关结构。请特别注意 inode_operations
和 file_operations
。这些结构表示可以在这个 inode 上执行的操作。inode_operations
定义直接在 inode 上执行的操作,而 file_operations
定义与文件和目录相关的方法(标准系统调用)。
图 5. inode 结构和相关联的操作
inode 和目录缓存分别保存最近使用的 inode 和 dentry。注意,对于 inode 缓存中的每个 inode,在目录缓存中都有一个对应的 dentry。可以在 ./linux/include/linux/fs.h 中找到 inode
和 dentry
结构。
缓冲区缓存
除了各个文件系统实现(可以在 ./linux/fs 中找到)之外,文件系统层的底部是缓冲区缓存。这个组件跟踪来自文件系统实现和物理设备(通过设备驱动程序)的读写请求。为了提高效率,Linux 对请求进行缓存,避免将所有请求发送到物理设备。缓存中缓存最近使用的缓冲区(页面),这些缓冲区可以快速提供给各个文件系统。
有趣的文件系统
本文没有讨论 Linux 中可用的具体文件系统,但是值得在这里稍微提一下。Linux 支持许多种文件系统,包括 MINIX、MS-DOS 和 ext2 等老式文件系统。Linux 还支持 ext3、JFS 和 ReiserFS 等新的日志型文件系统。另外,Linux 支持加密文件系统(比如 CFS)和虚拟文件系统(比如 /proc)。
最后一种值得注意的文件系统是 Filesystem in Userspace(FUSE)。这种文件系统可以将文件系统请求通过 VFS 发送回用户空间。所以,如果您有兴趣创建自己的文件系统,那么通过使用 FUSE 进行开发是一种不错的方法。
结束语
尽管文件系统的实现并不复杂,但它是可伸缩和可扩展的体系结构的好例子。文件系统体系结构已经发展了许多年,并成功地支持了许多不同类型的文件系统和许多目标存储设备类型。由于使用了基于插件的体系结构和多层的函数间接性。
Windows
windows操作系统发展史:
上面这个系统结构图在很多书上都有,它就是windows2000的结构图,下面我们就来详细说说各个部分的功能:
从上图我们可以看出,在用户态,windows2000有三个子系统,分别为win32,posix,os/2.其中最重要的就是win32,它负责输入输出管理,没有它,系统将无法工作,其它两个子系统需要配置才能启动。我们主要精力放在win32上,因为这是我们用的最广的。我们要特别注意以下三个关键点:子系统进程,子系统动态链接库,用户进程。
(1) 子系统进程:win32子系统在windows2000中是以一个进程的形式出现的(csrss.exe)。它负责所有win32用户进程,线程的创建与撤消,建立与撤消临时文件,以及控制台的管理。
(2)子系统动态链接库:win32子系统用的动态链接库,里面有子系统所需要的大部分功能。
(3)用户创建的运行于wn32子系统之上的应用程序。
用户进程并不直接地调用系统服务,它们直接调用子系统动态链接库,当一个程序调用子系统动态链接库的一个功能时,可能会发生以下三中情形之一:
(1)所要求的功能全部是由子系统动态链接库提供,也就是说程序完全运行于用户态。
(2)需要调用一个或者多个运行于核心态的服务。
(3)需要子系统进程的协助才能完成,这时,用户进程向子系统进程发送一C/S请求,具体工作由子系统进程来完成。
特别说明,当用户进程调用系统服务时实际上是通过设置一个陷阱陷入到核心态来运行,将运行权交给系统服务调度程序来调度,并不用通过创建新的进程,线程来实现。
ntdll.dll
子系统下面是 ntdll.dll,它提供了一些子系统动态链接库所需要的功能。其实,NTDLL.DLL的最主要功能就是为它的下层---执行体提供一个文档化接口,使得它以上的各个模块可以调用执行体提供的服务。
执行体:
这是令人激动的一层,因为从这层开始我们就进入了windows的核心态,虽然我们对核心态的具体含义不是太清楚,没有关系,随着我们研究的深入你就会慢慢发现这是最重要的一层,因为所有windows的主要功能都是在这里完成的,下面我们就一点一点剖开:
这一层包含以下几种重要函数(服务):
(1)可以从用户态直接调用的函数,这些在NTDLL中文档化(前面已说过),这些中大多数都可以调用某个WIN32 API来启动所对应的服务。
(2)只能从核心态调用的函数,其中有一些在DDK中已文档化,编写windows上驱动程序的人员必须熟悉的
(3)没有文档化的函数,供执行体内部使用
执行体从总体上可以分为以下几个模块:
(1)配置管理器:负责管理注册表,我们以后会详解
(2)进程、线程管理器:负责创建和终止进程、线程。
(3)安全引用监视器:在本地计算机上执行安全策略,保护计算机的资源
(4)I/O管理器:实现I/O的设备无关性,并负责把I/O请求分配给相应的设备驱动程序以进一步处理
(5)即插即用管理器(PNP):确定设备应该由哪个驱动程序来支持并负责加载相应驱动。在启动时的枚举过程中,它收集每个设备所需要的硬件资源,并根据设备的需要来分配合适的硬件资源如I/O端口,IRQ,DMA通道之类,当系统中的设备发生变化时它负责向系统和应用程序发送通知消息。
(6)电源管理:协调电源时间,通过合理的配置,使得CPU降低电源消耗
(7)缓冲管理器:将最近使用过的数据留在CACHE中来提高系统的整体性能
(8)虚拟内存管理:这是最为让人激动的地方,对于这个部分的理解会影响我们对整个系统结构的理解,我们会在以后详细解说
(9)WDM管理方法例程:可以让设备驱动程序发布性能和配置信息以及从用户态的WMI服务接受命令
在WINDOWS平台上有过编程经历的人一定对句柄(handle)不陌生,句柄到底是什么样的东东呢??这往往给一些初学者带来一些迷惑。其实要真正理解句柄就要从windows的设计理念上来解决这个问题,那就是wndows是面向对象的,它把系统的一些资源,进程,文件等都看成对象,用对象管理器对这些对象统一管理。对于用户来说是通过句柄来操作响应对象的,可以看成是对象的一个引用。
内核:
内核是执行体的下一个层次,它为执行体提供一些最基本的功能,简单的对象,而执行体就通过在这些简单对象上加上一些安全属性,控制属性等来完成更为复杂的功能。它重要提供以下四种函数:
(1)线程调度
(2)陷阱处理和异步调度
(3)中断处理和调度
(4)多处理器同步
内核提供了一个低层次的系统原语和机制供执行体来调用以实现其功能。内核只是提供了底层的机制,而不做任何策略性的事务。但线程的调度和异常处理是在内核中实现的,内核永远都运行在核心态。
一类对象叫做控制对象,包括APC,DPC对象以及I/O要用到的对象,如中断对象。
一类对象叫做调度对象,用于线程调度。这些对象包括线程,互斥体,事件,内核事件对,信号量,定时器,可等待定时器。
硬件支持:
内核的另一主要功能是使得执行体和设备驱动独立于硬件,这个工作包含处理多个方面的差异:中断处理,异常处理,多处理器同步方式的差异
硬件抽象层(HAL):
这是windows2000实现其可移植性最重要的组成部分,HAL是一个可加载的核心态模块(HAL.DLL),它提供了windows2000所运行的硬件平台的底层接口,HAL隐藏了各种与硬件有关的细节,比如I/O接口、中断控制器、多处理通信机制等----这些都是平台相关的。当需要平台相关的信息时,windows2000的内部模块或者用户程序通过HAL来实现。
设备驱动程序:
设备驱动程序是核心态可加载模块(以.SYS为扩展名),它们是I/O管理器和相关硬件设备的接口。它们运行于以下三种环境之一:
(1) 在一个初始化了I/O函数的用户线程环境中
(2) 在内核模式的系统线程中
(3) 中断发生后(不在任何进程和线程中运行,中断发生时哪一个进程或者线程正在运行)
如前所述,windows2000的设备驱动程序并不直接操作硬件,而是调用HAL中的函数作为与硬件的接口。驱动程序通常用C语言写(有时用C++)。因此,设备驱动程序通过使用HAL可以实现平台无关性。
有以下几中设备驱动程序:
(1)硬件驱动程序:实现对物理硬件的读写(通过使用HAL)。
(2)文件系统驱动程序:是面向文件I/O的驱动程序,它把这些请求转化成绑定到特定设备的I/O请求
(3)文件过滤器驱动程序
(4)网络重定向驱动程序
(5)协议驱动程序
(6)内核流过滤器驱动程序
因为安装驱动程序是把用户编写的用户态代码添加到系统的唯一办法,因此,一些程序员通过编写设备驱动程序可以访问OS的内部函数或者内部数据结构。
Android
- Android System Structure. Underscore the concept of service
- Android's procedures of starting up.
iOS
iOS基于UNIX系统,iOS的系统架构分为四层,由上到下一次为:可触摸层(Cocoa Touch layer)、媒体层(Media layer)、核心服务层(Core Services layer)、核心操作系统层(Core OS layer),如下图:
(1)触摸层:为应用程序开发提供了各种常用的框架并且大部分框架与界面有关,本质上来说它负责用户在iOS设备上的触摸交互操作。如NotificationCenter的本地通知和远程推送服务,iAd广告框架,GameKit游戏工具框架,消息UI框架,图片UI框架,地图框架,连接手表框架,自动适配等等
(2)媒体层:提供应用中视听方面的技术,如图形图像相关的CoreGraphics,CoreImage,GLKit,OpenGL ES,CoreText,ImageIO等等。声音技术相关的CoreAudio,OpenAL,AVFoundation,视频相关的CoreMedia,Media Player框架,音视频传输的AirPlay框架等等。
(3)核心服务层:提供给应用所需要的基础的系统服务。如Accounts账户框架,广告框架,数据存储框架,网络连接框架,地理位置框架,运动框架等等。这些服务中的最核心的是CoreFoundation和Foundation框架,定义了所有应用使用的数据类型。CoreFoundation是基于C的一组接口,Foundation是对CoreFoundation的OC封装。
(4)核心操作系统层包括:包含大多数低级别接近硬件的功能,它所包含的框架常常被其它框架所使用。Accelerate框架包含数字信号,线性代数,图像处理的接口。针对所有的iOS设备硬件之间的差异做优化,保证写一次代码在所有iOS设备上高效运行。CoreBluetooth框架利用蓝牙和外设交互,包括扫描连接蓝牙设备,保存连接状态,断开连接,获取外设的数据或者给外设传输数据等等。Security框架提供管理证书,公钥和私钥信任策略,keychain,hash认证数字签名等等与安全相关的解决方案。
框架是一个目录,这个目录包含了共享库,访问共享库里代码的头文件,和其它的图片和声音的资源文件。一个共享库定义的方法或函数可以被应用程序调用。
IOS提供了很多你可以在应用程序里调用的框架。要使用一个框架,需要将它添加到你的项目中,你的项目才可以使用它。许多应用程序都使用了如Foundation、UIKit、和Core Graphics这些框架。根据你为应用程序选择的模版,相关的框架就已经被自动引入了。如果默认加入的框架不能满足你的应用程序的需求,你也可以加入需要的框架。
看看HelloWorld.xcodeproj项目里都包含了哪些框架(注:HelloWorld.xcodeproj是《Your First iOS App tutorial 》这篇教程里的一个项目)
1.在XCode里打开HelloWorld.xcodeproj项目(如果还没有打开)
2. 在project navigator窗口里点击,点击Frameworks目录前面的三角形图标。你会看到:
UIKit.framework,Foundation.framework, 和CoreGraphics.framework
3. 点击任意一个framework前面的三角,然后再点击Headers前面的三角,可以看到框架里的头文件。
每个框架对应IOS系统里的一层,每层建立在它下面层的上面。应该尽量使用上层的框架来代替下面的框架。更高层次的框架是对底层框架基于对象的抽象。
在你开发程序时,主要使用框架就是Foundation和UIKit,因为它们包含了你需要的大部分东西。
Foundation框架为所有的应用程序提供基本系统服务
你的应用程序,UIKit和其它的框架都是建立在Foundation框架上面的。Foundation框架是用Object-C对Core Foundation框架里许多特性的封装。
使用Foundation可以:
- 创建和管理集合,比如数组和字典
- 访问存储在应用程序里的图片和其它资源
- 创建和管理字符串
- 提交和接收通知
- 创建日期和时间对象
- 自动发现IP网络上的设备
- 操作URL流
- 执行异步代码
你已经在《Your First iOS App》里使用到了Foundation框架。比如,你使用一个NSString类的实例存储用户输入的userName。你还使用了Foundation框架的initWithFormat方法创建了一个字符串。
UIKit框架提供创建基于触摸用户界面的类
所有的iOS应用程序都基于UIKit,你不能是应用程序脱离这个框架。UIKit提供了在屏幕上绘制的机制,捕获事件,和创建通用用户界面元素。UIKit也通过管理显示在屏幕上的组件来组织复杂的项目。
使用UIKit可以:
- 构建和管理你的用户界面
- 捕获触摸和基于移动的事件
- 呈现文字和web内容
- 优化你的多任务程序
- 创建定制的用户界面元素
在《YouFirst iOS App Tutorial》里,你也使用到了UIKit。当你仔细查看程序是怎么运行起来的时候,你会看到UIApplicationMain函数创建一个UIApplication类的实例,这个实例会捕获进来的用户事件。你实现UITextFieldDelegate协议,然后在用户按下Done时隐藏键盘。实际上,你是在使用UIKit创建用户界面上的UITextField, UILabel,和UIButton类。
你需要知道的其它重要的框架
Core Data , Core Graphics, Core Animation,和OpenGLES框架都是高级的技术。所以这些框架对于你开发应用程序也是很重要的,它们都需要时间去学习和掌握。
Core Data框架管着理应用程序数据模型
Core Data提供对象的管理,使用Core Data,你可以创建模型对象,并管理这些对象。你管理这这些对象间的联系并修改数据。Core Data提供的内建SQLlite技术可以高效的管理数据。
使用Core Data可以:
- 在库里存储和接收对象
- 提供基本的undo/redo
- 自动验证属性值
- 过滤、分组和优化内存中的数据
- 用[NSFetchedResultsController]管理表视图中的结果
- 支持基于文档的应用程序
Core Graphics框架帮助你创建图形
高质量的图形对于所有的iOS应用程序都是很重要的。在iOS中最简单且最快捷的创建图形的方式是使用UIKit框架提供的基于预渲染图形的视图和控件,然后让UIKit和iOS完成绘制。但是当你需要创建复杂的图形时,Core Graphics则提供了更底层的库来帮助你。
使用Core Graphics可以:
- 创建基于路径的绘图
- 抗锯齿渲染
- 添加梯度、图片和颜色
- Use coordinate-space transformations.
- 创建、显示和分析PDF文档
Core Animation允许你创建高级的动画和虚拟效果
UIKit提供建立在Core Animation之上的动画。如果你需要比UIKit能力更高级的功能,可以直接使用Core Animation。Core Animation接口包含在Quartz Core框架里。使用Core Animation可以创建嵌套的对象,并且可以对它们操作、旋转、缩放和转换。使用Core animation,你可以创建动态的用户界面而不用使用更底层的图形API,如OpenGL ES。
使用Core Animation可以:
- 创建定制动画
- 添加定时函数和图形
- 支持帧动画
- Specify graphical layout constraints.
- Group multiple-layer changes into anatomic update.
OpenGL ES 框架提供2D和3D绘图工具
OpenGL ES支持2D和3D绘图,Apple的OpenGL ES实现通过硬件提供了高速的全屏游戏式的应用程序。
使用OpenGL ES可以:
- 创建2D和3D图形
- 创建更复杂的图形,比如数据虚拟化、模拟飞行,或者视频游戏
- 访问底层图形设备
根据需要向项目中添加其它框架
还有许多框架可以添加到你的程序里。当你决定使用一个框架但项目里却没有引入这个框架时,你就需要将它加入到你的项目里。
计算机科学与技术
数学基础
高等数学
线性代数
概率论与数理统计
离散数学
数值分析
数据库系统
计算机网络
网络安全
数据结构与算法
编译原理
操作系统
是什么?
- operating system,OS。管理计算机硬件与软件资源的程序。操作系统处理如管理与配置内存、决定系统资源供需的优先次序、控制输入设备与输出设备、操作网络与管理文件系统等基本事务。操作系统也提供一个让用户与系统交互的操作界面。
组成部分
- 内核、驱动程序、接口库、外围
常见系统
- Windows,macOS,Linux,iOS,Android
特 征:并发、共享、虚拟、异步
- 并发:同一段时间内多个程序执行(注意区别并行和并发,前者是同一时刻的多个事件,后者是同一时间段内的多个事件)
- 共享:系统中的资源可以被内存中多个并发执行的进线程共同使用
- 虚拟:通过时分复用(如分时系统)以及空分复用(如虚拟内存)技术实现把一个物理实体虚拟为多个
- 异步:系统中的进程是以走走停停的方式执行的,且以一种不可预知的速度推进
功 能:处理器管理、存储器管理、设备管理、文件管理
- ①进程管理,其工作主要是进程调度,在单用户单任务的情况下,处理器仅为一个用户的一个任务所独占, 进程管理的工作十分简单。但在多道程序或多用户的情况 下,组织多个作业或任务时,就要解决处理器的调度、 分配和回收等问题 。
- ②存储管理分为几种功能:存储分配、存储共享、存储保护 、存储扩张。
- ③设备管理分有以下功能:设备分配、设备传输控制 、设备独立性。
- ④文件管理:文件存储空间的管理、目录管理 、文件操作管理、文件保护。
- ⑤作业管理是负责处理用户提交的任何要求。
基本类型:批处理系统、分时操作系统、实时操作系
统体系结构:模块组合结构、层次结构、微内核结构
简史
- 批量模式
- 分时机制
- 多处理器
- 分布式
设计哲学
- 模块化
- 结构化
- 通讯接口
- 层次式结构
操作系统虚拟化
- 容器的核心技术
操作系统实例
-
嵌入式系统
- VxWorks、eCos、Symbian OS及Palm OS
-
iOS
- 以Darwin为基础,属于类Unix 的商业操作系统。
-
Android
- 基于Linux
-
类Unix系统
- System V、BSD与Linux
- 惠普的HP-UX以及IBM的AIX仅设计用于自家的硬件产品上
- SUN的Solaris可安装于自家的硬件或x86计算机上
- 苹果计算机的Mac OS X是一个从NeXTSTEP、Mach以及FreeBSD共同派生出来的微内核BSD系统
-
微软Windows
- Microsoft Windows系列操作系统是在微软给IBM机器设计的MS-DOS的基础上设计的图形操作系统。现在的Windows系统,如Windows 2000、Windows XP皆是创建于现代的Windows NT内核。NT内核是由OS/2和OpenVMS等系统上借用来的。
-
MacOS X
- Mac OS是首个在商用领域成功的图形用户界面系统。Macintosh开发成员包括比尔·阿特金森(Bill Atkinson)、杰夫·拉斯金(Jef Raskin)和安迪·赫茨菲尔德(Andy Hertzfeld)。
-
Chrome OS
- Google的轻型的、基于网络的计算机操作系统计划,其基于Google的浏览器Google Chrome的Linux内核。
进程与线程
-
进程
- 1)PCB(Process Control Block):用来记录进程信息的数据结构(管理进程的核心,包含了PID等进程的所有关键信息)
- 2)进程的状态:1:就绪状态,2:执行状态,3:阻塞状态(多线程时也是这些状态)
- 3)队列:就绪队列、等待(阻塞)队列。
-
通信
- 共享存储
- 消息传递
- 管道通信:固定大小,半双工通信,即某一时刻只能单向传输。
- 共享文件
-
线程
-
TCB(thread control block线程控制块)
-
包括PC程序计数器,SP栈,State状态,和寄存器,线程id。
线程有内核级线程和用户级线程,我们一般说的都是用户级线程,内核级线程由内核管理。
-
-
发挥多核性能
- 1)只有内核级线程才能发挥多核性能,因为内核级线程共用一套MMU(即内存映射表),统一分配核1核2(即有多个CPU,可以一个CPU执行一个内核级线程)。进程无法发挥多核性能,因为进程切换都得切MMU。
- 2)为什么需要内核级线程?如果只有用户级线程,在内核中只能看到进程,所以当用户级线程中一个线程进行IO读写阻塞时,内核会将该线程所在的进程直接切换。
-
用户级线程
-
内核级线程
-
-
进程和线程的对比
- 进程是系统进行资源调度和分配的基本单位;线程是CPU调度的基本单位。
- 进程 = 资源 (包括寄存器值,PCB,内存映射表)+ TCB(栈结构)
- 线程 = TCB(栈结构)
- 线程 的资源是共享的
- 进程 间的资源是分隔独立的,内存映射表不同,占用物理内存地址是分隔的
- 线程 的切换只是切换PC,切换了TCB(栈结构)
- 进程 的切换不仅要切换PC,还包括切换资源,即切换内存映射表
-
进程间通信
-
同步
- 经典的进程同步问题:生产者-消费者问题;哲学家进餐问题;读者-写者问题
- 同步的解决方案:管程,信号量。
-
死锁
- 在两个或多个并发进程中,如果每个进程持有某种资源而又都等待别的进程释放它或它们现在保持着的资源,在未改变这种状态之前都不能向前推进,称这一组进程产生了死锁。通俗地讲,就是两个或多个进程被无限期地阻塞、相互等待的一种状态。
-
产生条件:
- 1:互斥条件:一个资源一次只能被一个进程使用
- 2:请求保持条件 : 一个进程因请求资源而阻塞时,对已经获得资源保持不放
- 3:不可抢占条件 : 进程已获得的资源在未使用完之前不能强行剥夺
- 4:循环等待条件 :若干进程之间形成一种头尾相接的循环等待资源的关系
-
死锁处理:
- 预防死锁:破坏产生死锁的4个必要条件中的一个或者多个;实现起来比较简单,但是如果限制过于严格会降低系统资源利用率以及吞吐量
- 避免死锁:在资源的动态分配中,防止系统进入不安全状态(可能产生死锁的状态)-如银行家算法
- 检测死锁:允许系统运行过程中产生死锁,在死锁发生之后,采用一定的算法进行检测,并确定与死锁相关的资源和进程,采取相关方法清除检测到的死锁。实现难度大
- 解除死锁:与死锁检测配合,将系统从死锁中解脱出来(撤销进程或者剥夺资源)。对检测到的和死锁相关的进程以及资源,通过撤销或者挂起的方式,释放一些资源并将其分配给处于阻塞状态的进程,使其转变为就绪态。实现难度大
- 死锁忽略: windows,Linux个人版都不做死锁处理,直接忽略,大不了重启就好了,小概率事件,代价可以接受
-
-
CPU调度算法:在就绪队列中,怎么挑选进程让CPU执行?
- 先来先服务调度算法FCFS:按作业或者进程到达的先后顺序依次调度;(平均周转时间可能会很长 )
- 短作业优先调度算法SJF:算法从就绪队列中选择估计时间最短的作业进行处理,直到得出结果或者无法继续执行(周转时间短,但是响应时间长 )
- 高相应比算法HRN:响应比=(等待时间+要求服务时间)/要求服务时间;
- 时间片轮转调度RR:按到达的先后对进程放入队列中,然后给队首进程分配CPU时间片,时间片用完之后计时器发出中断,暂停当前进程并将其放到队列尾部,循环 ;(响应时间可以得到保证)
- 多级反馈队列调度算法:目前公认较好的调度算法;设置多个就绪队列并为每个队列设置不同的优先级,第一个队列优先级最高,其余依次递减。优先级越高的队列分配的时间片越短,进程到达之后按FCFS放入第一个队列,如果调度执行后没有完成,那么放到第二个队列尾部等待调度,如果第二次调度仍然没有完成,放入第三队列尾部…。只有当前一个队列为空的时候才会去调度下一个队列的进程。
内存管理
-
分段
- 一个程序分成多个段(每个段特性不同为了方便管理,例如代码段只读、数据段等等),当然这都是逻辑上的。
- 管理段的结构叫段表,段表保存中进程的PCB中。
-
页表
- 把程序按段分对程序员是友好的,但是如果物理存储也按段存,则会导致大块的内存碎片,例如现在需要分个10M的段但是连续的存储空间只有8M/9M/5M三个。
- 解决办法: 将段细化到页 Page,存到页中。不要对内存进行连续的分配,将内存划分成1页1页,按页分配,1页4kb大小,最多浪费的也就4KB。这样不会有内存碎片,也不会出现没有符合要求大小的内存可以申请的情况,因为可以打散了分散到一页一页中。
- 进程需要有自己的“页表”,里面映射双方是程序的逻辑地址中的页号和系统分给这給程序的页框号。
-
段页结合的内存管理
- 页号加偏移称为虚拟地址,MMU负载从虚拟地址到物理地址的转换,同时也负责权限检查。
-
请求调页内存换入
- CPU对数据进行请求时,才会进行映射(虚拟内存到物理内存)。例如进程1正在运行,进行映射拿数据,查页表发现页框号中没有数据或有进程2的数据,则需要页表调入内存。
-
内存换出
- 有页表需要调入,那么谁被调出?
-
页面置换算法
- 1:最佳置换算法(Optimal):一种理论的算法,选着淘汰的页面是以后一定不再使用的页面(理想化的),该算法无法实现,只能作为其他算法好坏的一个评价对比。
- 2:先进先出(FIFO)算法:总是最先淘汰最先进去的页面,该算法容易实现。缺点:通常程序调入内存的先后顺序和程序执行的先后顺序不一致,导致缺页率高。
- 3:最近最久未使用算法LRU:算法赋予每个页面一个访问字段,用来记录上次页面被访问到现在所经历的时间t,每次置换的时候把t值最大的页面置换出去(实现方面可以采用寄存器或者栈的方式实现)。
-
4:时钟算法clock(也被称为是最近未使用算法NRU):页面设置一个访问位R,并将页面链接为一个环形队列,页面被访问的时候访问位设置R为1。页面置换的时候,如果当前指针所指页面访问R为0,那么置换,否则将其置为0,循环直到遇到一个访问为位0的页面。
- 但是这个方法有缺点:缺页比较少的时候(最近没有使用淘汰中的“最近”太长了),所有的R都为1(很少变成0),每次都要转一圈才能找到换出去的页,退化成FIFO,效率不高。
- 改进: 双指针,一个快,一个慢,像时钟一样 (定时清除R位)(更像clock)
- 快时钟做R的清0定时清0,等到慢指针转到这里的时候R=0,说明在定时时间片内没有备访问,该页可以被替换了。
软件工程
电路原理
模拟电子技术
数字逻辑系统
微机原理
系统仿真和虚拟现实
大数据技术
数据采集与处理
Web前/后端开发
机器学习&人工智能
自然语言处理