其他系统调用
除了进程、文件、目录系统调用,也存在其他系统调用的情况,下面我们来探讨一下。我们可以看到上面其他系统调用只有四种,首先来看第一个 chdir,chdir 调用更改当前工作目录,在调用
chdir("/usr/ast/test");
后,打开 xyz 文件,会打开 /usr/ast/test/xyz
文件,工作目录的概念消除了总是需要输入长文件名的需要。
在 UNIX 系统中,每个文件都会有保护模式,这个模式会有一个读-写-执行
位,它用来区分所有者、组和其他成员。chmod
系统调用提供改变文件模式的操作。例如,要使一个文件除了对所有者之外的用户可读,你可以执行
chmod("file",0644);
kill
系统调用是用户和用户进程发送信号的方式,如果一个进程准备好捕捉一个特定的信号,那么在信号捕捉之前,会运行一个信号处理程序。如果进程没有准备好捕捉特定的信号,那么信号的到来会杀掉该进程(此名字的由来)。
POSIX 定义了若干时间处理的进程。例如,time
以秒为单位返回当前时间,0 对应着 1970 年 1月 1日。在一台 32 位字的计算机中,time 的最大值是 (2^32) - 1秒,这个数字对应 136 年多一点。所以在 2106 年,32 位的 UNIX 系统会发飙。如果读者现在有 32 位 UNIX 系统,建议在 2106 年更换位 64 位操作系统(偷笑~)。
Win 32 API
上面我们提到的都是 UNIX 系统调用,现在我们来聊聊 Win 32 中的系统调用。Windows 和 UNIX 在各自的编程方式上有着根本的不同。UNIX 程序由执行某些操作或执行其他操作的代码组成,进行系统调用以执行某些服务。Windows 系统则不同,Windows 应用程序通常是由事件驱动的。主程序会等待一些事件发生,然后调用程序去处理。最简单的事件处理是键盘敲击和鼠标滑过,或者是鼠标点击,或者是插入 USB 驱动,然后操作系统调用处理器去处理事件,更新屏幕和更新程序内部状态。这是与 UNIX 不同的设计风格。
当然,Windows 也有系统调用。在 UNIX 中,系统调用(比如 read)和系统调用所使用的调用库(例如 read)几乎是一对一的关系。而在 Windows 中,情况则大不相同。首先,函数库的调用和实际的系统调用几乎是不对应的。微软定义了一系列过程,称为 Win32应用编程接口(Application Programming Interface)
,程序员通过这套标准的接口来实现系统调用。这个接口支持从 Windows 95 版本以来所有的 Windows 版本。
Win32 API 调用的数量是非常巨大的,有数千个多。但这些调用并不都是在内核态的模式下运行时,有一些是在用户态的模型下运行。Win32 API 有大量的调用,用来管理视窗、几何图形、文本、字体、滚动条、对话框、菜单以及 GUI 的其他功能。为了使图形子系统在内核态下运行,需要系统调用,否则就只有函数库调用。
我们把关注点放在和 Win32 系统调用中来,我们可以简单看一下 Win32 API 中的系统调用和 UNIX 中有什么不同(并不是所有的系统调用)
上表中是 UNIX 调用大致对应的 Win32 API 系统调用,简述一下上表。CreateProcess
用于创建一个新进程,它把 UNIX 中的 fork 和 execve 两个指令合成一个,一起执行。它有许多参数用来指定新创建进程的性质。Windows 中没有类似 UNIX 中的进程层次,所以不存在父进程和子进程的概念。在进程创建之后,创建者和被创建者是平等的。WaitForSingleObject
用于等待一个事件,等待的事件可以是多种可能的事件。如果有参数指定了某个进程,那么调用者将等待指定的进程退出,这通过 ExitProcess
来完成。
然后是6个文件操作,在功能上和 UNIX 的调用类似,然而在参数和细节上是不同的。和 UNIX 中一样,文件可以打开,读取,写入,关闭。SetFilePointer
和 GetFileAttributesEx
设置文件的位置并取得文件的属性。
Windows 中有目录,目录分别用 CreateDirectory
以及 RemoveDirectory
API 调用创建和删除。也有对当前的目录的标记,这可以通过 SetCurrentDirectory
来设置。使用GetLocalTime
可获得当前时间。
Win32 接口中没有文件的链接、文件系统的 mount、umount 和 stat ,当然, Win32 中也有大量 UNIX 中没有的系统调用,特别是对 GUI 的管理和调用。
操作系统结构
下面我们会探讨操作系统的几种结构,主要包括单体结构、分层系统、微内核、客户-服务端系统、虚拟机和外核等。下面以此来探讨一下
单体系统
到目前为止,在大多数系统中,整个系统在内核态以单一程序的方式运行。整个操作系统是以程序集合来编写的,链接在一块形成一个大的二进制可执行程序。使用此技术时,如果系统中的每个过程都提供了前者所需的一些有用的计算,则它可以自由调用任何其他过程。在单体系统中,调用任何一个所需要的程序都非常高效,但是上千个不受限制的彼此调用往往非常臃肿和笨拙,而且单体系统必然存在单体问题,那就是只要系统发生故障,那么任何系统和应用程序将不可用,这往往是灾难性的。
在单体系统中构造实际目标程序时,会首先编译所有单个过程(或包含这些过程的文件),然后使用系统链接器将它们全部绑定到一个可执行文件中
对于单体系统,往往有下面几种建议
- 需要有一个主程序,用来调用请求服务程序
- 需要一套服务过程,用来执行系统调用
- 需要一套服务程序,用来辅助服务过程调用
在单体系统中,对于每个系统调用都会有一个服务程序来保障和运行。需要一组实用程序来弥补服务程序需要的功能,例如从用户程序中获取数据。可将各种过程划分为一个三层模型
除了在计算机初启动时所装载的核心操作系统外,许多操作系统还支持额外的扩展。比如 I/O 设备驱动和文件系统。这些部件可以按需装载。在 UNIX 中把它们叫做 共享库(shared library)
,在 Windows 中则被称为 动态链接库(Dynamic Link Library,DLL)
。他们的扩展名为 .dll
,在 C:\Windows\system32
目录下存在 1000 多个 DLL 文件,所以不要轻易删除 C 盘文件,否则可能就炸了哦。
分层系统
分层系统使用层来分隔不同的功能单元。每一层只与该层的上层和下层通信。每一层都使用下面的层来执行其功能。层之间的通信通过预定义的固定接口通信。
分层系统是由 E.W.Dijkstar
和他的学生在荷兰技术学院所开发的 THE 系统。
把上面单体系统进一步通用化,就变为了一个层次式结构的操作系统,它的上层软件都是在下层软件的基础之上构建的。该系统分为六层,如下所示
层号 | 功能 |
5 | 操作员 |
4 | 用户程序 |
3 | 输入/输出管理 |
2 | 操作员-进程通信 |
1 | 存储器和磁鼓管理 |
0 | 处理器分配和多道程序编程 |
处理器在 0 层运行,当中断发生或定时器到期时,由该层完成进程切换;在第 0 层之上,系统由一些连续的进程组成,编写这些进程时不用再考虑在单处理器上多进程运行的细节。内存管理在第 1 层,它分配进程的主存空间。第 1 层软件保证一旦需要访问某一页面,该页面必定已经在内存中,并且在页面不需要的时候将其移出。
第 2 层处理进程与操作员控制台(即用户)之间的通信。第 3 层管理 I/O 设备和相关的信息流缓冲区。第 4 层是用户程序层,用户程序不用考虑进程、内存、控制台或 I/O 设备管理等细节。系统操作员在第 5 层。