UNIX环境高级编程--文件描述符浅析

UNIX 环境高级编程---文件描述符浅析

最近看到一本书叫《 UNIX 环境高级编程》,网上称这本书被誉为 UNIX 编程 圣经 ,对所有不同层次 UNIX/LINUX 程序员是一本不可缺少的参考书。自己 最近 恰好看到 GLIB IOChannel 这部分,关于 linux IO 这块很不清楚,先研究完这本书再说。

文件描述符 是一个小的非负整数,内核用以标识一个特定进程正在存访的文件。当内核打开一个现存文件或创建一个新文件时,它就返回一个文件描述符。当读、写文件时,就可使用它。说白了就是我们通常使用的句柄一个意思。

 

一、文件描述符---- 文件表 ----v 节点结构三者的联系

既然文件描述符标识特定进程正在访问的文件,那进程跟文件是怎么联系起来的呢?

首先我们得知道每运行一个进程,shell 就会默认为其打开三个文件描述符 (0,1,2) ,分别与标准输入 (stdin) ,标准输出 (stdout) 和标准错误 (stderr) 对应。

接下来讲下内核所使用的三种数据结构,正是这三种数据结构才使进程最终跟文件联系起来。 建议边看图一边看下面的文字描述

2.1  1)  每个进程在进程表中都有一个记录项,每个记录项中有一张打开文件描述符表,可将其视为一个矢量,每个描述符占用一项。与每个文件描述符相关联的是: (a)  文件描述符标志。 (b)  指向一个文件表项的指针

2.2  2) 内核为所有打开文件维持一张文件表。每个文件表项包含: (a)  文件状态标志 ( 读、写、增写、同步、非阻塞等 ) (b)  当前文件位移量。 (c)  指向该文件 v 节点表项的指针。

2.3  3) 每个打开文件(或设备)都有一个 v 节点结构。 是文件的重要信息部分。

具体

如图一,下图表示以上三个数据结构的关系:

图一

总之图一是一定要弄明白的,否则后面会更模糊。

 

二、文件描述符的分配

文件描述符的分配 当用户调用相关函数比如 open, creat 等函数时,如果成功,会返回一个文件描述符 ,返回的文件描述符一定是当前进程最小没有用到的描述符。但是要特别注意文件描述符的最大值,可以通过命令$ulimit  n查看文件描述符的最大值,一般 linux 发行版都是 1024 ,当然这个值可以修改的,具体可以参考 关于文件描述符

 

三、基于文件描述符的输入输出函数

接下来讲讲 基于文件描述符的输入输出函数:

open:打开一个文件 ,并指定访问该文件的方式,调用成功后返回一个文件描述符。

creat :打开一个文件,如果该文件不存在,则创建它,调用成功后返回一个文件描述符。

close :关闭文件,进程对文件所加的锁全都被释放。

read :从文件描述符对应的文件中读取数据,调用成功后返回读出的字节数。

write :向文件描述符对应的文件中写入数据,调用成功后返回写入的字节数。

ftruncate :把文件描述符对应的文件缩短到指定的长度,调用成功后返回 0

lseek :在文件描述符对应的文件里把文件指针设定到指定的位置,调用成功后返回新指针的位置。

fsync: 将所有已写入文件中的数据真正写到磁盘或其他下层设备上,调用成功后返回 0

fstat :返回文件描述符对应的文件的相关信息,把结果保存在 struct stat 中,调用成功后返回 0

fchown :改变与打开文件相关联的所有者和所有组,调用成功后返回 0

fchmod :把文件描述符对应的文件的权限位改为指定的八进制模式,调用成功后返回 0

flock :用于向文件描述符对应的文件施加建议性锁,调用成功后返回 0

fcntl :既能施加建议性锁也能施加强制性锁,能建立记录锁、读取锁和写入锁,调用成功后返回 0

dup :复制文件描述符,返回没使用的文件描述符中最小的编号。

dup2 :由用户指定返回的文件描述符的值,用来重新打开或重定向一个文件描述符。

select :同时从多个文件描述符读取数据或向多个文件描述符写入数据。

 

这里就重点讲解下 dup, dup2, fcntl 函数

1.  dup:

函数原型:int dup(int filefd)

函数功能:复制一份现存的文件描述符filefd

2.  dup2:

函数原型:int dup2(int Oldfilefd, int Newfield)

函数功能:复制一份现存的文件描述Oldfilefd ,若 Newfield 等于 Oldfilefd 时,返回 Newfield ;若两者不相等时,若 Newfield 已经打开,先关闭 Newfield ,然后返回 Newfield

3.  fcntl :

函数原型:int  fcntl  (int filefd, int cmd,  )

函数功能: fcntl 5 种功能,通过第二个参数 cmd 来决定。这里只讲一种:复制一份现存的文件描述符, cmd F_DUPFD

由上面三个函数的功能都是 复制文件描述符,记住是文件描述符,不是复制文件表,更不是复制v 节点表 ,其实这三个函数有微妙的联系,如下:

dup(filefd)

相当于

fcntl (filefd, F_DUPFD, 0)

 

dup2(Oldfilefd, Newfilefd)

相当于

close( Newfilefd)

fcntl ( Oldfilefd , F_DUPFD, 0)

主要区别是 dup2 操作是原子操作,执行过程中不会被打断,关于原子操作可以参考我的博文: Atomic Operation【原子操作符】简介【原】 ;。

 

四,dup, dup2, fcntl 文件描述符---- 文件表 ----v 节点结构影响

UNIX 环境高 级编程》 一书第三章习题要求画出 文件描述符---- 文件表 ----v 节点结构三者的关系图

如下题:

在假设一个进程执行下面的3 个函数调用:

fd1 = open(pathname, oflags);

fd2 = dup(fd1);

fd3 = open(pathname, oflags);

画出结果图( 类似于图一 )

解答:每次调用open 就分配一个文件表项,如果两次打开的是相同的文件,则两个文件表项指向相同的 v 节点结构,所以文件描述符 fd1 fd2 所指向的文件表项都指向相同的 v 节点结构。 dup 是复制文件描述符,复制的文件描述符所指向的文件表跟被复制的文件描述符一样。所以结果图就是图一。

 

五,参考资料

UNIX 环境高级编程》

关于文件描述符

解惑dup/dup2( 原创 )  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值