摘要:本文主要讨论文件控制fcntl函数的基本应用.dup函数能够拷贝文件描写叙述符,而fcntl函数与dup函数有着异曲同工之妙.而且还有更加强大的功能,能够获取或设置已打开文件的性质,操作文件锁.

1.fcntl函数

在《重定向编程 dup和dup2》一文中,介绍了dup和dup2两个函数,函数是提供了复制一个现存的文件描写叙述符的功能,而本文介绍的fcntl函数提供了进一步管理文件描写叙述符的各种手段,用它能够对以打开的描写叙述符运行各种控制操作,比方,能够像dup和dup2一样复制一个文件描写叙述符,还有获取或设置文件描写叙述符标志(仅仅读、仅仅写等等),操纵文件锁.

头文件:

#include <unistd.h>
#include <fcntl.h>

定义函数:

int fcntl(int filedes, int cmd);
int fcntl(int filedes, int cmd, longarg);
int fcntl(int filedes, int cmd,structflock *lock);

返回值:若成功返回值依赖与cmd,若出错则返回-1.假设设置属性,正确返回0,错误返回-1;假设是读取属性,正确返回该属性值,错误返回-1.如,下例三个命令有特定的返回值:F_DUPFD、F_GETFD、F_GETFL以及F_GETOWN.
F_DUPFD:返回新的文件描写叙述符.
F_GETFD:返回对应的标志.
F_GETFL以及F_GETOWN:返回一个进程ID或负的进程组ID.
函数说明:
   函数第一个參数为欲改动属性的文件描写叙述符,第三个整数总是整数或记录锁(记录锁这里不讨论),假设是记录锁,第三个參数则是指向一个结构体指针.
   fcntl()对打开的文件描写叙述符filedes运行各种控制操作,详细是那一操作则由第二个參数cmd决定,表1列出了该參数的全部同意值.依据參数cmd的值,有一些參数还要提供第三个參数,就是文件锁.

表1 fcntl函数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_SETLF).

2.F_DUPFD

拷贝文件描写叙述符filefes.新文件描写叙述符最为函数返回值.新文件描写叙述符具有下面特性:
(1)新描写叙述符是尚未打开的各文件描写叙述符中大于或等于第三个參数值(取正整数)中各值的最小值.
(2)新描写叙述符与filedes共享同一个文件表项(类似于dup函数);即,新描写叙述符与filedes原始文件同样的文件指针,同样的打开文件(或管道),同样的文件状态标志,同样的文件模式.如图2所看到的,fd=3与fd=1两个文件描写叙述符是指向同一个文件表的.可是,新文件描写叙述符有它自己的一套文件描写叙述符标志,其FD_CLOEXEC文件描写叙述符标志被清除.
(3)将与新文件描写叙述符关联的close-on-exe标志设置为在各exec(2)系统调用之间保持打开状态.
    当进程打开一个文件时,内核中的数据结构如图1所看到的,也就是在程序拷贝文件描写叙述符之前,内核状态是这样子的。每一个进程默认仅仅能打开1024个文件描写叙述符,当一个进程打开一个文件时,默认会从0開始查找未被使用的描写叙述符,因为0,1,2默认被占用,全部一般从3開始使用。

图1 进程打开一个文件时的内核数据结构状态

文件表项:每个打开的文件相应着一张文件表,文件表能够共享,当多个文件描写叙述符指向同一个文件表时,文件表中的refcnt字段会相应变化.文件表中包括着文件状态标识:文件的打开模式(R,W,RW,APPEND,NOBLOCK等)、当前文件偏移量、refcnt:被引用数量、v节点指针:指向一个v节点表。
v结点表:每一个文件相应一个v结点表,不管被多少个进程打开都仅仅有一个,它包含v节点信息(主要是stat结构体中的信息),i节点信息等。
    简单地说,拷贝文件描写叙述符只在当前进程打开的文件表项新增一项(图2:新增了fd=3这一项),两者(fd=1或fd=3)同一时候指向内核中的文件表信息,操作文件描写叙述符随意一个会影响到另外一个.

图2 进程拷贝文件描写叙述符后的内核数据结构状态

样例1:拷贝文件描写叙述符,并使用复制前后的文件描写叙述符往打开的文件写入信息.

#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>void main()
{int fd,newfd;char *bufFD="Advanced Programming! write by fd\n";char *bufNewFD="Advanced Programming! write by NewFD\n";fd = open("test.txt",O_RDWR|O_CREAT,0644);if(fd==-1){printf("open file error%m\n");exit(-1);}//開始复制了newfd = fcntl(fd,F_DUPFD);//使用fd写write(fd,bufFD,strlen(bufFD));close(fd);//使用newfd写write(newfd,bufNewFD,strlen(bufNewFD));if(close(newfd)==-1){printf("close error\n");}printf("now the content of file :\n");system("cat test.txt");exit(0);
}

输出:
:Advanced Programming! write by fd
:Advanced Programming! write by NewFD
    能够看出,对fd或newfd进行读写操作时对同一个文件操作,并且还能够看到fd关闭后,对newfd没有影响,使用newfd还能够操作打开的文件.
    对于复制一个文件描写叙述符这个问题,fcntl和dup函数是有异曲同工之妙.
调用:

dup(filedes);

等价于:

fcntl(filedes, F_DUPFD, 0);

而调用:

dup2(filedes,filedes2);

等价于:

close(filedes2);
fcntl(filesdes,F_DUPFD,filedes);

注意:对于后一种情况,dup2并不全然等价于close加上fcntl.差别:
(1)dup2是原子操作,而close及fcntl则包含两个函数调用.有可能在close和fcntl之间插入运行信号捕获函数,中间这个过程改动了文件描写叙述符.
(2)dup2和fcntl有某些不同的errno.

3.F_GETFL

F_GETFL用于获取文件状态标志和其訪问模式,相应于filedes的文件状态标志作为返回值.F_GETFL支持的标志.如表2.

表2 文件状态标志说明

样例2:监測文件当前的读取权限.假设文件具有读取权限,则返回可读信息,假设具有写权限,则返回可写信息.否则返回出错信息.

#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>int main(int argc, char *argv[])
{int accmode,val;if(argc!=2){printf("error:\n");}if((val=fcntl(atoi(argv[1]),F_GETFL,0))<0){printf("error:%m\n");exit(-1);}accmode = val & O_ACCMODE;switch(accmode){case O_RDONLY:printf("read only\n");break;case O_WRONLY:printf("write only\n");break;case O_RDWR:printf("read write\n");break;default:printf("unknow access mode\n");}exit(0);
}

输出:
:./a.out test.txt
:read write

4.综述

拷贝文件描写叙述符的三种方法已学习的差点儿相同,牢记dup、dup2和fcntl函数,由于,从此一生受用.关于fcntl的使用还有非常多未挖掘,到这里先简单入门,日后再进一步加深学习.

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------勿在浮沙筑高台,静下心来,慢慢地沉淀---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

文件控制 fcntl函数具体解释相关推荐

  1. linux非阻塞输入函数,Linux fcntl函数设置阻塞与非阻塞

    转自http://www.cnblogs.com/xuyh/p/3273082.html 用命令F_GETFL和F_SETFL设置文件标志,比如阻塞与非阻塞 F_SETFL     设置给arg描述符 ...

  2. 使用 fcntl 函数 获取,设置文件的状态标志

    前言 当打开一个文件的时候,我们需要指定打开文件的模式( 只读,只写等 ).那么在程序中如何获取,修改这个文件的状态标志呢?本文将告诉你如何用 fcntl函数 获取指定文件的状态标志. 解决思路 1. ...

  3. linux fcntl 函数 文件描述符选项控制

    功能描述:根据文件描述词来操作文件的特性. #include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd); ...

  4. UNIX中的文件控制--fcntl()

    文件控制函数          fcntl -- file control LIBRARY          Standard C Library (libc, -lc) SYNOPSIS       ...

  5. Linux 系统 文件锁 fcntl函数详解

    #include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd); int fcntl(int fd, int ...

  6. sigaction 函数,sigemptyset()函数,fcntl()函数,isatty()函数

    第一个函数:使用 sigaction函数: signal 函数的使用方法简单,但并不属于POSIX标准,在各类UNIX平台上的实现不尽相同,因此其用途受 到了一定的限制.而 POSIX标准定义的信号处 ...

  7. fcntl函数完成 set_fl()函数还有clr_fl()函数的封装

    使用fcntl函数完成,set_fl和clr_fl()函数的封装,设置文件的属性,例如:阻塞IO模型 和 非阻塞IO模型 #include <stdio.h> #include " ...

  8. fcntl函数-文件控制函数

    今日命令在vim中使用:vsplit ./include/io.h 是以垂直方式打开io.h文件 同理:split ./include/io.h 是以水平方式打开io.h文件 可以用fcntl 函数改 ...

  9. fcntl函数参数F_GETPIPE_SZ、F_SETPIPE_SZ报错引出的关于linux-specific头文件的使用方法...

    直接来个例子说明: -----------------------------------  #include <unistd.h> #include <errno.h> #i ...

最新文章

  1. 独家 | Deepnote测评:数据科学家的新IDE
  2. 《Windows Communication Foundation之旅》系列之一
  3. xmanager远程登录
  4. harmonyos 2.0怎么升级,HarmonyOS 2.0正式发布 分布式能力获得全面升级
  5. php退出页面父元素,jQuery中弹出iframe内嵌页面元素到父页面并全屏化的实例代码...
  6. 外循环java作用_循环和外循环的区别和作用
  7. ADO之connection
  8. 两个sql交集_神奇的 SQL 之性能优化 → 让 SQL 飞起来
  9. CDN - 域名解析错误排查
  10. 感知算法论文(一)YOLACT: Real-time Instance Segmentation(2019)译文
  11. bootstrap 合并菜单_Bootstrap与tab组合,切换菜单实例
  12. 为什么有些大公司的效率弱爆了?
  13. Perl 数字与字符串运算符之区别
  14. anywhere随启随用的静态文件服务器
  15. ffmpeg-20160517-git-bin
  16. python: 图像的维度、图像读写
  17. ectouch微信登录提示此次操作失败请返回重试原因
  18. 解决Rigify报错:“Please specify a valid pivot bone position. Incorrect armature for type ‘basic_spine‘”
  19. MyBatis是如何自动装配的
  20. wordpress mysql缓存_WordPress 如何启用 Memcached 内存缓存来提高网站速度

热门文章

  1. 记一次由Redis分布式锁造成的重大事故,避免以后踩坑!
  2. 阿里三面被挂,幸获内推,历经5轮终于拿到口碑offer
  3. 只知道用它打印了Hello World,除此之外你了解多少呢?
  4. 6种时序异常检测思路总结!
  5. 天大本科生论文入选CVPR 2022,实现深度学习长尾分类新SOTA
  6. 全球最大最干净的人脸公开训练集!格灵深瞳发布Glint360K
  7. 提高图形匹配精度,亮风台提出「完全可训练」的图匹配方法|CVPR 2020 Oral
  8. 论文LaTeX、项目README:无脑套用格式、开源模板最高10万赞
  9. 暴力裁员?小米回应来了,网友表示没毛病!
  10. 有了四步解题法模板,再也不害怕动态规划!