写这篇文正主要是为了介绍下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. SqlServer定时跑一段SQL语句

    1.请把这段SQL语句写成一个存储过程,然后需要在B上面开启 SQL Server Agent服务,如下图: 2.开启完之后,打开数据库管理工具,然后依下图所示,展开“SQL Server Agent ...

  2. PC-如何提高计算机的启动和关机的速度?

    如何提高计算机的启动和关机的速度? 一.bios的优化设置 在bios设置的首页我们进入"advanced bios features"选项,将光标移到"frist bo ...

  3. A Plain English Guide to JavaScript Prototypes

    When I first started learning about JavaScript object model my reaction was of horror and disbelief. ...

  4. 辗转相除法求最大公约数和最小公倍数【gcd】

    要求最小公倍数可先求出最大公约数 设要求两个数a,b的最大公约数 伪代码: int yushu,a,b: while(b不等于0) { yushu=a对b求余 b的值赋给a yushu的值赋给b } ...

  5. C#和C++中的float类型

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:C#和C++中的float类型.

  6. ASP.NET用HttpListener实现文件断点续传

    本文转载:http://www.cnblogs.com/TianFang/archive/2007/01/03/610739.html 断点续传的原理很简单,就是在Http的请求和应答的报文头上和一般 ...

  7. Xcode6为什么干掉pch(Precompile Prefix Header)&如何添加pch文件

    转载:  http://blog.csdn.net/iosdevtip/article/details/40918353 一直在用xcode6开发,但项目都是在xcode5上创建的,所以一直没注意到, ...

  8. 计算内存容量(measure)

    $m =gwmi Win32_PhysicalMemory $m|measure -Property capacity #计算 Property 出现次数 $m|measure -Property c ...

  9. FZOJ2110 star(DFS)

    Overpower often go to the playground with classmates. They play and chat on the playground. One day, ...

  10. Kivy A to Z -- 怎样从python代码中直接訪问Android的Service

    在Kivy中,通过pyjnius扩展能够间接调用Java代码,而pyjnius利用的是Java的反射机制.可是在Python对象和Java对象中转来转去总让人感觉到十分别扭.好在android提供了b ...