文件I/O之fcntl函数
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函数的更多相关文章
- Linux系统编程(3)——文件与IO之fcntl函数
linux文件I/O用:open.read.write.lseek以及close函数实现了文件的打开.读写等基本操作.fcntl函数可以根据文件描述词来操作文件. 用法: int fcntl(int ...
- UNIX环境编程学习笔记(5)——文件I/O之fcntl函数访问已打开文件的性质
lienhua342014-08-29 fcntl 函数可以改变已打开的文件的性质. #include <fcntl.h> int fcntl(int filedes, int cmd, ...
- fcntl函数的用法总结
fcntl系统调用可以用来对已打开的文件描述符进行各种控制操作以改变已打开文件的的各种属性 函数原型: #include<unistd.h> #include<fcntl.h&g ...
- fcntl 函数与文件锁
一.fcntl函数 功能:操纵文件描述符,改变已打开的文件的属性 int fcntl(int fd, int cmd, ... /* arg */ ); cmd的取值可以如下: 复制文件描述符 F_D ...
- Linux文件(区域)锁函数 -- open()、fcntl()
一.什么是文件锁定 对于锁这个字,大家一定不会陌生,因为我们生活中就存在着大量的锁,它们各个方面发挥着它的作用,现在世界中的锁的功能都可归结为一句话,就是阻止某些人做某些事,例如,门锁就是阻止除了屋主 ...
- 六、文件IO——fcntl 函数 和 ioctl 函数
6.1 fcntl 函数 6.1.1 函数介绍 #include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd ...
- 第七篇:使用 fcntl 函数 获取,设置文件的状态标志
前言 当打开一个文件的时候,我们需要指定打开文件的模式( 只读,只写等 ).那么在程序中如何获取,修改这个文件的状态标志呢? 本文将告诉你如何用 fcntl函数 获取指定文件的状态标志. 解决思路 1 ...
- 使用 fcntl 函数 获取,设置文件的状态标志
前言 当打开一个文件的时候,我们需要指定打开文件的模式( 只读,只写等 ).那么在程序中如何获取,修改这个文件的状态标志呢?本文将告诉你如何用 fcntl函数 获取指定文件的状态标志. 解决思路 1. ...
- fcntl函数用法——操纵文件描述符状态
fcntl函数:操纵文件描述符,改变已经打开的文件的属性int fcntl(int fd, int cmd, ... //arg );cmd选项:一.复制文件描述符:F_DUPFD二.更改设置文件描 ...
随机推荐
- C# 向共享文件夹上传及下载文件
//第一步建立共享链接 public static bool connectState(string path, string userName, string passWord) { bool Fl ...
- 如何从Linux源码获知版本信息
/*************************************************************************** * 如何从Linux源码获知版本信息 * 声明 ...
- centos nginx 多端口配置过程记录
1. 编辑 /usr/local/nginx/vhosts/ 在此目录下增加一文件,如;ci.ainux.com,或复制一个文件 修改其中的端口和目录,更改log_format 名称 重启nginx ...
- 【转】JAVA中的反射机制
反射,当时经常听他们说,自己也看过一些资料,也可能在设计模式中使用过,但是感觉对它没有一个较深入的了解,这次重新学习了一下,感觉还行吧! 一,先看一下反射的概念: 主要是指程序可以访问,检测和修改它本 ...
- 【转】Eclipse配置Struts2问题:ClassNotFoundException: org...dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
我的解决方案 一开始,我是依照某本教材,配置了User Libraries(名为struts-2.2.3, 可供多个项目多次使用), 然后直接把struts-2.2.3引入过来(这个包不会真正的放在项 ...
- Live555研究之二Sleep实现
Live555通过一个while循环来不断读取socket,判断是否有连接进来,但是Live555并没有使用Sleep函数来让线程休眠多少毫秒来降低CPU占用率.Live555是通过select函数来 ...
- HDU 5699 货物运输 二分判定
转自:http://blog.csdn.net/jtjy568805874/article/details/51480479 #include <cstdio> #include < ...
- Selenium 使用方法小结
基本介绍: Selenium工具专门为WEB应用程序编写的一个验收测试工具. Selenium的核心:browser bot,是用JAVASCRIPT编写的. Selenium工具有4种:Sele ...
- 介绍并扩展Fitnesse的测试模块化机制:ScenarioTable
摘要:在验收测试框架Fitneese中,使用Scenario可以把最常用的测试步骤封装起来,从而达到模块化定义Fitnesse测试用例的能力.但Scenario仅限于封装Script测试步骤,Scri ...
- Codeforces Round #359 (Div. 1)
A http://codeforces.com/contest/685/standings 题意:给你n和m,找出(a,b)的对数,其中a满足要求:0<=a<n,a的7进制的位数和n-1的 ...