UNIX系统下的C程序设计.docx

上传人:b****1 文档编号:684012 上传时间:2023-04-29 格式:DOCX 页数:40 大小:38.23KB
下载 相关 举报
UNIX系统下的C程序设计.docx_第1页
第1页 / 共40页
UNIX系统下的C程序设计.docx_第2页
第2页 / 共40页
UNIX系统下的C程序设计.docx_第3页
第3页 / 共40页
UNIX系统下的C程序设计.docx_第4页
第4页 / 共40页
UNIX系统下的C程序设计.docx_第5页
第5页 / 共40页
UNIX系统下的C程序设计.docx_第6页
第6页 / 共40页
UNIX系统下的C程序设计.docx_第7页
第7页 / 共40页
UNIX系统下的C程序设计.docx_第8页
第8页 / 共40页
UNIX系统下的C程序设计.docx_第9页
第9页 / 共40页
UNIX系统下的C程序设计.docx_第10页
第10页 / 共40页
UNIX系统下的C程序设计.docx_第11页
第11页 / 共40页
UNIX系统下的C程序设计.docx_第12页
第12页 / 共40页
UNIX系统下的C程序设计.docx_第13页
第13页 / 共40页
UNIX系统下的C程序设计.docx_第14页
第14页 / 共40页
UNIX系统下的C程序设计.docx_第15页
第15页 / 共40页
UNIX系统下的C程序设计.docx_第16页
第16页 / 共40页
UNIX系统下的C程序设计.docx_第17页
第17页 / 共40页
UNIX系统下的C程序设计.docx_第18页
第18页 / 共40页
UNIX系统下的C程序设计.docx_第19页
第19页 / 共40页
UNIX系统下的C程序设计.docx_第20页
第20页 / 共40页
亲,该文档总共40页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

UNIX系统下的C程序设计.docx

《UNIX系统下的C程序设计.docx》由会员分享,可在线阅读,更多相关《UNIX系统下的C程序设计.docx(40页珍藏版)》请在冰点文库上搜索。

UNIX系统下的C程序设计.docx

UNIX系统下的C程序设计

第一章概述

1.1UNIX的版本

本教材的目的是讲解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等。

由于Windows

NT的异军突起,对UNIX的市场形成巨大的威胁,各大UNIX厂商不得不联合起来,在工作站市场上,统一以系统V版作为标准,加入BSD版本中的一些优点,支持统一的CDE(Common

DesktopEnvironment)窗口环境,以与WindowsNT进行对抗。

1.2UNIX编程环境 

UNIX操作系统通过Shell程序实现系统与用户的交互,在Shell提示符下,用户键入UNIX命令,即可得到操作系统的输出结果。

BSD系统的常用Shell是CShell,缺省提示符是"%",系统V的常用Shell是BourneShell(现在多为Korn

Shell),缺省提示符是"$",有关Shell的编程,我们在后面的章节中进行介绍。

 

UNIX上的标准编译器是cc。

在Shell提示符下(以CShell为例)键入下列命令:

%cc-ohellohello.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.owindowx.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.3UNIX编程中的基本概念

在讨论UNIX编程开发前,首先需要阐明系统调用和库函数这两个概念。

一个系统调用指一个需要操作系统代表用户程序来执行某些任务的请求。

例如:

read是一个系统调用,它请求操作系统存储在一个磁盘设备(或其他设备)上的数据去填充一个缓冲区。

如果任何人在他们想执行任务的时候都能随便访问设备,那么后果将是不可预测的。

所以,这种服务必须请求操作系统来做,它(经常是透明地)记录所有处理每个设备的请求。

而一个库函数,并不经常需要操作系统来执行其任务。

例如数学库函数中的sin(),cos()等,这些计算只需要简单地对一个有限序列求和,所以并不需要操作系统干预。

在UNIX操作系统中,有一个常用的命令man,可用来查阅命令、库函数和系统调用等的具体使用方法。

传统Unix联机帮助手册的分节法为:

1用户级命令(User-levelcommands)

2系统调用(Systemcalls)

3库函数(Libraryfunctions)

4设备及驱动程序(Devicesanddevicedrivers)

5文件格式(Fileformats)

6游戏(Games)

7杂项(Variousmiscellaneousstuff-macropackagesetc.)

8系统维护及操作命令(Systemmaintenanceandoperationcommands)

第二章标准输入/输出库 

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()用于为读写而打开一个文件,或用它来创建新文件。

intopen(constchar*path,intoflag,.../*mode_tmode*/);

open使用三个参数:

一个字符串path包含要打开的文件名;一个整数oflag指明文件将被如何打开;整数mode在创建文件时使用。

常用的oflag包括:

O_RDONLY打开文件仅用于读。

O_WRONLY打开文件仅用于写。

O_RDWR打开文件用于读写。

O_CREAT如果文件不存在,则创建,此时mode作为第三个参数给出。

close()用于关闭一个已经打开的文件。

 

·文件读写

read()用于读文件,格式为:

read(intfildes,void*buf,size_tnbyte);

三个参数说明如下:

filedes是文件描述字;指针buf指向一个数据将被读入的缓冲区;整数nbytes指明要读的字节个数。

成功时返回实际读入的字节数,出错则返回-1。

write()用于写文件,与read类似,格式为:

write(intfildes,void*buf,size_tnbyte);

三个参数说明如下:

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-x1ydsuser589月25日10时54分hello.c 

最左面一栏显示了该文件的模式:

文件主对该文件可读(r)、可写(w)、可执行(x),同组用户对该文件可读、可执行,其他用户对该文件可读、可执行。

相应的,di_mode的0-8位为111101101(0755)。

4.2文件编程介绍 

·检查访问权限-access系统调用 

access系统调用的格式为:

 

#include

intaccess(constchar*path,intamode); 

其中:

参数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

intlink(constchar*path1,constchar*path2);

intunlink(constchar*path); 

其中:

参数path1指出已经存在的要被链接的文件路径名,path2指出要建立的链接文件。

link实现path2到path1的链接,相当于给path1起了一个别名,同时文件path1的链接计数加1。

若成功则返回0,否则返回-1。

 

参数path指出要被删除的文件路径名。

Unlink删除由path指出的文件,若成功则返回0,否则返回-1。

 

·从I节点上获取信息-stat与fstat系统调用 

stat与fstat的调用格式为:

 

#include

#include

intstat(constchar*path,structstat*buf);

intfstat(intfildes,structstat*buf); 

说明:

stat和fstat都用于获取文件I节点中有关状态信息。

stat根据参数path给出的文件路径名,搜索它对应的盘I节点,而fstat则根据参数fildes给出的文件描述字去查找对应的I节点。

这两个调用都把从I节点中获取到的信息重组后放入参数buf指向的stat结构中(stat结构的说明在文件/usr/include/sys/stat.h中)。

这两个调用成功时均返回0,否则返回-1。

 

stat与fstat调用无论在使用上还是在功能上都是非常类似的,在参数上有一点区别。

下面我们来看一个例子。

 

/*statfile.c*/

#include

#include

#include

#include 

main(argc,argv)

intargc;

char*argv[];

{

intfd;

structstatstatbuf;

if(argc!

=2){

printf("usage:

statfilefilename!

\n");

exit

(1);

}

if((fd=fopen(argv[1],O_RDONLY))==-1)

fprintf(stderr,"Cannotopen%s!

\n",argv[1]);

if(unlink(argv[1])==-1)

fprintf(stderr,"Cannotunlink%s!

\n",argv[1]);

if(stat(argv[1],&statbuf)==-1)/*byfilename*/

fprintf(stderr,"stat%sfailsasitshould!

\n");

else

printf("stat%ssucceed!

\n",argv[1]);

if(fstat(fd,&statbuf)==-1)/*byfiledescriptor*/

fprintf(stderr,"fstat%sfails!

\n",argv[1]);

else

printf("fstat%ssucceedsasitshould!

\n",argv[1]);

程序首先打开命令行中指定的文件,然后用unlink将该文件删除,接着分别用stat与fstat系统调用获取该文件的信息。

假设当前命令下有一个名为xxx.c的文件,运行 

%statfilexxx.c 

后,将会输出如下结果:

 

statxxx.cfailsasitshould!

fstatxxx.csucceedsasitshould!

 

从中可知,当一个打开文件被删除后,用stat无法获取该文件的信息。

而fstat就可获取该文件的信息。

这是由于文件名在unlink之后已从目录中除去,无法找到该文件名,而文件描述字则因文件仍打开而保存下来。

因此stat不能成功返回,但fstat仍可成功返回。

 

使用stat调用来判定一个文件为何种文件类型时相当有用。

例如下列代码:

 

stat("hello",&statbuf);

if(statbuf.st_mod&S_IFMT)==S_IFDIR)

printf("Thisisadirectoryfile!

\n");

elseif(statbuf.st_mod&S_IFMT)==S_IFREG)

printf("Thisisaregularfile!

\n");

else… 

以上代码可判定当前目录下的hello文件是否为目录文件或其他类型的文件。

 

4.3目录编程介绍 

UNIX把目录也视为一种文件,称为目录文件,并同普通文件一样进行管理和保护。

如open、close、read、lseek等文件操作对目录文件都是有效的。

前面讲到的文件编程中的各个系统调用对于目录来说也同样有效。

但是与普通文件相比目录文件又具有自身的一些特点:

 

目录文件的读/写/执行访问权限有特殊的含义:

读权限允许用户读取目录项的内容;写权限允许用户创建或删除一个文件;执行权限则允许用户检索目录(此时通常称为目录搜索权限)。

 

目录的创建、删除与普通文件也不同,另外,任何用户都不能对目录文件以写方式打开进行文件写操作。

 

·目录的创建和删除-mkdir和rmdir系统调用 

mkdir和rmdir系统调用的格式为:

 

#include

#include

intmkdir(constchar*path,mode_tmode); 

#include

intrmdir(constchar*path); 

其中:

参数path分别指出要创建和删除的目录文件的文件名。

mkdir调用中的参数mode指出新创建目录文件的文件模式。

新创建目录后,除"."和".."两项外,无别的目录项;删除目录时,要求目录中除"."和".."两项外,也无别的目录项。

这两个系统调用Access成功时都返回0,否则返回-1。

 

·目录的读取-opendir/readdir/closedir库函数 

目录文件可以像普通文件一样,先用系统调用open以读方式打开,再用read调用读取其中的内容。

同时,由于目录文件是由具有目录结构的目录项组成的,用read读取其内容有些不方便。

UNIX提供的库函数opendir/readdir/closedir等可以方便地实现目录读取。

函数说明如下:

 

#include

#include

DIR*opendir(char*filename);

structdirect*readdir(DIR*dirp);

voidclosedir(DIR*dirp); 

说明:

参数filename指出要打开的目录路径名,库函数opendir返回一个指向结构DIR(在文件/usr/include/sys/dir.h中定义)的指针。

库函数readdir和closedir均以这个指针作为参数,其中readdir返回一个指向结构direct的指针。

有关目录的操作均可基于这个指针。

下面是一个例子,查找当前目录下文件名为"name"的文件。

 

len=strlen(name);

dirp=opendir(".");

if(dirp==NULL){

returnNOT_FOUND;

}

while((dp=readdir(dirp))!

=NULL){

if(dp->d_namlen==len&&!

strcmp(dp->d_name,name)){

closedir(dirp);

returnFOUND;

}

}

closedir(dirp);

returnNOT_FOUND; 

库函数closedir关闭打开的目录。

值得注意的是,上面这一小段代码在编程中很实用,稍加修改即可实现UNIX下类似"ls"的简单命令。

第五章基本进程编程 

5.1概述 

UNIX系统为程序员提供了一个强有力的工具:

在一个程序中执行另一个程序。

执行一个程序最简单的途径就是使用库函数system。

该函数使用一个参数:

一个包含要被执行的命令的字符串。

这一库函数的特点是用法简单,在程序中调用简单的UNIX命令时很有用。

但是由于它的调用要由SHELL进程来实现,故效率并不高,在实际的编程中应用并不广泛。

本章主要介绍在实际编程中经常使用的有关进程控制和管理方面的系统调用,它们包括:

 

fork-创建一子进程

exec-执行子进程

exit-终止进程执行

wait-等待子进程暂停或终止

setpgrp-设置进程标识符

getpid、getppid-获取进程标识符

setuid、setgid-设置进程的用户标识符

getuid、geteuid、getgid、getegid-获取进程的用户标识符

5.2进程控制 

1.fork系统调用 

系统调用fork是UNIX操作系统创建新进程的唯一手段,习惯上将新创建的进程称为子进程,调用fork的进程称为父进程。

fork系统调用的格式为:

 

intfork() 

fork系统调用没有参数,如执行成功,则创建一子进程,子进程继承了父进程的某些属性。

当从该系统调用返回时,系统中已有两个用户级环境完全相同的进程存在。

这两个进程从fork调用中得到的返回值不同,其中子进程得到的返回值为零,父进程得到的返回值是最新创建的子进程的进程标识符。

 

2.exec系统调用 

fork系统调用只是将父进程的环境拷贝到新进程中,而没有启动执行一个新的目标程序。

UNIX系统提供了exec系统调用,用它更换进程的执行映象,启动新的目标程序。

例如:

UNIX系统中的所有命令都是通过exec来执行的。

 

exec系统调用有六种不同的使用格式,但在核心中只对应一个调用入口。

它们有不同的调用格式和调用参数。

这六种调用格式分别为:

 

#include

intexecl(constchar*path,constchar*arg0,...,constchar

*argn,(char*)0);

intexecv(constchar*path,char*const*argv);

intexecle(constchar*path,constchar*arg0,...,constchar

*argn,

(char*0),constchar*envp[]);

intexecve(constchar*path,char*const*argv,char*const*envp);

intexeclp(constchar*file,constchar

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 总结汇报 > 学习总结

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2