分类:
2008-10-15 16:40:50
UNIX 编程资料
第一章 概述
1.1UNIX的版本
UNIX操作系统是贝尔实验室于六十年代末用C语言研制开发的。经过几十年的发展,已经成为流行于从大型机、小型机到工作站甚至微机等多种平台的操作系统。UNIX的成功同时也推动了C语言的普及。本教材的目的是讲解UNIX系统下的C程序设计,使C程序员快速掌握UNIX系统下的编程开发。作者在进行UNIX编程开发的实践过程中,深感实例的重要性-一个简短的C语言实例往往胜过长篇累牍的文字说明,当然了,文字说明也是必不可少的。本教材将本着实例优先的原则,使您能够对UNIX编程开发快速入门。
UNIX的版本不统一是出了名的,从UNIX的发展历史来看,主要有两大流派:AT&T的UNIX系统V版本和加州大学伯克利分校的BSD版本,在此基础上,各家UNIX厂商均开发了各自的UNIX操作系统。如:工作站厂商中有HP的hpux、SUN的solaris、SGI的irix、IBM的AIX等,小型机有VAX上的Ultrix,微机上有SCO
UNIX、微软的Xenix以及随着Internet而风靡全球的Linux等。由于
NT的异军突起,对UNIX的市场形成巨大的威胁,各大UNIX厂商不得不联合起来,在工作站市场上,统一以系统V版作为标准,加入BSD版本中的一些优点,支持统一的CDE(Common
Desktop Environment)窗口环境,以与 NT进行对抗。
1.2 UNIX编程环境
UNIX操作系统通过Shell程序实现系统与用户的交互,在Shell提示符下,用户键入UNIX命令,即可得到操作系统的输出结果。BSD系统的常用Shell是C Shell,缺省提示符是"%",系统V的常用Shell是Bourne Shell(现在多为Korn
Shell),缺省提示符是"$",有关Shell的编程,我们在后面的章节中进行介绍。
UNIX上的标准编译器是cc。在Shell提示符下(以C Shell为例)键入下列命令:
%cc -o hello hello.c
即将C文件hello.c编译为可执行文件hello。在编译多个文件生成一个可执行文件时,UNIX提供命令make。用户需要针对多个C文件,按照一定的格式编写一个叫做Makefile的文本文件。下面是SGI上的一个Makefile的例子:
CC = cc
CFLAGS = $(DEBUG) -cckr -I$(INC)/X11 -DSYSV
DEBUG = -g
INC = /usr/include
LDFLAGS = -lXext -lXm -lXt -lX11 -lPW -lc
OBJS = initx.o windowx.o
TGTS = showxwin
all:: $(TGTS)
showxwin: $(OBJS)
$(CC) -o $@ $(OBJS) $(CFLAGS) $(LDFLAGS)
大写字母的字串是一些宏,CC是编译器的名字、CFLAGS定义cc的编译开关、DEBUG是调试宏、INC是头文件所在目录、LDFLAGS定义了编译连接库、OBJ定义了目标文件名、TGTS定义了可执行文件名。在Shell提示符下直接键入:
%make
即可将Makefile中指定的所有C文件进行编译并生成可执行文件。
1.3 UNIX编程中的基本概念
在讨论UNIX编程开发前,首先需要阐明系统调用和库函数这两个概念。
一个系统调用指一个需要操作系统代表用户程序来执行某些任务的请求。例如:read是一个系统调用,它请求操作系统在一个磁盘设备(或其他设备)上的数据去填充一个缓冲区。如果任何人在他们想执行任务的时候都能随便访问设备,那么后果将是不可预测的。所以,这种服务必须请求操作系统来做,它(经常是透明地)记录所有处理每个设备的请求。
而一个库函数,并不经常需要操作系统来执行其任务。例如数学库函数中的sin(),cos()等,这些计算只需要简单地对一个有限序列求和,所以并不需要操作系统干预。
在UNIX操作系统中,有一个常用的命令man,可用来查阅命令、库函数和系统调用等的具体使用方法。传统 Unix 联机帮助手册的分节法为:
1 用户级命令(User-level commands)
2 系统调用(System calls)
3 库函数(Library functions)
4 设备及驱动程序(Devices and device drivers)
5 文件格式(File formats)
6 游戏(Games)
7 杂项(Various miscellaneous stuff - macro packages etc.)
8 系统维护及操作命令(System maintenance and operation commands)
第二章 标准输入/输出库
2.1 概述
本章介绍UNIX的标准输入/输出库,UNIX提供一些库函数完成高级输入/输出,为程序员提供了三方面的主要功能:
·自动开辟缓冲区。即使一次读或写的数据只有几个字节,库函数仍然在大到由数千个字节组成的"块"中执行实际输入或输出(缓冲区大小通常由头文件stdio.h中的常量BUFSIZ定义)。这个缓冲区在内部开辟给库函数使用,对于程序员来说是透明的;
·自动执行输入和输出转换。
·输入输出被自动格式化。以上两点在C语言的教程中一般均以讲到。
在标准输入/输出库中,一个文件被称为一串字符流,并且被一个指向类型为FILE的目标指针所描述,该指针被称为文件指针。在UNIX中文件指针stdin、stdout、stderr是预先定义好的,分别对应标准输入(键盘)、标准输出(终端屏幕)和标准错误输出。
2.2 库函数介绍
·文件创建和关闭
fopen()用于打开已存在的文件或创建新文件
·文件读写
1、 一次处理一个字符 getc(), putc()
2、 一次处理多个字符 fgets(), fputs()
3、 文件的二进制读写 fread(), fwrite()
4、 文件的格式化输入/输出 fscanf(), fprintf()
5、 字符串的格式化输入/输出 sscanf(), sprintf()
·文件移动定位
用于在文件中移动的标准输入/输出库函数是fseek(),它接收三个参数:一个文件指针指向一个打开的字符流;一个整数指明要移动的字节数,称为offset;一个整数指明从文件中什么位置移动。
第三章 低级输入/输出
3.1 概述
与第二章内容相对应,本章介绍UNIX系统中通过系统调用来实现的输入/输出,通常称之为低级输入/输出。这些系统调用能够直接实现对设备(如磁带驱动器等)的输入和输出,程序员能够决定要使用的缓冲区的大小,而不象标准输入/输出库函数那样透明设定缓冲区大小。
在标准输入/输出库中,一个文件是由一个文件指针来对应的。当使用低级界面时,则用一个文件描述字对应一个文件。文件描述字是一个小的整数。有3个事先定义的文件描述字0、1和2,分别对应标准输入、标准输出和标准错误输出。一般说来,文件描述字都是作为系统调用的第一个参数给出的。
3.2 相关系统调用介绍
·文件创建和关闭
open()用于为读写而打开一个文件,或用它来创建新文件。
int open (const char *path, int oflag, ... /* mode_t mode */);
open使用三个参数:一个字符串path包含要打开的文件名;一个整数oflag指明文件将被如何打开;整数mode在创建文件时使用。常用的oflag包括:
O_RDONLY 打开文件仅用于读。
O_WRONLY 打开文件仅用于写。
O_RDWR 打开文件用于读写。
O_CREAT 如果文件不存在,则创建,此时mode作为第三个参数给出。
close()用于关闭一个已经打开的文件。
·文件读写
read()用于读文件,格式为:
read(int fildes, void *buf, size_t nbyte);
三个参数说明如下:filedes是文件描述字;指针buf指向一个数据将被读入的缓冲区;整数nbytes指明要读的字节个数。成功时返回实际读入的字节数,出错则返回-1。
write()用于写文件,与read类似,格式为:
write(int fildes, void *buf, size_t nbyte);
三个参数说明如下:filedes是文件描述字;指针buf指向一个数据将被写入的缓冲区;整数nbytes指明要写的字节个数。成功时返回实际写入的字节数,出错则返回-1。
·文件移动定位
用于在文件中移动的低级输入/输出系统调用是lseek(),与fseek()类似,它也接收三个参数:一个文件描述字对应一个打开的文件;一个整数指明要移动的字节数,称为offset;一个整数指明从文件中什么位置移动。
·复制文件描述字
有时候有不只一个文件描述字对应一个文件。当创建子进程时(参加后面关于进程开发的章节),这一点很常用。为了获得一个新的文件描述字,并保证其与fd对应同一个文件,应调用
fd2 = dup(fd)
fd2现在和fd对应同一个文件,并且和fd一样在文件中有相同的位置。
第四章 文件与目录编程
4.1 基本概念
·文件目录概述
文件系统是UNIX对计算机技术的一大贡献!UNIX系统的文件管理十分灵活、功能强大,许多首次在UNIX系统中出现的概念被其他操作系统所采用,如MS-DOS等。
UNIX系统提供了一种层次目录方案。目录就象存放一组文件的柜子一样,目录也可以包括在其他目录中,这样就形成了一种庞大的、具有分支的组织方式,这种结构通常被称为树状结构。目录实际上也是一种特殊的文件。命令、数据文件、其他命令甚至设备(特别文件)都可以作为目录中的项(文件)。
·I标识号、I列表和I节点
一个目录是由一系列结构组成的;每个结构包含一个文件名和一个指向文件自身的指针,该指针是一个整数,称为文件的I标识号。当文件被访问时,它的I标识号用来作为索引打开一个系统表(I列表),系统中存放着文件(I节点)的实体。I节点包含了对文件的描述:
·文件自身的用户和用户组ID
·文件的保护码
·文件内容所在的物理磁盘地址
·文件的大小
·最后一次I节点改变的时间,最后一次使用和修改的时间
·连接该文件的次数,即它出现在其他目录中的次数
·一个指明文件类型的标记(目录、普通文件、特别文件)
·文件的三级保护
UNIX把使用文件的用户分成三个等级:文件所有者、同组用户和其他用户。文件所有者也称文件主,是文件的创建者,对该文件拥有所有权限;同组用户是具有相同组标识号的所有用户,文件主可以决定一个文件属于哪个组以及该组用户对文件的存取权;其他用户是指与文件主无关的用户,他们与文件主不属于同一个用户组,其他用户对一个文件的访问权限也由该文件主决定的。
一个文件的访问权限存放在该文件I节点的di_mode域中,di_mode的0-8位表示文件主、文件组用户和其他用户对该文件的存取权限。举个例子,用"ls
-l"命令可列出文件hello.c的模式和属性:
-rwxr-xr-x 1 yds user 58 9月 25日 10时54分 hello.c
最左面一栏显示了该文件的模式:文件主对该文件可读(r)、可写(w)、可执行(x),同组用户对该文件可读、可执行,其他用户对该文件可读、可执行。相应的,di_mode的0-8位为111101101(0755)。
4.2 文件编程介绍
·检查访问权限-access系统调用
access系统调用的格式为:
#include
int access(const char *path, int amode);
其中:参数path指出被检查文件的路径,参数amode指出访问权限。Access判断调用进程的实际用户对文件path是否具有amode所指定的访问权限,若有相应权限,access返回0,否则返回-1。
参数amode可取以下值或它们的逻辑"或":
R_OK 检查读权限
W_OK 检查写权限
X_OK 检查执行(搜索)权限
F_OK 检查文件是否存在
例如:access("hello.c", R_OK|W_OK),
用来检查实际用户对文件hello.c是否具有读/写权;access("hello.c",F_OK) 判断文件hello.c是否存在。
·链接与删除文件-link和unlink系统调用
link和unlink系统调用的格式为:
#include
int link (const char *path1, const char *path2);
int unlink(const char *path);
其中:参数path1指出已经存在的要被链接的文件路径名,path2指出要建立的链接文件。link实现path2到path1的链接,相当于给path1起了一个别名,同时文件path1的链接计数加1。若成功则返回0,否则返回-1。
参数path指出要被删除的文件路径名。Unlink删除由path指出的文件,若成功则返回0,否则返回-1。
·从I节点上获取信息-stat与fstat系统调用
stat与fstat的调用格式为:
#include
#include
int stat(const char *path, struct stat *buf);
int fstat(int fildes, struct stat *buf);
[1]