写这篇文正主要是为了介绍下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. 8-18-Exercise

    8-18-小练 A.HDU 1172   猜数字 采用枚举~[赤果果的暴力~] 代码: #include <iostream> #include <cstdio> #inclu ...

  2. 跑马灯效果的TextView之singLine 和maxLines

    Android 的TextView 里面有两个属性 singLine 和maxLines . 从字面意思来理解,这两个都是限制Text的行数.那么singleLine="true" ...

  3. Delphi- 内置数据库的使用例子BDE

    以前开发时经常使用一些大型的数据库,像这样小的数据库还是前段时间才看到.看看Delphi怎么使用内置的数据库, 先在BDE里拉两个数据库控件.DataBase和Table,然后再拉两个数据库控件Dat ...

  4. excel多个文件合并

    多个excel文件合并成一个需要用ms office wps是不行的 1.将所有文件放在一个文件夹里 2.在文件夹里新建一个空的excel打开 右键sheet点击查看代码->输入下面代码-> ...

  5. SYNONYMS

    SQL> SELECT * FROM V$VERSION WHERE ROWNUM=1; BANNER --------------------------------------------- ...

  6. 在不同平台上CocosDenshion所支持的音频格式

    在大多数平台上,cocos2d-x调用不同的SDK API来播放背景音乐和音效.CocosDenshion在同一时间只能播放一首背景音乐,但是能同时播放多个音效. 背景音乐 Platform supp ...

  7. Top 10 questions about Java Collections--reference

    reference from:http://www.programcreek.com/2013/09/top-10-questions-for-java-collections/ The follow ...

  8. TCPDUMP Command Examples

    tcpdump command is also called as packet analyzer. tcpdump command will work on most flavors of unix ...

  9. Add an IPv6 route through an interface

    Not often needed, sometimes in cases of dedicated point-to-point links. 7.4.1. Using "ip" ...

  10. c++匿名类—指针

    1 摘自网上 2代码实例 #include <iostream> #include <list> #include <iterator> #include < ...