打字猴:1.700436095e+09
1700436095 UNIX传奇:历史与回忆 [:1700434690]
1700436096 UNIX传奇:历史与回忆 4.2 系统调用
1700436097
1700436098 操作系统为运行于其上的程序提供一系列服务,包括启动和停止程序、读取或写入文件中的信息、访问设备和网络连接、报告日期和时间之类信息等。这些服务在操作系统内部实现,正在运行的程序可以通过一种叫作系统调用的机制来获取服务。
1700436099
1700436100 归根结底,系统调用就是操作系统,因为它们定义了系统提供的服务。一套系统调用可能有多个独立的实现,Unix系统和类Unix系统的不同版本就是如此。其他完全不同的操作系统,如Windows,可以提供软件,将Unix系统调用转换为自己的系统调用。而且即使是类Unix系统,也必然会有某一操作系统特有的系统调用。
1700436101
1700436102 第1版Unix只有30多个系统调用,其中大约一半与文件系统有关。由于文件只包含未经释义的字节,所以基本的文件系统接口非常简单,只有5个系统调用,用于打开或创建文件,读写其字节,以及关闭文件。通过使用以下这样的语句,从C语言程序中调用函数访问这些服务。
1700436103
1700436104 fd = creat(filename, perms)
1700436105 fd = open(filename, mode)
1700436106 nread = read(fd, buf, n)
1700436107 nwrite = write(fd, buf, n)
1700436108 status = close(fd)
1700436109
1700436110
1700436111 creat系统调用创建新文件,并设置它的访问权限。通常情况下,访问权限允许或禁止用户、用户所在组和其他所有人读、写及执行文件的能力。这9个权限位[1]用相对较少的机制给出了相当大的控制权。open系统调用打开现有文件,mode指明是读文件还是写文件,filename是层级文件系统中的任意路径。
1700436112 调用open和creat产生的fd值称为文件描述符(file descriptor),是一个非负小整数,在后续的文件读写中使用。read和write系统调用尝试从文件读出或向文件写入n个字节;系统调用返回实际传输的字节数。对于所有这些系统调用,如果返回负值(通常是-1),则表示发生了某种错误。
1700436113
1700436114 顺便说一下,creat系统调用之所以这么拼写[2],只能归咎于肯 · 汤普森的个人品位,没有其他什么好借口。罗布·派克曾经问肯,如果重写Unix,他会做哪些修改。他的答案是什么?“我会在creat后头加上字母e。”
1700436115
1700436116 Unix的另一创新是把磁盘、终端等外围设备都看作文件系统中的文件,磁盘是功能列表中提到的“可拆卸卷”。访问设备的系统调用和访问文件的系统调用是一样的,所以同样的代码既可以操作文件也可以操作设备。当然实际上并没那么简单,因为真实的设备有奇怪的属性要处理,所以还有其他系统调用来处理这些特殊性,尤其是终端的特殊性。这部分系统并不漂亮。
1700436117
1700436118 还有一些系统调用负责设定文件内的位置、确定文件状态等。50年来,这些系统调用都得到了完善,偶尔也有改进,但基本模式很简单,易于使用。
1700436119
1700436120 今天的读者可能很难体会到这一切是做了多大简化之后的结果。早期操作系统中,真实设备的所有复杂情况都会反馈给用户。用户必须知道磁盘名称,了解磁盘的物理结构,如有多少柱面和磁道,以及数据是如何安放在上面。史蒂夫·约翰逊下面这段话让我记起,那时霍尼韦尔主计算机上的分时子系统是多么的笨拙:
1700436121
1700436122 “要在霍尼韦尔TSS系统上创建文件,必须先进入一个子系统。你得回答8个问题:文件的初始尺寸、最大尺寸、名称、设备、谁能读它、谁能写它等。问题逐个提出,你逐个回答。答完所有问题后,操作系统得到这些信息。如果输入错误,文件创建就会失败。这意味着你得再次进入子系统,再次回答所有的问题。难怪文件终于创建时,系统会反馈说‘SUCCESSFUL!’”
1700436123
1700436124 Unix效仿Multics,隐藏了所有这些冗言赘语:文件只是字节。用户决定这些字节代表什么,而操作系统则只负责存储和取出,不向用户暴露设备属性。
1700436125
1700436126
1700436127
1700436128
1700436129 UNIX传奇:历史与回忆 [:1700434691]
1700436130 UNIX传奇:历史与回忆 4.3 shell[3]
1700436131
1700436132 shell是运行其他程序的程序。它让用户运行命令,是用户和操作系统之间的主要接口。登录到Unix系统时,我的键盘连接到一个正在运行的shell实例。我可以输入命令,通常一次输入一个命令。shell依次运行每个命令,完成一个命令后,它就会为下一个命令做好准备。会话可能像下文这样,其中$是shell输出的提示,让我知道它在等我做点什么。我输入的内容以斜体字表示[4]。
1700436133
1700436134 $ date(告诉我当前日期和时间)
1700436135 Fri Oct 18 13:09:00 EDT 2019
1700436136 $ ls(列出目录内容)
1700436137 book.pdf book.txt
1700436138 $ wc book.txt (计算book.txt的行数、单词数和字符数)
1700436139 9918 59395 362773 book.txt
1700436140 $ cp book.txt backup.txt(将book.txt复制到备份文件)
1700436141
1700436142
1700436143 重点说明:shell是个普通的用户程序,而非操作系统的组成部分,这也是从Multics中汲取的概念(也就是功能列表中提到的所谓“用户可选择系统命令语言”)。因为shell是用户程序,所以很容易用其他程序取代,这就是为什么有那么多Unix shell的原因。如果你不喜欢某个shell的工作方式,大可另择优者,甚至可以自己写个shell取而代之,所以shell并不特指哪个具体程序。
1700436144 也就是说,所有Unix shell都提供了相同的基本功能,通常也采用相同的语法。Unix shell最重要的功能是运行程序。它们也都提供了文件名通配符,像“*”这样的模式元字符会被扩展成符合模式的文件名列表。例如,要运行程序wc(word count,字数统计)来计算当前目录下所有名字以book开头的文件中的行数、字数和字符数,对应命令是:
[ 上一页 ]  [ :1.700436095e+09 ]  [ 下一页 ]