本文研究的主要是Linux中文件描述符fd与文件指针FILE*互相转换的相关内容,具体介绍如下。

1.文件描述符fd的定义:文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于UNIX、Linux这样的操作系统。

2.文件指针FILE定义说明文件指针的一般形式为:

FILE *指针变量标识符;

其中FILE应为大写,它实际上是由系统定义的一个结构,该结构中含有文件名、文件状态和文件当前位置等信息。在编写源程序时不必关心FILE结构的细节。

使用系统调用的时候用文件描述符的时候比较多,但是操作比较原始。C库函数在I/O上提供了一些方便的包装(比如格式化I/O、重定向),但是对细节的控制不够。

如果过度依赖其中的一种只会徒增麻烦,所以知道两者的转换是很有必要的。FILE*是对fd的封装

当然,有人会说知道文件路径的话重新打开就是了,但是这会产生竞争条件(Race Conditions),首先重新打开文件,相当于是2个fd指向同一文件,然后如果在打开的期间文件被删除了又被新建了一个同名文件,2个fd指向的便是不同的文件。

glibc库提供了两个转换函数fdopen(3)和fileno(3),都是中的

FILE *fdopen(int fd, const char *mode);

int fileno(FILE *stream);

PS:为了节省篇幅,还是继续忽略返回值的检查。

来看看测试吧,是不是我们想的那样。

#include

#include

#include

int main()

{

const char* filename = "new.txt";

int fd = open(filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);

FILE* fp = fdopen(fd, "w+");

int fd2 = fileno(fp);

printf("fd=%d | fd2=%d

", fd, fd2);

fclose(fp);

close(fd);

return 0;

}

$ gcc test.c

$ ./a.out

fd=3 | fd2=3

参考fileno手册:

The function fileno() examines the argument stream and returns its integer descriptor.

FILE是对fd的封装,fileno()是直接取得被封装的fd,因此并未创建新的fd指向该文件。

参考fdopen手册:

The fdopen() function associates a stream with the existing file descriptor, fd. The mode of

the stream (one of the values "r", "r+", "w", "w+", "a", "a+") must be compatible with the

mode of the file descriptor.

fdopen()是讲流(FILE对象)与已存在的文件描述符fd进行关联,因此也是未创建新的fd。值得注意的是,FILE指针的模式(mode)必须与文件描述符的模式兼容。

关于mode参数先搁置会儿,目前我们知道的是,使用fileno和fdopen进行转换,都是在原有的fd上进行操作,并未产生新的fd。那么,再次审视刚才的代码,是否发现了问题?

我们来检查下close(fd)的返回值,把close(fd)改成下列代码

if (-1 == close(fd)) {

perror("close");

exit(1);

}

$ gcc test.c

$ ./a.out

close: Bad file descriptor

没错,fclose在关闭文件指针的时候,内部其实也关闭了文件描述符(否则资源就泄露了),既然这里fp内部的文件描述符和fd是同一个,当fp被关闭时,fd也被关闭了,再次关闭fd就会出现“损坏的文件描述符”错误。

OK,现在回顾下fopen的第2个参数,又r/r+/w/w+/a/a+一共6种设置(windows平台的rb/rb+/wb/wb+暂且不谈),对比Linux手册我将对应的open设置列出来

依然是进行测试,修改fd_mode和fp_mode,看看实验结果

#include

#include

#include

#include

const int security = S_IRUSR | S_IWUSR;

const int fd_mode = O_RDWR | O_CREAT | O_TRUNC;

const char* fp_mode = "r";

int main()

{

int fd = open("new.txt", fd_mode, security);

FILE* fp = fdopen(fd, fp_mode);

if (fp == NULL) {

perror("fdopen");

exit(1);

}

close(fd);

return 0;

}

在fd_mode等价于"w+"时,fp_mode的6种设置(r/r+/w/w+/a/a+)均返回非空指针。

在fd_mode等价于"w"时,fp_mode6种设置只有"a"和"w"返回非空指针。

继续尝试"r"/"r+"/"a"/"a+"的设置,可以发现所谓“兼容”只与读写权限有关,O_RDWR兼容O_RDONLY和O_WRONLY,而后两者则只与自身兼容。

有意思的是O_APPEND(在末尾添加)和O_TRUNC(截断文件从头添加)也兼容。

The file position indicator of the new stream is set to that

belonging to fd, and the error and end-of-file indicators are cleared. Modes "w" or "w+" do

not cause truncation of the file. The file descriptor is not dup"ed, and will be closed when

the stream created by fdopen() is closed.

继续查看fdopen的手册内容,可以看到"w"和"w+"在这里不会导致文件截断。

后一句也印证了我们前面的实验结果:文件描述符不会被复制,文件指针被关闭时文件描述符也会被关闭。

PS:其实fdopen的手册上还有最后一句:The result of applying fdopen() to a shared memory object is undefined.

将fdopen用于共享内存对象的结果是未定义的。

总结

以上就是本文关于Linux中文件描述符fd与文件指针FILE*互相转换实例解析的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

linux 文件指针,Linux中文件描述符fd与文件指针FILE*互相转换实例解析相关推荐

  1. 文件描述符fd和文件指针File* fp的区别和转换

    在linux系统中把设备和普通文件也都看做是文件,要对文件进行操作就必须先打开文件,打开文件后会得到一个文件描述符,它是一个很小的正整数,是一个索引值.  内核会为每一个运行中的进程在进程控制块pcb ...

  2. linux中文件描述符fd和文件指针flip的理解

    整理自:http://www.cnblogs.com/Jezze/archive/2011/12/23/2299861.html 简单归纳:fd(file descriptor)只是一个整数,在ope ...

  3. 文件描述符fd、文件指针fp和vfork()

    1. fd:在形式上是一个非负整数.实际上他是一个索引值.指向kernal为每一个进程所维护的该进程打开文件的记录表. 当程序打开一个文件或者创建一个新文件的时候kernal向进程返回一个文件描述符. ...

  4. linux文件描述符与标识符,文件描述符fd

    这里以问答的方式来讨论这个问题: 1. 文件描述符 fd 和文件指针 FILE *的关系? 文件描述符是什么?我们知道每一个进程都有一个自己的PCB(进程控制块),进程控制块的结构是: struct ...

  5. android MemeoryFile和Parcel操作文件描述符fd

    ParcelFileDescriptor pfd; FileDescriptor fd; Parcel p; static byte[] testString = new byte[] {1,2,3, ...

  6. Linux中的文件描述符与打开文件之间的关系

    1. 概述 在Linux系统中一切皆可以看成是文件,文件又可分为:普通文件.目录文件.链接文件和设备文件.文件描述符(file descriptor)是内核为了高效管理已被打开的文件所创建的索引,其是 ...

  7. linux c中的文件描述符与打开文件之间的关系

    转载请说明出处:http://blog.csdn.net/cywosp/article/details/38965239 1. 概述     在Linux系统中一切皆可以看成是文件,文件又可分为:普通 ...

  8. <Linux基础--文件描述符fd、重定向、文件流指针FILE*概念理解>

    文章目录 1.文件描述符fd 2.重定向 3.文件流指针:FILE* 4.动态库和静态库 1.文件描述符fd 文件描述符:实际上就是内核中一个进程打开的文件描述信息数组(file* fd_array[ ...

  9. linux存储--文件描述符fd与FILE结构体(二)

    文件描述符fd 对于linux而言,所有对设备(对于linux而言,一切皆文件)和文件的操作都使用文件描述符来进行的. 文件描述符是一个非负的整数,它是一个索引值,指向内核中每个进程打开文件的记录表. ...

最新文章

  1. awstats CGI模式下动态生成页面缓慢的改进
  2. Chatter 导入
  3. Odoo10 启动选项
  4. 《JavaScript凌厉开发 Ext详解与实践》3月5日开始上架销售
  5. linux下echo命令详解(转)
  6. python线程监控_Python实现线程状态监测简单示例
  7. 数据库基础知识——TCL语言
  8. python sklearn生成分类、回归任务数据集(可选切分训练数据/测试数据)
  9. 《关于莉莉周的一切》
  10. 五分钟快速过完Verilog HDL基本概念(1)
  11. 剖析Elasticsearch集群系列之二:分布式的三个C、translog和Lucene段
  12. java aspose例子_在Java中使用Aspose对文档操作示例
  13. astc软解性能测试 - adxe引擎项目
  14. ThinkPad E430光驱面板拆卸方法
  15. 从外观上如何识别单模和多模光纤
  16. python 游戏(记忆拼图Memory_Puzzle)
  17. linux 安装mmdetection 踩坑笔记
  18. 百度OCR识别图片文字,解决image format error错误
  19. TCGA官网下载和TCGAbiolinks下载的文件数量竟然不一样?
  20. idea2021.3CPU占用100%解决办法

热门文章

  1. 递推(hdu2563)
  2. javascript动态添加删除行后行内计算及取值
  3. GDI+ 学习记录(31) 图像颜色变换(TGPImageAttributes)
  4. 3D深度估计,让视频特效更梦幻!
  5. 2020年最前沿的 8 本AI技术图书—文末留言赠8本
  6. ChinaMM竞赛:VideoNet视频内容识别-总奖池10W人民币
  7. 我对计算机网络的期待,表白对女朋友说的情话短句 我愿是你最期待的风景线...
  8. php点击按钮弹窗提示,WEB表单,给出弹出框提示,点击按钮报错
  9. 资深程序员:Python中你不知道的那些小工具
  10. 收藏 | 一文看完吴恩达最新演讲精髓,人工智能部署的三大挑战及解决方案