引言:
对于一个普通的文件,我们可以想到的对它的操作有,读取文件的内容、写数据到文件中,这些都是前面提到的read、write函数的作用。除此之外,还可以获取文件的其他性质,并对这些性质进行修改,比如文件的描述符、文件描述符标记、文件状态标志等等。这些对文件性质的修改就由fcntl函数完成。
函数介绍:
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );
参数:
fd:欲设置的文件描述符。
cmd:打算对文件进行操作的指令。
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)。
详细说明:
1、F_DUPFD
复制文件描述符fd。新文件描述符作为函数值返回。它是尚未打开的个描述符中大于或等于第三个参数(取为整数值)中各值的最小值。新描述符与fd共享同一文件表项。但是新描述符有它自己的一套文件描述符标志,其FD_CLOEXEC文件描述符标志被清除。其实,此时fcntl函数的功能与dup2的功能类似。
/* * File Name : fupfd.c * Author : libing * Mail : libing1209@126.com * Function : just for a test */ #include <stdio.h> #include <stdlib.h> #include <fcntl.h> int main(void) { int fd, newfd; fd = open("test.txt", O_RDWR); if(fd == -1){ printf("can‘t open test.txt.\n"); exit(1); } //使用fcntl函数复制文件描述符 newfd = fcntl(fd, F_DUPFD, 5); printf("newfd = %d.\n", newfd); return 0; }编译测试:
编译程序: gcc fupfd.c 执行程序: ./a.out 测试结果: newfd = 5.2、F_GETFD:对应于fd的文件描述符标志作为函数返回。当前仅定义了一个文件描述符标志FD_CLOEXEC。
F_SETFD:对于fd设置文件描述符标志。新标志按第三个参数设置。
3、F_GETFL:对于fd的文件状态标志作为函数值返回。文件状态标志有O_RDONLY、O_WRONLY、O_RDWR等。因为三个访问方式标志并不各占1位。因此首先必须用屏蔽字O_ACCMODE取得访问模式位,然后将结果与这三种值的任一种做比较。
F_SETFL:将文件状态标志设置为第三个参数的值。可以更改的几个标志是:O_APPEND、O_NONBLOCK、O_SYNC、O_DSYNC、O_RSYNC等。
#include <fcntl.h> #include <stdio.h> #include <stdlib.h> int main(void) { int val; int fd; fd = open("test.txt", O_RDWR); //fcntl函数获得文件状态标志 if((val = fcntl(fd, F_GETFL, 0)) < 0) printf("fcntl failed.\n"); switch(val & O_ACCMODE){ case O_RDONLY: printf("read only"); break; case O_WRONLY: printf("write only"); break; case O_RDWR: printf("read and write"); break; default: printf("unknown access mode"); } if(val & O_APPEND) printf("append"); if(val & O_NONBLOCK) printf("nonblock"); putchar(‘\n‘); exit(0); }编译测试结果:
编译程序: gcc fcntl.c 执行程序: ./a.out 结果显示: read and write4、F_GETOWN:取当前接收SIGIO和SIGURG信号的进程ID或进程组ID。
F_GETOWN:设置接收SIGIO和SIGURG信号的进程ID或进程组ID。