fcntl函数可以改变已打开的文件的性质。

#include <fcntl.h>
int fcntl( int filedes, int cmd, ... /* int arg */ );
返回值:若成功则依赖于cmd,若出错则返回-

在本节的各实例中,第三个参数总是一个整数,与上面所示函数原型中的注释部分相对应。但是在说明记录锁时,第三个参数则是指向一个结构的指针。

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种(后3种,在谈记录锁时说明)。我们将涉及与进程表项中各文件描述符相关联的文件描述符标志,以及每个文件表项中的文件状态标志。

F_DUPFD         复制文件描述符filedes。新文件描述符作为函数值返回。它是尚未打开的各描述符中大于或等于第三个参数值(取为整型值)中各值的最小值。新描述符与filedes共享同一文件表项。但是,新描述符有它自己的一套文件描述符标志,其FD_CLOEXEC文件描述符标志被清除(这表示该描述符在通过一个exec时仍保持有效)。

F_GETFD         对应于filedes的文件描述符标志作为函数值返回。当前只定义了一个文件描述符标志FD_CLOEXEC。

F_SETFD         对于filedes设置文件描述符标志。新标志值按第三个参数(取为整型值)设置。

注:应当了解很多现有的涉及文件描述符标志的程序并不使用常量FD_CLOEXEC,而是将此标志设置为0(系统默认,在exec时不关闭)或1(在exec时关闭)。

F_GETFL         对应于filedes的文件状态标志作为函数值返回。文件状态标志如下表3-3:(表3-3中的各个标志,除了三个访问方式标志(O_RDONLY、O_WRONLY以及O_RDWR)不各占一位,其他标志分别占文件状态标志的一个bit位)

不幸的是,三个访问方式标志(O_RDONLY、O_WRONLY以及O_RDWR)并不各占1位(由于历史原因,这三种标志的值分别是0、1和2。这三个访问方式标志用文件状态标志的后两位表示,00:O_RDONLY,01:O_WRONLY,10:O_RDWR。这三种值互斥——一个文件只能有这三种值之一)。因此首先必须用屏蔽字O_ACCMODE(0x0003)取得访问模式位(文件状态标志的后两位),然后将结果与这三种值的任一种做比较。

F_SETFL         将文件状态标志设置为第三个参数的值(取为整型值)。可以更改的几个标志是:O_APPEND、O_NONBLOCK、O_SYNC、O_DSYNC、O_RSYNC、O_FSYNC和O_ASYNC。

F_GETOWN    取当前接受SIGIO和SIGURG信号的进程ID或进程组ID。

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 对于指定的描述符打印文件标志

[root@localhost apue]# cat prog3-.c
#include "apue.h"
#include <fcntl.h> int
main(int argc, char *argv[])
{
int val; if(argc != )
err_quit("usage: prog3-4 <descriptor#>"); if((val = fcntl(atoi(argv[]), F_GETFL, )) < )
err_sys("fcntl error for fd %d", atoi(argv[])); switch(val & O_ACCMODE)
{
case O_RDONLY:
printf("read only");
break;
case O_WRONLY:
printf("write only");
break;
case O_RDWR:
printf("read write");
break;
default:
err_dump("unknown access mode");
} if(val & O_APPEND)
printf(", append");
if(val & O_NONBLOCK)
printf(", nonblocking");
#if defined(O_SYNC)
if(val & O_SYNC)
printf(", synchronous writes");
#endif
#if !defined(_POSIX_C_SOURCE) && defined(O_FSYNC)
if(val & O_FSYNC)
printf(", synchronous writes");
#endif
putchar('\n');
exit();
}

注意,我们使用了功能测试宏_POSIX_C_SOURCE,并且条件编译了POSIX.1中没有定义的文件访问标志。

在修改文件描述符标志或文件状态标志时必须谨慎,先要取得现有的标志值,然后根据需要修改它,最后设置新标志值。不能只是执行F_SETFD或F_SETFL命令,这样会关闭以前设置的标志位。

程序清单3-5 对一个文件描述符打开一个或多个文件状态标志

[root@localhost apue]# cat prog3-.c
#include "apue.h"
#include <fcntl.h> void
set_fl(int fd, int flags) /* flags are file status flags to turn to */
{
int val; if((val = fcntl(fd, F_GETFL, )) < )
err_sys("fcntl F_GETFL error"); val |= flags; /* turn on flags */ if(fcntl(fd, F_SETFL, val) < )
err_sys("fcntl F_SETFL error");
}

如果将中间的一条语句改为:

val &= ~flags;    /* turn flags off */

就构成另一个函数,我们称其为clr_fl。

比较fsync和fdatasync与O_SYNC标志,fsync和fdatasync在我们需要时更新文件内容,O_SYNC标志则在我们每次写至文件时更新文件内容。

fcntl的必要性:我们的程序在一个描述符(标准输出)上进行操作,但是根本不知道由shell打开的相应的文件名。因为这是shell打开的,于是不能在打开时,按我们的要求设置O_SYNC标志。fcntl则允许仅知道打开文件描述符时可以修改其性质。

本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/

文件I/O之fcntl函数的更多相关文章

  1. Linux系统编程(3)——文件与IO之fcntl函数

    linux文件I/O用:open.read.write.lseek以及close函数实现了文件的打开.读写等基本操作.fcntl函数可以根据文件描述词来操作文件. 用法: int fcntl(int ...

  2. UNIX环境编程学习笔记(5)——文件I/O之fcntl函数访问已打开文件的性质

    lienhua342014-08-29 fcntl 函数可以改变已打开的文件的性质. #include <fcntl.h> int fcntl(int filedes, int cmd, ...

  3. fcntl函数的用法总结

    fcntl系统调用可以用来对已打开的文件描述符进行各种控制操作以改变已打开文件的的各种属性 函数原型:   #include<unistd.h> #include<fcntl.h&g ...

  4. fcntl 函数与文件锁

    一.fcntl函数 功能:操纵文件描述符,改变已打开的文件的属性 int fcntl(int fd, int cmd, ... /* arg */ ); cmd的取值可以如下: 复制文件描述符 F_D ...

  5. Linux文件(区域)锁函数 -- open()、fcntl()

    一.什么是文件锁定 对于锁这个字,大家一定不会陌生,因为我们生活中就存在着大量的锁,它们各个方面发挥着它的作用,现在世界中的锁的功能都可归结为一句话,就是阻止某些人做某些事,例如,门锁就是阻止除了屋主 ...

  6. 六、文件IO——fcntl 函数 和 ioctl 函数

    6.1 fcntl 函数 6.1.1 函数介绍 #include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd ...

  7. 第七篇:使用 fcntl 函数 获取,设置文件的状态标志

    前言 当打开一个文件的时候,我们需要指定打开文件的模式( 只读,只写等 ).那么在程序中如何获取,修改这个文件的状态标志呢? 本文将告诉你如何用 fcntl函数 获取指定文件的状态标志. 解决思路 1 ...

  8. 使用 fcntl 函数 获取,设置文件的状态标志

    前言 当打开一个文件的时候,我们需要指定打开文件的模式( 只读,只写等 ).那么在程序中如何获取,修改这个文件的状态标志呢?本文将告诉你如何用 fcntl函数 获取指定文件的状态标志. 解决思路 1. ...

  9. fcntl函数用法——操纵文件描述符状态

    fcntl函数:操纵文件描述符,改变已经打开的文件的属性int fcntl(int fd, int cmd, ... //arg  );cmd选项:一.复制文件描述符:F_DUPFD二.更改设置文件描 ...

随机推荐

  1. 在Azure HDInsight HBase集群中使用Thrift接口

    Sun wei  Wed, Feb 25 2015 2:17 AM Apache Thrift 是一种可扩展的跨语言服务接口,可以通过内置的代码生成引擎帮助创建跨语言服务类库,Apache HBase ...

  2. FirstOrDefault

    FirstOrDefault:取序列中满足条件的第一个元素,如果没有元素满足条件,则返回默认值(对于可以为null的对象,默认值为null,对于不能为null的对象,如int,默认值为0)

  3. 将android中的sample例子到eclipse中

    SDK中带有很多的例子,那么我们怎么样导入到eclipse中呢?方法很简单,如下: 1. 新建android工程,选择Create project from existing sample, 2. 选 ...

  4. 那些年一起踩过的坑 — java 自动装箱拆箱问题

    坑在哪里?   我们都知道Java的八种基本数据类型:int, short, long, double, byte, char, float, boolean   分别有各自对应的包装类型:Integ ...

  5. RhinoMocks简单范例

    using System; namespace MockTest { public interface IBBB { int Number { get; } int Compute(int j); i ...

  6. MSP430F149流水灯闪烁以及数码管的显示

    今天下午写了一个流水灯闪烁的实验,总的来说,不难,因为这块板子集合的电路图没有上一块那么复杂,所以总的来说,还是比较顺手,开始的时候,出现流水灯没有流转的现象,原来是没有加入延时函数,后来经过调整,结 ...

  7. 【原】Storm调度器

    Storm入门教程 1. Storm基础 Storm Storm主要特点 Storm基本概念 Storm调度器 Pluggable scheduler(可插拔调度器) Isolation schedu ...

  8. Ubuntu 设置简单密码,复杂度太高

    Ubuntu 中创建的用户密码复杂度很高,如果想设置1234 ,或者与账户名相同的密码时,SystemSetting 中是不可以设置的. 可以通过简单的命令来设置 其中 anyongfei 是账户名 ...

  9. NOIP2012 同余方程

    1同余方程 题目描述 求关于 x 的同余方程 ax ≡ 1 (mod b)的最小正整数解. 输入输出格式 输入格式: 输入只有一行,包含两个正整数 a, b,用一个空格隔开. 输出格式: 输出只有一行 ...

  10. -lrt

    在编写pthread有关的程序时,编译时老是报"undefined reference to `pthread_create'"的错误,原因是没有链接pthread相关的库,gcc ...