您的位置:首页 > 产品设计 > UI/UE

APUE读书笔记

2016-01-20 19:30 423 查看
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中定义如下
struct
files_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]/article/7618636.html
[3]/article/1751125.html
[4]http://blog.sina.com.cn/s/blog_7943319e01018m3w.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: