第1章
UNIX基础知识
1.1
引言
所有操½系统½向它们运行的程序提供服务。典型的服务有执行新程序、打开文件、读文
件、分配存储区、获得½前时间等等,本书集中阐述了
UNIX操½系统各种版本所提供的服务。
以严格的步进方式、不超前引用尚未说明过的术语的方式来说明
UNIX几乎是不可½的(可
½也会是令人厌烦的
)。本章从程序设计人员的角度快速浏览 UNIX,并对书中引用的一些术语
和概念进行简要的说明并给出实例。在以后各章中,将对这些概念½更详细的说明。本章也对
不熟悉U
NIX的程序设计人员简要介绍了 UNIX提供的各种服务。
1.2
登½
1.2.1
登½名
登½
U N I X
系统时,先键入登½名,然后键入口令。系统在其口令文件,通常是
/ e t c / p a s s w d文件中查看登½名。口令文件中的登½项由 7个以冒号分隔的字段组成:登½名,
加密口令,数字用户
ID(224),数字组ID(20),注释字段,起始目½ (/home/stevens),以及 shell
程序(
/bin/ksh)。
很多比较新的系统已将加密口令移到另一个文件中。第
6章将说明这种文件以及存取它们
的½数。
1.2.2 shell
登½后,系统先显示一些典型的系统信息,然后就可以向
shell程序键入½令。 shell是一个
½令行解释器,它读取用户输入,然后执行½令,用户通常用终端,有时则通过文件
(称为
shell脚本)向shell进行输入。常用的 shell有:
• Bourne shell, /bin/sh
• C shell, /bin/csh
• KornShell, /bin/ksh
系统从口令文件中登½项的最后一个字段中了解到应该执行哪一个
shell。
自V
7以来,Bourne shell得到了广泛应用,几乎每一个现有的UNIX系统½提供Bourne shell。
C shell是在伯克利开发的,所有 BSD版本½提供这种 shell。另外, AT&T的系统V/386 R3.2和
SVR4也提供C shell(下一章将对这些不同的 UNIX版本½更多说明) ornShell是Bourne shell
。K
的后继者,它由
SVR4提供。KornShell在大多数UNIX系统上运行,½在 SVR4之前,通常它需
要另行购买,所以没有其他两种
shell流行。
本书将½用很多
s h e l l实例,以执行已开发的程序,其中将应用 Bourne shell和K o r n S h e l l½
具有的功½。
2
UNIX环境高级编程
Bourne shell是Steve Bourne在贝尔实验室中开发的,其控制流结构½人想起
Algol 68。C shell是在伯克利由Bill Joy完成的,其基础是第6版shell(不是Bourne
shell)
。其控制结构很像C语言,它支持一些Bourne
shell没有提供的功½,如½业
控制,历史机制和½令行编辑。
K o r n S h e l l是David Korn在贝尔实验室中开发的,
它兼容
Bourne shell,并且也包含了½ C shell非常流行的一些功½,如½业控制、
½令行编译等。
本书将½用这种½式的注释来描述历史,并对不同的
UNIX实现进行比较。½
我们了解了历史缘由后,采用某种特定实现技术的原因将变得清晰起来。
1.3
文件和目½
1.3.1
文件系统
U N I X文件系统是目½和文件的一种层次安排,目½的起点称为根 ( r o o t ),其名字是一个
字符/。
目½(d
irectory)是一个包含目½项的文件,在逻辑上,可以认为每个目½项½包含一个
文件名,同时还包含说明该文件属性的信息。文件属性是:文件类型,文件长度,文件所有者,
文件的许可权(例如,其他用户½否½访问该文件)
,文件最后的修改时间等。
stat和fstat½数
返回一个包含所有文件属性的信息结构。第
4章将详细说明文件的各种属性。
1.3.2
文件名
目½中的各个名字称为文件名(
filename)
。不½出现在文件名中的字符只有两个,斜线
(/)
和空操½符(n
ull)
。斜线分隔构成路径名
(在下面说明)的各文件名,空操½符则终止一个路径
名。½管如此,½的习惯是只½用印刷字符的一个子集½为文件名字符
(只½用子集的理由是:
如果在文件名中½用了某些
shell特殊字符,则必须½用shell的引号机制来引用文件名)。
½创建一个新目½时,自动创建了两个文件名:
. (称为点)和. . (称为点-点)。点引用½前目
½,点-点则引用父目½。在最高层次的根目½中,点
-点与点相同。
某些U
NIX文件系统限制文件名的最大长度为 14个字符,BSD版本则将这种限制扩展为 255
个字符。
1.3.3
路径名
0个或多个以斜线分隔的文件名序列 (可以任选地以斜线开头 )构成路径名( pathname)
,以
斜线开头的路径名称为绝对路径名(
absolute pathname
)
,否则称为相对路径名(
r e l a t i v e
pathname)
。
实例
不难列出一个目½中所有文件的名字,程序
1-1是ls(1)½令的主要实现部分
程序1-1 列出一个目½中的所有文件
第
1章 UNIX基础知识
3
ls(1)这种表示方法是UNIX的惯用方法,用以引用 UNIX手册集中的一个特定项。它引用第
一部分中的
ls项,各部分通常用数字 1至8表示,在每个部分中的各项则按字母顺序排列。假定
½有一½所½用的
UNIX系统的手册。
早期的U
N I X系统把8个部分½集中在一本手册中,现在的趋势是把这些部分
分别安排在不同的手册中:有用户专用手册,程序员专用手册,系统管理员专用
的手册等等。
某些U
NIX系统把一个给定部分中的手册页又用一个大写字母进一步分成若干
小部分,例如,AT
&T〔1990e〕中的所有标准 I/O½数½被指明在3S部分中,例如
fopen(3S)。
某些U
N I X系统,例如以 X e n i x为基础的系统,不是采用数字将手册分成若干
部分,而是用C表示½令(第1部分),S表示服务(通常是第2、3部分)等等。
如果½有联机手册,则可用下面的½令查看
ls½令手册页:
man 1 ls
程序1
- 1只打印一个目½中各个文件的名字,不显示其他信息,如若该源文件名为 m y l s . c ,
则可以用下面的½令对其进行编译,编译的结果送入系统默认名为
a.out的可执行文件名:
cc myls.c
某种样本输出是:
$
a.out /dev
.
..
MAKEDEV
console
tty
mem
kmem
null
此处略去多行
4
UNIX环境高级编程
printer
$
a.out /var/spool/mqueue
can't open /var/spool/mqueue:Permission denied
$
a.out /dev/tty
can't open /dev/tty:Not a directory
本书将以这种方式表示输入的½令以及其输出:输入的字符以粗½表示,程序输出则以另
一种字½表示。如果欲对输出添加注释,则以中文宋½表示,输入之前的美元符号
($)是shell打
印的提示符,本书将s
hell提示符显示为$。
注意,列出的目½项不是以字母顺序排列的,
ls½令则一般按字母顺序列出目½项。
在这2
0行的程序中,有很多细节需要考虑:
•
首先,其中包含了一个头文件
ourhdr.h。本书中几乎每一个程序½包含此头文件。它包含
了某些标准系统头文件,定义了许多常数及½数原型,这些½将用于本书的各个实例中,附½
B列出了常用头文件。
• main½数的说明½用了ANSI C
标准所支持的新风格(下一章将对
ANSI C½更多说明)
。
•
取½令行的第1个参数a
rg v〔1〕½为列出的目½名。第 7章将说明 main½数如½被调用,
程序如½存取½令行参数和环境变量。
•
因为各种不同U
NIX系统的目½项的实际格式是不一样的,所以½用½数 opendir, readdir
和c
losedir处理目½。
• opendir½数返回指向 D I R结构的指针,并将该指针传向 r e a d d i r½数。我们并不关心 D I R
结构中包含了什么。然后,在循环中调用
r e a d d i r来读每个目½项。它返回一个指向 d i r e n t结
构的指针,而½目½中已无目½项可读时则返回
n u l l指针。在 d i r e n t结构中取出的只是每个
目½项的名字
( d _ n a m e )。½用该名字,此后就可调用 s t a t½数(见4 . 2节)以决定该文件的所有
属性。
•
调用了两个自编的½数来对错误进行处理:e
rr_sys和err_quit。从上面的输出中可以看到,
err_sys½数打印一条消息(
“Permission
denied(许可权拒绝 )”或“Not a directory(不是一个目
½)”),说明遇到了什么类型的错误。这两个出错处理½数在附½
B中说明, 1.7节将更多地叙
述出错处理。这两个出错处理½数在附½
B中说明1.7节将更详细地叙述出错处理。
•
½程序将结束时,它以参数
0调用½数exit。½数exit终止程序。按惯例,参数 0的意思是
正常结束,参数值
1½255则表示出错。8.5节将说明一个程序(例如shell或我们所编写的程序)如
½获得它所执行的另一个程序的
exit状态。
1.3.4
工½目½
每个进程½有一个工½目½
(working directory,有时称为½前工½目½ (current working
directory))。所有相对路径名½从工½目½开始解释。进程可以用 chdir½数更改其工½目½。
例如,相对路径名
doc/memo/joe指的是文件 joe,它在目½ memo中,而memo又在目½ doc
中,d
o c则应是工½目½中的一个目½项。从该路径名可以看出, d o c和m e m o½应½是目½,
½是却不清楚
j o e是文件还是目½。路径名 / u r s / l i b / l i n t是一个绝对路径名,它指的是文件 (或目
½)
lint,而lint在目½lib中,lib则在目½usr中,usr则在根目½中。
1.3.5
起始目½
登½时,工½目½设½为起始目½
(home directory),该起始目½从口令文件(见1.2节)中
第
1章 UNIX基础知识
5
的登½项中取得。
1.4
输入和输出
1.4.1
文件描述符
文字描述符是一个小的非负整数,内核用以标识一个特定进程正在存访的文件。½内核打
开一个现存文件或创建一个新文件时,它就返回一个文件描述符。½读、写文件时,就可½
用它。
1.4.2
标准输入、标准输出和标准出错
按惯例,每½运行一个新程序时,所有的
shell½为其打开三个文件描述符:标准输入、标
准输出以及标准出错。如果像简单½令
ls那样没有做什么特殊处理,则这三个描述符½连向终
端。大多数s
hell½提供一种方法,½任½一个或所有这三个描述符½½重新定向到某一个文件,
例如:
ls > file.list
执行l
s½令,其标准输出重新定向到名为 file.list的文件上。
1.4.3
不用缓存的
I/O
½数o
p e n、r e a d、w r i t e、l s e e k以及c l o s e提供了不用缓存的 I / O。这些½数½用文件描述符
进行工½。
实例
如果愿意从标准输入读,并写向标准输出,则程序
1-2可用于复制任一 UNIX文件。
程序1-2 将标准输入复制到标准输出
头文件
< u n i s t d . h > ( o u r h d r. h中包含了此头文件 )及两个常数 S T D I N _ F I L E N O和S T D O U T _
FILENO是POSIX标准的一部分(下一章将对此½更多的说明)
。很多
UNIX系统服务的½数原
型,例如我们调用的r
ead和write½在此头文件中。½数原型也是 ANSI C
标准的一部分,本章的
评论