Kernel version:2.6.14
CPU architecture:ARM920T
Author:ce123(http://blog.csdn.net/ce123)
作为文件的运用者,进程天经地义的要将所运用的文件记载于自己的操控块中,也便是task_struct。别的,因为进程所对应的程序也是一个文件,因而进程操控块还必须记载这个文件的相关信息。因为OS要对一切进程供应服务,因而OS还要保护一个记载一切进程翻开的文件的总表。
1.文件目标
当进程经过open体系调用翻开一个文件时,该体系调用找到这个文件后,会把文件封装到一个file结构的实例中供应给进程,这个实例称为file目标。file结构的界说如下:
print?
- structfile{
- structlist_headf_list;//一切翻开文件的链表
- structdentry*f_dentry;//文件的dentry
- structvfsmount*f_vfsmnt;//文件目录的VFS安点缀指针
- structfile_operations*f_op;//指向文件操作函数集的指针
- atomic_tf_count;//记载拜访本文件的进程数目的计数器
- unsignedintf_flags;//拜访类型
- mode_tf_mode;//拜访形式
- loff_tf_pos;//文件当时的读写方位
- structfown_structf_owner;
- unsignedintf_uid,f_gid;//文件一切者ID和用户组ID
- structfile_ra_statef_ra;
- unsignedlongf_version;
- void*f_security;
- /*neededforttydriver,andmaybeothers*/
- void*private_data;
- #ifdefCONFIG_EPOLL
- /*Usedbyfs/eventpoll.ctolinkallthehookstothisfile*/
- structlist_headf_ep_links;
- spinlock_tf_ep_lock;
- #endif/*#ifdefCONFIG_EPOLL*/
- structaddress_space*f_mapping;
- structrcu_headf_rcuhead;
- };
结构中的域f_uid为文件一切者的ID,f_gid为文件一切者地点组的ID。这样就使得一个文件或许面对三种用户的拜访:
- 文件一切者;
- 同组用户;
- 其他用户。
内核在处理一个进程或用户拜访一个文件的恳求时,要根据进程的f_uid和f_gid以及拜访形式来确认该进程是否具有拜访这个文件的权限。关于一个用户来说,能够有读、写和履行三种文件权限,这三种权限和三种用户就共有9中组合,即文件的拜访权限能够用9个bit来表明,并将其保存在文件的dentry中。
结构中的域f_pos记载了进程对文件读写方位的当时值,能够经过调用函数llseek进程移动。
结构中的f_op执向结构file_operations,该结构封装了对文件进行操作的函数,界说如下:
print?
- structfile_operations{
- structmodule*owner;
- loff_t(*llseek)(structfile*,loff_t,int);
- ssize_t(*read)(structfile*,char__user*,size_t,loff_t*);
- ssize_t(*aio_read)(structkiocb*,char__user*,size_t,loff_t);
- ssize_t(*write)(structfile*,constchar__user*,size_t,loff_t*);
- ssize_t(*aio_write)(structkiocb*,constchar__user*,size_t,loff_t);
- int(*readdir)(structfile*,void*,filldir_t);
- unsignedint(*poll)(structfile*,structpoll_table_struct*);
- int(*ioctl)(structinode*,structfile*,unsignedint,unsignedlong);
- long(*unlocked_ioctl)(structfile*,unsignedint,unsignedlong);
- long(*compat_ioctl)(structfile*,unsignedint,unsignedlong);
- int(*mmap)(structfile*,structvm_area_struct*);
- int(*open)(structinode*,structfile*);
- int(*flush)(structfile*);
- int(*release)(structinode*,structfile*);
- int(*fsync)(structfile*,structdentry*,intdatasync);
- int(*aio_fsync)(structkiocb*,intdatasync);
- int(*fasync)(int,structfile*,int);
- int(*lock)(structfile*,int,structfile_lock*);
- ssize_t(*readv)(structfile*,conststructiovec*,unsignedlong,loff_t*);
- ssize_t(*writev)(structfile*,conststructiovec*,unsignedlong,loff_t*);
- ssize_t(*sendfile)(structfile*,loff_t*,size_t,read_actor_t,void*);
- ssize_t(*sendpage)(structfile*,structpage*,int,size_t,loff_t*,int);
- unsignedlong(*get_unmapped_area)(structfile*,unsignedlong,unsignedlong,unsignedlong,unsignedlong);
- int(*check_flags)(int);
- int(*dir_notify)(structfile*filp,unsignedlongarg);
- int(*flock)(structfile*,int,structfile_lock*);
- };
从上面的代码能够看到,结构中是一系列函数的指针,这里有咱们比较了解的read、open、write和close等函数的指针。进程便是经过这些函数拜访一个文件的,file_operations是linux虚拟文件体系VFS和进程之间的接口。
2.文件描述符
下面进一步介绍进程对自己所拜访的file目标的办理办法。linux中运用一个数组来办理进程翻开的文件的file目标,数组中的每个元素都寄存一个纸箱进程所翻开的文件的file目标。已然用一个数组来寄存file目标,那么用数组的下标来拜访文件便是一件水到渠成的办法,所以,linux就把数组元素的下标叫做该数组元素所对应的文件的文件描述符,该描述符便是体系对文件的标识,这个数组也叫文件描述符数组,如下图所示:
内核经过体系调用dup、dup2和fctl能够使数组中的多个元素指向同一个文件的file目标,也便是说,在linux中,同一个文件能够有多个文件描述符。
3.进程翻开文件表
进程描述符数组中寄存了一个进程所拜访的一切文件,把这个文件描述符数组和这个数组在体系中的一些动态信息组合到一同,就形成了一个新的数据结构——进程翻开文件表,即file_struct,其界说如下:
print?
- /*
- *Openfiletablestructure
- */
- structfiles_struct{
- atomic_tcount;//引证计数
- spinlock_tfile_lock;/*Protectsallthebelowmembers.Nestsinsidetsk->alloc_lock*/
- structfdtable*fdt;//办理文件描述符
- structfdtablefdtab;//办理文件描述符
- fd_setclose_on_exec_init;//位图
- fd_setopen_fds_init;//位图
- structfile*fd_array[NR_OPEN_DEFAULT];//文件描述符数组
- };
明显,这个结构应该归于进程的私有数据,所以进程操控块task_struct用指针files指向它。
print?
- structtask_struct{
- …
- /*openfileinformation*/
- structfiles_struct*files;
- …
- };
进程与其翻开文件之间的联系如下图所示。
4.文件描述符的办理
file_struct中的fdt和fdtab用于办理文件文件描述符,一个是fdtable类型,另一个是其指针类型。fdtable的界说如下:
print?
- structfdtable{
- unsignedintmax_fds;//能够代开的最大文件数
- intmax_fdset;//位图的最大长度
- intnext_fd;//下一个可用的fd
- structfile**fd;/*currentfdarray指向files_struct的fd_array*/
- fd_set*close_on_exec;
- fd_set*open_fds;//翻开的文件符号,比方第2位为0,则翻开了2号文件
- structrcu_headrcu;
- structfiles_struct*free_files;
- structfdtable*next;
- };
下图能够很直观的阐明文件描述符fd的办理。