免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1232 | 回复: 0
打印 上一主题 下一主题

fcntl文件描述词操作 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-06-24 15:15 |只看该作者 |倒序浏览

相关函数:open, flock
表头文件:#include  
               #include  
定义函数:int  fcntl(int fd,  int  cmd)
               int  fcntl(int fd,  int cmd,  long  arg)
               int  fcntl(int fd,  int cmd,  struct  flock *lock)
函数说明:fcntl() 用来操作文件描述词的一些特性。参数代表欲设置的文件描述词, 参数cmd代表欲操作的指令,有下列几种情况
F_DUPFD             用来查找大于或等于参数arg的最小且仍未使用的文件描述词,并且复制参数fd的文件描述词。执行成功则返回新复制的文件描述词。
F_GETFD             取得close-on-exec旗标。若此旗标的FD_CLOSEXEC位为0,代表在调用exec()相关函数时文件将不会关闭
F_SETFD             设置close-on-exec旗标。该旗标以参数arg的FD_CLOSEXEC位决定
F_GETFL              取得文件描述词状态旗标, 此旗标为open()的参数flags
F_SETFL              设置文件描述词状态旗标,参数arg为新旗标,但只允许O_APPEND、O_NONBLOCK和O_ASYNC位的改变,其他位的改变将不受影响
F_GETLK              取得文件锁定的状态
F_SETLK              设置文件锁定的状态。此时flock结构的l_type值必须是F_FDLCK、F_WRLCK或F_UNLCK。如果无法建立锁定,则返回-1,错误代码为EACCESS或EAGAIN
F_SETLKW            F_SETLK作用相同,但无法建立锁定时,此调用会一直等到锁定动作成功为止。若在等待锁定的过程中被信号中断地,会立即返回-1,错误代码为EINTR。 参数lock指针为flock结构指针,定义如下
struct  flock
{
      short   int  l_type;              /*锁定的型态*/
      short   int  l_whence;         /*决定l_start位置*/
      off_t         l_start;             /*锁定区域的开头位置*/
      off_t         l_len;               /*锁定区域的大小*/
      off_t         l_pid;               /*锁定动作的进程*/
};
l_type有三种形态:
        F_RDLCK                         建立一个供读取用的锁定
        F_WRLCK                        建立一个供写入用的锁定
        F_UNLCK                         删除之前建立的锁定
        
l_whence有三种方式
        SEEK_SET                      以文件开头为锁定的起始位置
        SEEK_CUR                      以目前文件读写位置为锁定的起始位置
        SEEK_END                      以文件结尾为锁定的起始位置
返回值 : 成功则返回0,  错误返回-1, 错误原因存于errno


UNIX环境高级编程(第2版)
fcntl函数
fcntl函数可以改变已打开的文件的性质。


在本节的各实例中,第三个参数总是一个整数,与上面所示函数原型中的注释部分相对应。但是在14.3节说明记录锁时,第三个参数则是指向一个结构的指针。
fcntl函数有5种功能:
(1) 复制一个现有的描述符(cmd=F_DUPFD)。
(2) 获得/设置文件描述符标记(cmd = F_GETFD或F_SETFD)。
(3) 获得/设置文件状态标志(cmd = F_GETFL或F_SETFL)。
(4) 获得/设置异步I/O所有权(cmd = F_GETOWN或F_SETOWN)。
(5) 获得/设置记录锁(cmd = F_GETLK、F_SETLK或F_SETLKW)。
我们先说明这10种cmd值中的前7种(14.3节说明后3种,它们都与记录锁有关)。我们将涉及与进程表项中各文件描述符相关联的文件描述符标志,以及每个文件表项中的文件状态标志(见图3-1)。
F_DUPFD:复制文件描述符filedes。新文件描述符作为函数值返回。它是尚未打开的各描述符中大于或等于第三个参数值(取为整型值)中各值的最小值。新描述符与filedes共享同一文件表项(见图3-3)。但是,新描述符有它自己的一套文件描述符标志,其FD_CLOEXEC文件描述符标志被清除(这表示该描述符在通过一个exec时仍保持有效,我们将在第8章对此进行讨论)。
F_GETFD:对应于filedes的文件描述符标志作为函数值返回。当前只定义了一个文件描述符标志FD_CLOEXEC。
F_SETFD:对于filedes设置文件描述符标志。新标志值按第三个参数(取为整型值)设置。
应当了解很多现有的涉及文件描述符标志的程序并不使用常量FD_CLOEXEC,而是将此标志设置为0(系统默认,在exec时不关闭)或1(在exec时关闭)。
F_GETFL:对应于filedes的文件状态标志作为函数值返回。在说明open函数时,已说明了文件状态标志。它们列于表3-3中。

不幸的是,三个访问方式标志(O_RDONLY、O_WRONLY以及O_RDWR)并
不各占1位(正如前述,这三种标志的值分别是0、1和2,由于历史原因。
这三种值互斥—一个文件只能有这三种值之一)。因此首先必须用屏蔽字
O_ACCMODE取得访问模式位,然后将结果与这三种值中的任一种作比较。
F_SETFL 将文件状态标志设置为第三个参数的值(取为整型值)。可以更改的几个标志是:O_APPEND、O_NONBLOCK、O_SYNC、O_DSYNC、O_RSYNC、 O_FSYNC和O_ASYNC。
F_GETOWN     取当前接收SIGIO和SIGURG信号的进程ID或进程组ID。14.6.2节将论述这两种异步I/O信号。
F_SETOWN      设置接收SIGIO和SIGURG信号的进程ID或进程组ID。正的arg 指定一个进程ID,负的arg 表示等于arg 绝对值的一个进程组ID。
fcntl的返回值与命令有关。如果出错,所有命令都返回-1,如果成功则返回某个其他值。下列四个命令有特定返回值:F_DUPFD、F_GETFD、F_GETFL以及F_GETOWN。第一个返回新的文件描述符,接下来的两个返回相应标志,最后一个返回一个正的进程ID或负的进程组ID。
实例
程序清单3-4中的程序的第一个参数指定文件描述符,并对于该描述符打印其所选择的文件标志说明。

注意,我们使用了功能测试宏_POSIX_C_SOURCE,并且条件编译了POSIX.1中没有定义的文件访问标志。下面显示了从bash(Bourne-again shell)调用该程序时的几种情况。当使用不同shell时,结果会发生变化。



子句5temp.foo表示在文件描述符5上打开文件temp.foo以供读和写。
实例
在修改文件描述符标志或文件状态标志时必须谨慎,先要取得现有的标志值,然后根据需要修改它,最后设置新标志值。不能只是执行F_SETFD或F_SETFL命令,这样会关闭以前设置的标志位。
程序清单3-5显示了一个对一个文件描述符设置一个或多个文件状态标志的函数。


就构成另一个函数,我们称其为clr_fl,并将在后面某个例子中用到它。此语句使当前文件状态标志值val与flags的补码进行逻辑“与”运算。
如果在程序清单3-5的开始处,加上下面一行以调用set_fl,则打开了同步写标志。


这就使每次write都要等待,直至数据已写到磁盘上再返回。在UNIX系统中,通常write只是将数据排入队列,而实际的写磁盘操作则可能在以后的某个时刻进行。数据库系统很可能需要使用O_SYNC,这样一来,当它从write返回时就知道数据已确实写到了磁盘上,以免在系统崩溃时产生数据丢失。
程序运行时,设置O_SYNC标志会增加时钟时间。为了测试这一点,运行程序清单3-3,它从一个磁盘文件中将98.5 MB字节的数据复制到另一个文件。然后,在此程序中设置O_SYNC标志,使其完成上述同样的工作,以便将两者的结果进行比较。在使用ext2文件系统的Linux系统上执行上述操作,得到的结果见表3-4。
表3-4中的6行都是在BUFFSIZE为4096的情况下测量得到的。表3-2中的结果所测量的情况是读一个磁盘文件,然后写到/dev/null,所以没有磁盘输出。表3-4中的第2行对应于读一个磁盘文件,然后写到另一个磁盘文件中。这就是为什么表3-4中第1、2行有差别的原因。在写磁盘文件时,系统时间增加了,其原因是内核需要从进程中复制数据,并将数据排入队列以便由磁盘驱动器将其写到磁盘上。当写至磁盘文件时,我们期望时钟时间也会增加,但在本测试中,它并未显著增加,这表明写操作将数据写到了系统高速缓存中,我们并没有测量将数据写到磁盘上的开销。

当支持同步写时,系统时间和时钟时间应当会显著增加。从第3行可见,同步写所用的时间与延迟写所用的时间几乎相同。这意味着Linux ext2文件系统并未真正实现O_SYNC标志功能。第6行的时间值支持了我们的这种怀疑,其中显示,实施同步写,然后跟随fsync调用,这一操作序列所用的时间与写文件(未设置同步标志),然后接着执行fsync调用这一序列所用的时间(第5行)几乎相同。在同步写一个文件后,我们期望fsync调用不会产生影响。
表3-5显示了在Mac OS X 10.3上运行同样的测试所得到的计时结果。注意该计时结果与我们的期望相符:同步写较延迟写所消耗的时间增加了很多,而且在同步写后再调用函数fsync 并不会产生测量上的显著差别。还要引起注意的是,在延迟写后增加一个fsync函数调用也不产生可测量的差别。其原因很可能是,当写新数据到某个文件中时,操作系统将以前写的数据冲洗到了磁盘上,所以在调用函数fsync时几乎就没有什么工作要做了。

比较fsync和fdatasync与O_SYNC标志,fsync和fdatasync在我们需要时更新文件内容,O_SYNC标志则在我们每次写至文件时更新文件内容。
在本例中,我们看到了fcntl的必要性。我们的程序在一个描述符(标准输出)上进行操作,但是根本不知道由shell打开的相应文件的文件名。因为这是shell打开的,于是不能在打开时,按我们的要求设置O_SYNC标志。fcntl则允许仅知道打开文件描述符时可以修改其性质。在说明非阻塞管道时(15.2节),我们还将了解到,由于我们对管道所具有的知识只是其描述符,所以也需要使用fcntl的功能。



本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/71872/showart_1010178.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP