linux 文件描述符和库函数FILE文件指针关系

本文详细介绍了Linux系统中的文件描述符与C语言中的文件指针概念,解释了两者之间的区别与联系,并展示了如何在程序中实现两者的转换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


       文件描述符:在linux系统中,设备也是以文件的形式存在,要对该设备进行操作就必须先打开这个文件,打开文件就会获得文件描述符,它是个很小的正整数。每个进程在PCB(Process Control Block)中保存着一份文件描述符表,文件描述符就是这个表的索引,每个表项都有一个指向已打开文件的指针。文件描述符的优点:兼容POSIX标准,许多Linux和UNIX系统调用都依赖于它。文件描述符的缺点:不能移植到UNIX以外的系统上去,也不直观。
       文件指针:C语言中使用的是文件指针而不是文件描述符做为I/O的句柄。文件指针指向进程用户区中的一个被称为FILE结构的数据结构。FILE结构包括一个缓冲区和一个文件描述符。而文件描述符是文件描述符表的一个索引,因此从某种意义上说文件指针就是句柄的句柄(在Windows系统上,文件描述符被称作文件句柄)。FILE *中除了包含了fd信息,还包含了IO缓冲,是C标准形式,所以FILE *比fd更适合跨平台,应该多用fopen在,少用open。
       C语言文件指针与文件描述符之间可以相互转换:
       这要通过fdopen和fileno两个函数实现。它们都包含在头文件stdio.h中。
       fdopen的原型: FILE * fdopen(int filedes, const char *opentype);
       第一个参数filedes是一个打开的文件描述符,opentype是表示打开方式的字符串,和fopen函数具有相同的取值,比如"w"或"w+"等。但是你必须保证该字符串的描述和文件实际的打开方式是匹配的。函数fopen()就是返回打开文件的指针;如果操作失败,返回空指针null。
     把文件流指针转换成文件描述符用fileno函数,其原型为:
     int fileno(FILE *stream);
     它返回和stream文件流对应的文件描述符。如果失败,返回-1。

     当程序执行时,就已经有三个文件流打开了,它们分别是标准输入stdin,标准输出stdout和标准错误输出stderr。和流式文件相对应的是,也有三个文件描述符被预先打开,它们分别是0,1,2,代表标准输入、标准输出和标准错误输出。


FILE结构是包含有文件描述符的
FILE结构函数可以看作是对fd直接操作的系统调用的封装, 它的优点是带有I/O缓存

glibc中的源码定义:

stdio.h
/* The opaque type of streams.  */
typedef struct _IO_FILE FILE;

#######################################################
/usr/include/libio.h
typedef struct _IO_FILE _IO_FILE;
struct _IO_FILE 
{ 
        int _flags;       /* High-order word is _IO_MAGIC; rest is flags. */
        #define _IO_file_flags _flags
       
         /* The following pointers correspond to the C++ streambuf protocol. */
         /* Note:  Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
         char* _IO_read_ptr;   /* Current read pointer */
         char* _IO_read_end;   /* End of get area. */
         char* _IO_read_base;  /* Start of putback+get area. */
         char* _IO_write_base; /* Start of put area. */
         char* _IO_write_ptr;  /* Current put pointer. */
         char* _IO_write_end;  /* End of put area. */
         char* _IO_buf_base;   /* Start of reserve area. */
         char* _IO_buf_end;    /* End of reserve area. */
         /* The following fields are used to support backing up and undo. */
         char *_IO_save_base; /* Pointer to start of non-current get area. */
         char *_IO_backup_base;  /* Pointer to first valid character of backup area */
         char *_IO_save_end; /* Pointer to end of non-current get area. */
         
         struct _IO_marker *_markers;
       
         struct _IO_FILE *_chain;
       [1:stdio.h][2:libio.h]*
       -MiniBufExplorer-                                                                                                 
       
        int _fileno; //文件描述符
       #if 0
         int _blksize;
       #else
         int _flags2;
       #endif
         _IO_off_t _old_offset; /* This used to be _offset but it's too small.  */
       
       #define __HAVE_COLUMN /* temporary */
         /* 1+column number of pbase(); 0 is unknown. */
         unsigned short _cur_column;
         signed char _vtable_offset;
         char _shortbuf[1];
       
         /*  char* _save_gptr;  char* _save_egptr; */
       
         _IO_lock_t *_lock;
       #ifdef _IO_USE_OLD_IO_FILE
};



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值