open和fopen的区别以及两者打开文件后操作的区别

open和fopen的区别以及两者打开文件后操作的区别本文对比了 open 与 fopen 两种文件 I O 操作 讨论了它们在缓存 效率和移植性上的差异 以及 Linux 中 structfile 结构体在文件操作中的关键作用

大家好,欢迎来到IT知识分享网。

概念

open

属于不带缓存的文件IO操作,是通过调用非标准库(libc库)函数来间接调用系统调用实现的IO操作。这种操作方式,可以高效完成文件输入输出,它以文件标识符作为文件唯一性的判断依据。但由于这种操作不是ANSI C标准的,与系统有关,所以移植起来会有问题。当然,频繁操作的话开销也是个问题。

fopen

带缓存的IO操作是在不带缓存的基础上封装了一层,维护了一个输入输出缓冲区,使之能跨OS,成为ANSI C标准,成为标准IO库。由于缓冲区的存在,使得不用频繁地调用系统调用,可以减小系统开销,但是响应速度也会受到影响。

两者比较

不带缓存的方式会频繁地进行用户态和内核态的切换,高效但是需要程序员自己维护;带缓存的方式因为有了缓冲区,不是非常高效,但是易于维护。

表现为,如果顺序访问文件,fopen系列的函数要比直接调用open系列快;如果随机访问文件,open要比fopen快。且由于设备文件不可以当成流式文件来用,只能用open。所以,一般用fopen打开普通文件,用open打开设备文件。


操作

Linux里面有一个struct file结构体,定义在include/Linux/fs.h,文件结构体对应一个打开了的文件,每一个打开的文件在内核空间里面都对应了一个文件结构体。它由内核在打开文件时创建,并传递给在文件上进行操作的任何函数。在文件的所有实例都关闭后,内核释放这个数据结构。在内核创建和驱动源码中,struct file的指针通常被命名为file或filp。

struct file {   union {    struct list_head fu_list; //文件对象链表指针linux/include/linux/list.h    struct rcu_head fu_rcuhead; //RCU(Read-Copy Update)是Linux 2.6内核中新的锁机制    } f_u;   struct path f_path; //包含dentry和mnt两个成员,用于确定文件路径   #define f_dentry f_path.dentry //f_path的成员之一,当前文件的dentry结构   #define f_vfsmnt f_path.mnt //表示当前文件所在文件系统的挂载根目录   const struct file_operations *f_op; //与该文件相关联的操作函数   atomic_t f_count; //文件的引用计数(有多少进程打开该文件)   unsigned int f_flags; //对应于open时指定的flag   mode_t f_mode; //读写模式:open的mod_t mode参数 loff_t f_pos;//当前文件指针位置   off_t f_pos; //该文件在当前进程中的文件偏移量   struct fown_struct f_owner; //该结构的作用是通过信号进行I/O时间通知的数据。   unsigned int f_uid, f_gid;// 文件所有者id,所有者组id   struct file_ra_state f_ra; //在linux/include/linux/fs.h中定义,文件预读相关   unsigned long f_version;//记录文件的版本号,每次使用之后递增   #ifdef CONFIG_SECURITY    void *f_security;   #endif   /* needed for tty driver, and maybe others */   void *private_data;//使用这个成员来指向分配的数据   #ifdef CONFIG_EPOLL   /* Used by fs/eventpoll.c to link all the hooks to this file */    struct list_head f_ep_links;    spinlock_t f_ep_lock;   #endif /* #ifdef CONFIG_EPOLL */   struct address_space *f_mapping;   }; 

每个进程在PCB(进程控制块)中都维护着一张文件描述符表,文件描述表中每个表项都有一个指向已打开文件(上面提到的file结构体)的指针。

关于返回值。open返回的是一个描述符,这个描述符对应的就是PCB中文件描述符表里面的描述符,操作这个值即可操作对应文件。fopen返回的是一个FILE类型的指针(与上面的file结构体不一样),这个类型的结构体包含了缓冲区的部分,以及描述符,所以也很好理解fopen是在open的基础上封装了一层缓冲区。

#ifndef _FILE_DEFINED struct _iobuf { char *_ptr; //文件输入的下一个位置 int _cnt; //当前缓冲区的相对位置 char *_base; //指基础位置(即是文件的其始位置) int _flag; //文件标志 int _file; //文件的有效性验证(文件描述符) int _charbuf; //检查缓冲区状况,如果无缓冲区则不读取 int _bufsiz; //缓冲区大小 char *_tmpfname; //临时文件名 }; typedef struct _iobuf FILE;

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/141994.html

(0)
上一篇 2025-05-13 16:20
下一篇 2025-05-13 16:26

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信