Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1754138
  • 博文数量: 600
  • 博客积分: 10581
  • 博客等级: 上将
  • 技术积分: 6205
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-06 10:13
文章分类
文章存档

2016年(2)

2015年(9)

2014年(8)

2013年(5)

2012年(8)

2011年(36)

2010年(34)

2009年(451)

2008年(47)

分类: LINUX

2009-08-22 13:06:39

 (5) F I F O。这种文件用于进程间的通信,有时也将其称为命名管道。

(6) 套接口( s o c k e t )。这种文件用于进程间的网络通信。套接口也可用于在一台宿主机上的进程之间的非网络通信。

(7) 符号连接(symbolic link)。这种文件指向另一个文件。

 

       宏文件类型

S _ I S R E G ( ) 普通文件

S _ I S D I R ( ) 目录文件

S _ I S C H R ( ) 字符特殊文件

S _ I S B L K ( ) 块特殊文件

S _ I S F I F O ( ) 管道或F I F O

S _ I S L N K ( ) 符号连接( P O S I X . 1S V R 4无此类型)

S _ I S S O C K ( ) 套接字(P O S I X . 1S V R 4无此类型)

 

 

1.         当用o p e n函数打开一个文件时,内核以进程的有效用户I D和有效组I D为基

础执行其存取许可权测试。有时,进程也希望按其实际用户I D和实际组I D来测试其存取能力。

例如当一个进程使用设置-用户- I D,或设置-- I D特征作为另一个用户(或组)运行时,这就可

能需要。即使一个进程可能已经设置-用户- I D为根,它仍可能想验证实际用户能否存取一个给

定的文件。a c c e s s函数是按实际用户I D和实际组I D进行存取许可权测试的。

 

2.        粘住位

S _ I S V T X位有一段有趣的历史。在U N I X的早期版本中,有一位被称为粘住位(sticky bit)。如果一个可执行程序文件的这一位被设置了,那么在该程序第一次执行并结束时,该程序正文的一个文本被保存在交换区。(程序的正文部分是机器指令部分。)这使得下次执行该程序时能较快地将其装入内存区。其原因是:在交换区,该文件是被连续存放的,而在一般的U N I X

件系统中,文件的各数据块很可能是随机存放的。对于常用的应用程序,例如文本编辑程序和

编译程序的各部分常常设置它们所在文件的粘住位。自然,对交换区中可以同时存放的设置了

粘住位的文件数有一定限制,以免过多占用交换区空间,但无论如何这是一个有用的技术。因

为在系统再次自举前,文件的正文部分总是在交换区中,所以使用了名字“粘住”。后来的

U N I X版本称之为保存-正文位( saved-text bit),因此也就有了常数S _ I S V T X。现今较新的

U N I X系统大多数都具有虚存系统以及快速文件系统,所以不再需要使用这种技术。

S V R 44 . 3 + B S D中粘住位的主要针对目录。如果对一个目录设置了粘住位,则只有对该

目录具有写许可权的用户并且满足下列条件之一,才能删除或更名该目录下的文件:

拥有此文件。

拥有此目录。

是超级用户。

目录/ t m p/ v a r / s p o o l / u u c p p u b l i c是设置粘住位的候选者—这两个目录是任何用户都可在其中创建文件的目录。这两个目录对任一用户(用户、组和其他)的许可权通常都是读、写和执行。但是用户不应能删除或更名属于其他人的文件,为此在这两个目录的文件方式中都设置了粘住位。

 

:    如果我们试图设置普通文件的粘住位( S _ I S V T X ),而且又没有超级用户优先权,那么m o d e中的粘住位自动被关闭。这意味着只有超级用户才能设置普通文件的粘住位。这样做的理由是可以防止不怀好意的用户设置粘住位,并试图以此方式填满交换区(如果系统支持保存-正文特征的话)

 

 

 

 

 

 

  

 

第二节    文件操作

打开文件 OPEN()

[格式:]

 

#   include

 

int fd;

fd=open(filename,flags,perms)

filename             文件及路径名

flags            打开文件的模式    ******* 请参考3

perms          访问权限              ********可选,当与O_CREAT合用时要确定文件的权限

 

成功返回文件描述符,不成功则返回-1

UNIX进程(每个进程)最多可以同时使用20个文件描述符(0-19),其中0-2 分别为stdin,stdout,stderr,所以在进程中打开的文件由3开始。

 

[标志:]

O_RDONLYO_WRONLYO_RDWR的取值分别为012,它们之间不能用OR的方法联合使用。下面再介绍一些标志值:

l         O_CREAT:当文件不存在时,将建立该文件,此时会用到open的第三个参数。

l         O_EXCL:当该标志与O_CREAT一起使用,且如果文件存在,这次open系统调用将失败。(不能确定文件是否存在,而且要在文件不在时建立此文件,则要此参数与O_CREAT合用)

注意:NFS文件系统上用O_EXCL程序会产生问题,因为程序执行时依赖的锁可能将引起竞争。

 

l         O_NOCTTY:当文件名(可以包含路径,即第一个参数pathname)指向一个终端设备,它将不再是进程控制的终端,即使该进程没有一个终端设备。

l         O_TRUNC:如果文件存在,则该文件将被截断,即长度截断为0。(就是文件被清空)注意,文件没有以写方式打开也可以截断;截断后文件的属主和属性不变。

l         O_APPEND:文件以追加的方式打开,每次进行写操作时,文件指针都会被放置到文件末尾。注意,O_APPENDNFS(网络文件系统)上可能会导致异常,当多于一个进程对该文件同时追加数据时,可能得到不可预测的结果。这是因为NFS并不支持对一个文件的追加,所以这就需要客户端核心来模拟它,但必须有锁的支持,才能很好地解决竞争。

l         O_NONBLOCKO_NDELAY:当文件以非阻塞方式打开后,对于open及随后的对该文件的文件操作,都会及时返回,而无需进程等待。这对于普通文件和目录文件没有作用,但对于管道等进程间通信的操作很有用。

 

较早的系统V版本引入了O _ N D E L AY(不延迟)标志,它与O _ N O N B L O C K

(不阻塞)选择项类似,但在读操作的返回值中具有两义性。如果不能从管道、

F I F O或设备读得数据,则不延迟选择项使r e a d返回0,这与表示已读到文件尾端的

返回值0相冲突。S V R 4仍支持这种语义的不延迟选择项,但是新的应用程序应当

使用不阻塞选择项以代替之。

 

l         O_SYNCO_FSYNC:文件以同步I/O的方式打开。任何的写操作都会使得进程被阻塞,直到物理的写动作完成为止。

l         O_WSYNC,有的系统没有该标志。

 

读写文件 read,write

[格式:]

 

  read(int fd,char *buf,int buflen)

write(int fd,char *buf,int buflen)

 

[说明:]

 

ü         read,write 执行失败返回-1,而 read在碰到EOF时返回0

ü         如果write写入对象是文本文件时,在遇到换行符时,它会输出换行符和回车符(0D0A

read刚好反,它将换行符和回车符转换为换行符。

 

:read,write在对管道作用,其方式和作用于一般文件不同,物别是配O_NDELAY标识后。

       r e a d成功,则返回读到的字节数。如已到达文件的尾端,则返回0

有多种情况可使实际读到的字节数少于要求读字节数:

.      读普通文件时,在读到要求字节数之前已到达了文件尾端。例如,若在到达文件尾端之

前还有3 0个字节,而要求读1 0 0个字节,则r e a d返回3 0,下一次再调用r e a d时,它将返回0 (文件尾端)

l         当从终端设备读时,通常一次最多读一行。

l          当从网络读时,网络中的缓冲机构可能造成返回值小于所要求读的字节数。

l          某些面向记录的设备,例如磁带,一次最多返回一个记录。

 

LSEEK( )函数

[格式:]

可以调用l s e e k显式地定位一个打开文件。

 

#include

#include

 

off_t   lseek(int f i l e d e s, off_t  o f f s e t, int w h e n c e) ;

 

返回:若成功为新的文件位移,若出错为- 1

 

对参数offset (偏移量)的解释与参数w h e n c e的值有关。

 

         w h e n c eS E E K _ S E T,则将该文件的位移量设置为距文件开始offset 个字节。

w h e n c eS E E K _ C U R,则将该文件的位移量设置为其当前值offset, offset可为正或负。

w h e n c eS E E K _ E N D,则将该文件的位移量设置为文件长度(文件尾)offset, offset可为正或负。

l s e e k成功执行,则返回新的文件位移量,为此可以用下列方式确定一个打开文件的当前

位移量:

 

off_t currpos;

currpos = lseek(fd, 0, SEEK_CUR);

 

这种方法也可用来确定所涉及的文件是否可以设置位移量。如果文件描述符引用的是一个管道或F I F O,则l s e e k返回-1,并将e r r n o设置为E P I P E

 

!       EXAMPLE:

 

# include

# include

# include

 

main()

{

  /***省略文件打开等操作*******/

  if(lseek(fd,0,SEEK_CUR)==-1) {    

         fprintf(stderr,”can’t lseek\n”)

         close(fd);

  }else{

         fprintf(stderr,”lseek OK\n”);

         /*处理文件*/

  }

}

 

 

 

通常,文件的当前位移量应当是一个非负整数,但是,某些设备也可能允许负的位移量

但对于普通文件,则其位移量必须是非负值。因为位移量可能是负值,所以在比较l s e e k的返回值时应当谨慎,不要测试它是否小于0,而要测试它是否等于-1

 

 

        

创建链接link()

[格式:]

 

int  link(char *oldlink,char *newlink)

char *oldlink

char *newlink

 

  删除文件链接unlink()

  int   unlink(char * filename)

 

  [说明]

unlink()把文件filename链接数目减1,如果执行减1操作后文件的链接数目为零该文件将被删除。  执行成功返回值是0,否则返回值是-1.

 

动态修攺文件属性 fcntl()

[格式]

# include

# include

 

int   fcntl(int fd,int cmd,int oparg)

 

[说明]

fcntl()函数调用可以修改正在使用的文件的属性,这些属性包括文件描述字,文件状态,close-on-exec标志等。

fd                 文件描述字

CMD        fcntl()命令

 

 

复制一个现存的描述符(c m dF _ D U P F D)。

获得/设置文件描述符标记(c m d = F _ G E T F DF _ S E T F D)。

获得/设置文件状态标志(c m d = F _ G E T F LF _ S E T F L)。

获得/设置异步I / O有权(c m d = F _ G E TO W NF _ S E TO W N)。

获得/设置记录锁(c m d = F _ G E T L K , F _ S E T L KF _ S E T L K W)。

 

 

CMD 共有五类格式:

 

 

 

 

F_DUPFD

使用该命令时,fcntl()的返回值为一个文件描述符,该文件描述符是通过复制参数FD而得到的.这个命令的作用与DUP类似

 

F_GETFD

返回文件的”close-on-exec”标志,如果这个标志被置为”on”,在执行exec()命令之后,文件描述字fd所指向的文件会被自动关閉,否则,文件处于继续打开的状态

F_SETFD

设定”close-on-exec”标志

F_GETFL

返回文件描述符字fd所指向文件的状态标志.例如:是否为只读,是否可写等等.

F_SETFL

设定参数oparg中的标志,标志包括O_NDELAY或者O_APPEND

 

 

!       EXAMPLE:

 

# include

# include

 

# DEFINE DUMVY 0

 

main()

{

  int fd,flags,num;

  char name[10];

  if((fd=open(“/tmp/filename”,O_RDONLY))==-1){

         fprintf(stderr,”open file error\n”);

         exit (-1);

  }

  sleep(5);

  flags=fcntl(fd,F_GETFL,DUMVY);

  flags&=O_RDWR;       

  fcntl(fd,F_SETFL,flags);

  exit(0);

}

 

 

另一个例子

 

 

struct  flock dataflock;

 

dataflock.l_type=F_WRLCK;

dataflock.l_start=0;

dataflock.l_whence=SEEK_SET;

dataflock.l_len=0;

if(fcntl(fd,F_SETKW,&dataflock)<0){

  ……

 

 

}

 

/**** flock   in  fcntl.h***********

 

struct flock{

   short         l_type;

   short         l_whence;

   off_t        l_start;

   off_t l_len;

#if       defined(_M_I386)

   short          l_sysid;

   pid_t          l_pid;

#else

   short          l_pid;

   short          l_sysid;

  

# endif

}

 

 

# define                F_RDLCK          01     /*Read lock*/

# define                F_WRLCK         02     /*Write lock*/

# define                F_UNLCK         03     /*Remove LOCK(S)*/

 

阅读(563) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~