大家好,欢迎来到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