写这篇文正主要是为了介绍下fcntl,并将我自己在学习过程中的一些理解写下来,不一定那么官方,也有错误,希望指正,共同进步~

fcntl:

  一个修改一打开文件的性质的函数。基本的格式是 int fcntl(int filedes, int cmd, ...) 包含在头文件<fcntl.h>中。 参数三是看cmd这个参数的设置。函数返回一个文件描述符。fcntl有五种功能。下面介绍其中的三种功能

  1、复制一个现有的描述符(cmd = F_DUPFD)

  2、获得/设置文件描述符标记(cmd = F_GETFD或是cmd = F_SETFD)

  3、获得/设置文件状态标志(cmd = F_GETFL或是cmd = F_SETFL)

F_DUPFD:

  简单的说下把,在我的上一篇博客里面有提到过,复制文件描述符filedes,新的文件描述符作为返回值返回。这个返回值是尚未打开的描述符中大于或是等于你所设置的那个第三个参数的。

  例如: newfd = fcntl(fd, F_DUPFD,fd1),就是将fd复制给描述符的值为fd1的上。和dup2一样的。这边是对dup过程的一个解释把。

F_GETFD和F_SETFD:

  这两个也是比较简单的,F_GETFD将 对应于filedes的文件描述符标志作为函数值返回。很好理解的,就是返回一个文件描述符。相当于查看下,不需要第三个参数

   F_SETFD 将filedes所对应的文件描述符,按照第三个参数的值设定。

文件描述符标志和文件状态标志:

  这两个容易混淆。文件描述符标志可以看作是文件描述符里面的一项,文件描述符包含两个,一个就是fd标志,还有一个就是文件指针。 文件指针指向文件状态标志,文件状态标志里面保存了文件的读、写、添写、以及同步和非阻塞等。

  所以着两个是不同的,文件状态标志更加复杂一点。下面这个图可以帮助我们理解(来自Unix环境高级编程)

这样看上去是不是感觉没有那么混淆了?很清晰的就解释了二者的区别。

F_GETFL:

  对应的filedes的文件状态标志作为函数值返回。里面的参数包含open函数里面的参数 如:O_RDWR O_RDONLY O_WRONLY O_APPEND O_NONBLOCK O_SYNC 等等,值得注意的是 在open里面有的参数如(O_TRUNC O_EXCL O_CREAT等,这些是不在这里面的。)

有一个比较很不好的是,O_RDONLY O_WRONLY O_RDWR这三个不可以同时存在的,所以他们的三个共同占据一位,所以要想能够把这个状态更get出来,我们要和O_ACCMODE这个屏蔽字操作下,才能获得对已的状态信息。其他的各占一位。

F_SETFL:

  这边就要用到了fcntl的第三个参数了,将文件的状态标志设置为第三个参数的值。可以更改的有O_APPEND ,O_SYNC ,O_NONBLOCK, O_DSYNC, O_RSYNC, O_FSYNC 和O_ASYNC.这些都是可以设置上去的。

上面的是一些基础的知识,只是用作理解fcntl的一个基础。下面我们可以看两个例子。一个是打印出一个文件的一些状态标志。一个是设置一个或者多个文件状态标志的。

 #include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<fcntl.h>
#include<unistd.h>
#include<errno.h> int main()
{
int val;
int fd; fd = open("a.txt",O_RDWR|O_APPEND);
if(fd < )
{
fprintf(stderr,"open:%s\n",strerror(errno));
exit();
} if((val = fcntl(fd,F_GETFL,)) < )
{
fprintf(stderr,"fcntl:%s\n",strerror(errno));
exit();
}
//判断文件读写的信息
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:
printf("Can not identify the 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 printf("\n");
close(fd);
return ; }

这个程序,我是直接在程序里面打开一个文件,然后程序给出这个文件的相关标志,上面也可以看出来,我们通过F_GETFL获取到文件的状态标志,然后我们和O_ACCMODE这个屏蔽字相比较,判断出文件的读写状态。通过和不同的状态标志,不断的&操作,判断是否有这个位。然后打印下标志信息。

继续下一个程序:

 #include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<fcntl.h>
#include<unistd.h> int set_fl(int fd,int flag); int main(void)
{
int fd;
int val1;
//打开文件没有加入O_APPEND状态标志
fd = open("a.txt",O_RDWR);
if(fd < )
{
fprintf(stderr,"open:%s\n",strerror(errno));
exit();
} printf("Set status O_APPEND to the a.txt\n");
//调用set_fl函数
fd = set_fl(fd,O_APPEND); if((val1 = fcntl(fd,F_GETFL,)) < )
{
fprintf(stderr, "F_GETFL:%s\n",strerror(errno));
exit();
}
//判断有没有设置成功
if(val1 & O_APPEND)
printf("O_APPEND was be setted!\n"); return ; } int set_fl(int fd, int flag)
{
int val;
//获取到状态标志信息
if((val = fcntl(fd, F_GETFL,)) < )
{
fprintf(stderr, "fcntl F_GETFL:%s\n",strerror(errno));
exit();
}
//将指定状态标志加到状态信息中
val |= flag;
//设置状态标志信息
if(fcntl(fd,F_SETFL,val) < )
{
fprintf(stderr,"fcntl F_SETFL:%s\n",strerror(errno));
exit();
} return fd;
}

关键的是函数,set_fl() 必须先获取到位置信息,才能对其设置。这里面还有一个就是,我在main里面没有写的操作,所以对O_SYNC这类的是测试不出来状态信息,所以我在打开文件的时候没有加上O_APPEND这个参数,为的是在测试的时候能够显示出来这个状态信息。

说了这么多,fcntl有什么用,我套用书本上的话就是。我们的程序在一个描述符(标准输出)上进行操作,但不知道是由shell打开的相应文件的文件名,因为这是有shell打开的,所以不能在打开时,按我们的要求设置成O_SYNC标志,而fcntl则允许仅知道打开文件描述符时可以修改文件的性质。这句话需要多读几次才能理解是什么意思。

最后和大家共勉一下: 无他,唯手熟尔——《卖油翁》

Unix环境高级编程学习笔记——fcntl的更多相关文章

  1. Unix环境高级编程学习笔记——dup

    dup 和 dup2   dup和dup2,都是用来将一个文件描述符复制给另一个文件描述符上,这两个文件描述符都指向同一个文件状态标志上. 只是文件描述符的大小不一样,dup所执行下的复制,肯定是返回 ...

  2. UNIX环境高级编程学习笔记(十)为何 fork 函数会有两个不同的返回值【转】

    转自:http://blog.csdn.net/fool_duck/article/details/46917377 以下是基于 linux 0.11 内核的说明. 在init/main.c第138行 ...

  3. [置顶] 文件和目录(二)--unix环境高级编程读书笔记

    在linux中,文件的相关信息都记录在stat这个结构体中,文件长度是记录在stat的st_size成员中.对于普通文件,其长度可以为0,目录的长度一般为1024的倍数,这与linux文件系统中blo ...

  4. unix环境高级编程-读书笔记与习题解答-第一篇

    从这周开始逐渐的进入学习状态,每天晚上都会坚持写c程序,并且伴随对这本书的深入,希望能写出更高质量的读书笔记和程序. 本书的第一章,介绍了一些关于unix的基础知识,在这里我不想去讨论linux到底是 ...

  5. 《UNIX环境高级编程》笔记--UNIX标准化及实现

    1.UNIX标准化 1.1.ISO C 1989 年后期,C程序设计语言的ANSI(American National Standards Institute) 标准X3. 15 9-1989得到批准 ...

  6. 《UNIX环境高级编程》笔记——3.文件IO

    一.引言 说明几个I/O函数:open.read.write.lseek和close,这些函数都是不带缓冲(不带缓冲,只调用内核的一个系统调用),这些函数不输入ISO C,是POSIX的一部分: 多进 ...

  7. 《UNIX环境高级编程》笔记——2.标准和实现

    随着UNIX各种衍生版本不断发展壮大,标准化工作就十分必要.其实干啥事都是这样,玩的人多了,必须进行标准化. 一.UNIX标准 1.1 ISO C(ANSI C) ANSI:Amerocan Nato ...

  8. 《UNIX环境高级编程》笔记——1.UNIX基础知识

    这一章节侧重一些基本概念和书中用到的一些名词. 一.引言 所有的操作都提供服务,典型的服务包括:执行新程序.打开文件.读写文件.分配存储区以及获得当前时间等. 二.UNIX体系结构 其实linux常见 ...

  9. unix 环境高级编程 读书笔记与习题解答第四篇

    第一章 第六节 第一小节 这一章没有程序设计和API方面的深入学习,而是注重介绍了unix操作系统中的原始数据类型和系统原型函数,错误处理方面的知识. ____unistd.h____ 该文件包含了u ...

随机推荐

  1. A Tour of Go If with a short statement

    Like for, the if statement can start with a short statement to execute before the condition. Variabl ...

  2. poj 1149 PIGS【最大流经典建图】

    PIGS Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 18727   Accepted: 8508 Description ...

  3. 通过Response.Flush()实现IE下载失败的问题

    通过Response.Flush()实现对服务端文件的下载时,会失败,不能正常弹出IE下载框,经过测试发现需要进行如下设置后即可解决. 进入 [工具]--->[Internet选项]---> ...

  4. OceanBase里面的rowkey是什么概念,是由哪些要素构成的?

    Rowkey是OceanBase诞生之初就引入的概念,最终被确立是在OceanBase 0.3. 为了便于理解,不妨把OceanBase想象成一个Key-Value系统,Rowkey就是Key,Val ...

  5. Repository模式介绍汇总

    1.Linq To Sql中Repository模式应用场景 http://www.cnblogs.com/zhijianliutang/archive/2012/02/24/2367305.html ...

  6. Windows Server 2012 R2中的网络诊断命令

    Get-NetAdapter Get-NetIPAddress Get-NetIPConfiguration(GIP) TNC :Pinging Servers and Trace Route tnc ...

  7. 软中断&amp;tasklet&amp;工作队列

    软中断 软中断的分配时静态的(即在编译时定义),而tasklet的分配和初始化能够在执行时进行. 软中断(即便是同一种类型的软中断)能够并发地运行在多个CPU上. 因此,软中断是可重入函数并且必须明白 ...

  8. eclipse修改SVN下载的项目“>”变成“*”

    遇到过这样的问题,可能是因为下载的eclipse 的版本国过于高的原因. 一张图说明就行了. 将红色的地方打上勾就行了.

  9. Nginx 简单的负载均衡配置示例

    http://www.cnblogs.com/xiaogangqq123/archive/2011/03/02/1969006.html 在此记录下Nginx服务器nginx.conf的配置文件说明, ...

  10. EF中使用数据库的标量值函数

    参考资料:https://msdn.microsoft.com/zh-cn/library/dd456847(v=vs.110).aspx http://stackoverflow.com/quest ...