摘要:本文主要讨论文件控制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. fcntl函数

    很多时候,当我们有多个进程要访问同一个文件的时候,为了防止多进程访问导致的不一致,我们就要考虑进程间的同步问题. fcntl是一个很强大的函数,我们可以通过它给文件的某一部分上锁 int fcntl( ...

  2. linxu fcntl 函数用法 【转】

    功能描述:根据文件描述词来操作文件的特性. 文件控制函数         fcntl -- file control 头文件: #include <fcntl.h>;          i ...

  3. 文件I/O之fcntl函数

    fcntl函数可以改变已打开的文件的性质. #include <fcntl.h> int fcntl( int filedes, int cmd, ... /* int arg */ ); ...

  4. 高级I/O函数(3)-tee、fcntl函数

    tee函数使用 功能描述:tee函数在两个管道文件描述符之间复制数据,也是零拷贝操作.它不消耗数据,因此源文件描述符仍然可以用于后续的操作. 函数原型: #include <fcntl.h> ...

  5. Linux系统编程(3)——文件与IO之fcntl函数

    linux文件I/O用:open.read.write.lseek以及close函数实现了文件的打开.读写等基本操作.fcntl函数可以根据文件描述词来操作文件. 用法: int fcntl(int ...

  6. Linux下 fcntl 函数用法说明

    功能描述:根据文件描述词来操作文件的特性. 文件控制函数         fcntl -- file control LIBRARY         Standard C Library (libc, ...

  7. UNIX网络编程——fcntl函数

    fcntl函数提供了与网络编程相关的如下特性: 非阻塞式I/O.  通过使用F_SETFL命令设置O_NONBLOCK文件状态标志,我们可以把一个套接字设置为非阻塞型. 信号驱动式I/O. 通过使用F ...

  8. UNIX环境高级编程——记录上锁(fcntl函数)以及死锁检测

    一.记录锁 record locking 功能:当一个进程正在读或修改文件的某个部分时,它可以阻止其它进程修改同一文件区. 字节范围锁 byte-range locking 二.历史 flock函数, ...

  9. [Linux]fcntl函数文件锁概述

    概述 fcntl函数文件锁有几个比较容易忽视的地方: 1.文件锁是真的进程之间而言的,调用进程绝对不会被自己创建的锁锁住,因为F_SETLK和F_SETLKW命令总是替换调用进程现有的锁(若已存在), ...

随机推荐

  1. Java Web学习总结(7)——HttpServletRequest对象

    一.HttpServletRequest介绍 HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,通过这个对象 ...

  2. nyoj999 师傅又被妖怪抓走了 (预处理+bfs+状态压缩)

    题目999 题目信息 执行结果 本题排行 讨论区 师傅又被妖怪抓走了 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描写叙述 话说唐僧复得了孙行者,师徒们一心同体,共诣西方.自宝 ...

  3. php课程 11-37 类和对象的关系是什么

    php课程 11-37 类和对象的关系是什么 一.总结 一句话总结:类生成对象,对象是类的实例化,一定是先有类,后有对象,一定是先有标准,再有个体. 1.oop的三大优势是什么? 重用性,灵活性.扩展 ...

  4. input选中 和 select点击下拉选择获取选中选项的值

    1.input选中$('#checkBox').find('input').each(function(i){ if($(this).prop('checked')){//获取是否选中 并判断 $(t ...

  5. js里的表格数组某个key去重

    如Elemgnt的table绑定的数据要某个key是唯一的 var myarry = [ {name: 'liuyang',age :13}, {name:'jike',age:15}, {name: ...

  6. iOS_02_什么是ios开发

    什么是ios开发? * 已知:ios是iphone,ipad等手持设备操作系统. * ios开发就是开发运行在ios系统上的应用或者游戏软件,比如手机QQ,微博或者游戏,说白了,就是开发手机软件:当然 ...

  7. 学习redis--安装(二)

    安装前准备,我是在虚拟机中安装centos,然后安装redis. 安装 1.安装VMware,并安转centos系统 2.将redis的压缩包,上传到linux系统中(将下载到pc中的文件,拖到cen ...

  8. MongoDB 管理

    1.给数据库增加分片功能 mongos> use admin mongos> db.runCommand({enablesharding:"cipnet"}) mong ...

  9. 【t048】水流

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] 全球气候变暖,小镇A面临水灾.于是你必须买一些泵把水抽走.泵的抽水能力可以认为是无穷大,但你必须把泵放 ...

  10. [Angular] Providers and useFactory

    // service.ts import { Injectable, Inject } from '@angular/core'; import { Http } from '@angular/htt ...