APUE学习笔记
第三章 文件I/O
1.文件描述符
1.1作用:
文件描述符是fd内核为了高效地管理已经被打开的文件所创建的索引,它是一个非负整数用来表示打开的文件。fd只是一个整数,在open时产生。进程通过PCB中的文件描述符表找到该fd所指向的文件指针filp。
1.2最大文件描述符个数:
系统最大打开文件描述符数:/proc/sys/fs/file-max
进程最大打开文件描述符数:$ulimit -n
查看当前系统使用的打开文件描述符数:cat/proc/sys/fs/file-nr
1.3文件描述符和打开文件的关系:
每个进程在PCB(ProcessControlBlock)即进程控制块中都保存着一份文件描述符表,文件描述符就是这个表的索引,文件描述表中每个表项都有一个指向已打开文件的指针。对应于每个进程都有一个文件描述符表,表示这个进程打开的所有文件。文件描述表中每一项都是一个指针,指向一个用于描述打开的文件的数据块———file对象,file对象中描述了文件的打开模式,读写位置等重要信息,当进程打开一个文件时,内核就会创建一个新的file对象。file对象不是专属于某个进程的,不同进程的文件描述符表中的指针可以指向相同的file对象,从而共享这个打开的文件。
file对象中包含一个指针,指向dentry对象。dentry对象代表一个独立的文件路径,如果一个文件路径被打开多次,那么会建立多个file对象,但它们都指向同一个dentry对象。
dentry对象中又包含一个指向inode对象的指针。inode对象代表一个独立文件。因为存在硬链接与符号链接,因此不同的dentry对象可以指向相同的inode对象.inode对象包含了最终对文件进行操作所需的所有信息,如文件系统类型、文件的操作方法、文件的权限、访问日期等。打开文件后,进程得到的文件描述符实质上就是文件描述符表的下标,内核根据这个下标值去访问相应的文件对象,从而实现对文件的操作。
详细介绍:
1)进程级文件描述符:
include/linux/sched.h中定义如下
structfiles_struct {
atomic_tcount; /*共享该表的进程数 */
rwlock_tfile_lock; /*保护以下的所有域,以免在tsk->alloc_lock中的嵌套*/
intmax_fds; /*当前文件对象的最大数*/
intmax_fdset; /*当前文件描述符的最大数*/
intnext_fd;/*已分配的文件描述符加1*/
structfile ** fd; /*指向文件对象指针数组的指针*/
fd_set*close_on_exec; /*指向执行exec()时需要关闭的文件描述符*/
fd_set*open_fds; /*指向打开文件描述符的指针*/
fd_setclose_on_exec_init;/*执行exec()时需要关闭的文件描述符的初值集合*/
fd_set open_fds_init; /*文件描述符的初值集合*/
structfile * fd_array[32];/*文件对象指针的初始化数组*/
};
fd域指向文件对象的指针数组。该数组的长度存放在max_fds域中。通常,fd域指 files_struct结构的fd_array域,该域包括32个文件对象指针。对于在fd数组中有入口地址的每个文件来说,数组的索引就是文件描述符(filedescriptor)。open_fds域包含 open_fds_init域的地址,open_fds_init域表示当前已打开文件的文件描述符的位图。 max_fdset域存放位图中的位数。
2)系统级文件描述符表(打开的文件描述(openfile description))
在include\linux\fs.h中定义如下:
structfile{
structlist_head f_list; /*所有打开的文件形成一个链表*/
structdentry *f_dentry; /*指向相关目录项的指针*/
structvfsmount *f_vfsmnt; /*指向VFS安装点的指针*/
structfile_operations *f_op; /*指向文件操作表的指针*/
mode_tf_mode; /*文件的打开模式*/
loff_tf_pos; /*文件的当前位置*/
unsignedshort f_flags; /*打开文件时所指定的标志*/
unsignedshort f_count; /*使用该结构的进程数*/
unsignedlong f_reada, f_ramax, f_raend, f_ralen, f_rawin;
/*预读标志、要预读的最多页面数、上次预读后的文件指针、预读的字节数以及
预读的页面数*/
intf_owner; /*通过信号进行异步I/O数据的传送*/
unsignedint f_uid, f_gid; /*用户的UID和GID*/
intf_error; /*网络写操作的错误码*/
unsignedlong f_version; /*版本号*/
void*private_data; /* tty驱动程序所需*/
};
每个文件对象总是包含在下列的一个双向循环链表之中:
·1.“未使用”文件对象的链表。
·2.“正在使用”文件对的象链表。
structfile_operations {
structmodule *owner;
loff_t(*llseek)(struct file *, loff_t, int);
ssize_t(*read)(struct file *, char __user *, size_t, loff_t *);
ssize_t(*aio_read)(struct kiocb *, char __user *, size_t, loff_t);
ssize_t(*write)(struct file *, const char __user *, size_t, loff_t *);
ssize_t(*aio_write)(struct kiocb *, const char __user *, size_t, loff_t);
int(*readdir) (struct file *, void *, filldir_t);
unsignedint (*poll) (struct file *, struct poll_table_struct *);
int(*ioctl) (struct inode *, struct file *, unsigned int, unsignedlong);
int(*mmap) (struct file *, struct vm_area_struct *);
int(*open) (struct inode *, struct file *);
int(*flush) (struct file *);
int(*release) (struct inode *, struct file *);
int(*fsync) (struct file *, struct dentry *, int datasync);
int(*aio_fsync) (struct kiocb *, int datasync);
int(*fasync) (int, struct file *, int);
int(*lock) (struct file *, int, struct file_lock *);
ssize_t(*readv)(struct file *, const struct iovec *, unsigned long, loff_t *);
ssize_t(*writev)(struct file *, const struct iovec *, unsigned long, loff_t *);
ssize_t(*sendfile)(struct file *, loff_t *, size_t, read_actor_t, void __user *);
ssize_t(*sendpage)(struct file *, struct page *, int, size_t, loff_t *, int);
unsignedlong (*get_unmapped_area) (struct file *, unsigned long,
unsignedlong, unsigned long,unsignedlong);
};
structdentry {
atomic_td_count;目录项对象使用计数器,可以有未使用态,使用态和负状态
unsignedint d_flags;目录项标志
structinode * d_inode;与文件名关联的索引节点
structdentry * d_parent;父目录的目录项对象
structlist_head d_hash;散列表表项的指针
structlist_head d_lru;未使用链表的指针
structlist_head d_child;父目录中目录项对象的链表的指针
structlist_head d_subdirs;对目录而言,表示子目录目录项对象的链表
structlist_head d_alias;相关索引节点(别名)的链表
intd_mounted;对于安装点而言,表示被安装文件系统根项
structqstr d_name;文件名
unsignedlong d_time;
structdentry_operations *d_op;目录项方法
structsuper_block * d_sb;文件的超级块对象
vunsignedlong d_vfs_flags;
void* d_fsdata;与文件系统相关的数据
unsignedchar d_iname [DNAME_INLINE_LEN];存放短文件名
};
参考
[1]《APUE》
[2]http://blog.csdn.net/cywosp/article/details/38965239
[3]http://blog.csdn.net/houliang120/article/details/39853959
[4]http://blog.sina.com.cn/s/blog_7943319e01018m3w.html