linux内核中的文件描述符(一)--基础知识简介

Kernel version:2.6.14

CPU architecture:ARM920T

Author:ce123(http://blog.csdn.net/ce123)

作为文件的使用者,进程理所当然的要将所使用的文件记录于自己的控制块中,也就是task_struct。另外,由于进程所对应的程序也是一个文件,因此进程控制块还必须记录这个文件的相关信息。由于OS要对所有进程提供服务,因此OS还要维护一个记录所有进程打开的文件的总表。

1.文件对象

当进程通过open系统调用打开一个文件时,该系统调用找到这个文件后,会把文件封装到一个file结构的实例中提供给进程,这个实例称为file对象。file结构的定义如下:

struct file {struct list_head    f_list;         //所有打开文件的链表struct dentry        *f_dentry;      //文件的dentrystruct vfsmount         *f_vfsmnt;      //文件目录的VFS安装点指针struct file_operations    *f_op;          //指向文件操作函数集的指针atomic_t      f_count;        //记录访问本文件的进程数目的计数器unsigned int      f_flags;        //访问类型mode_t            f_mode;         //访问模式loff_t            f_pos;          //文件当前的读写位置struct fown_struct   f_owner;unsigned int        f_uid, f_gid;   //文件所有者ID和用户组IDstruct file_ra_state f_ra;unsigned long      f_version;void          *f_security;/* 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;struct rcu_head  f_rcuhead;
};

结构中的域f_uid为文件所有者的ID,f_gid为文件所有者所在组的ID。这样就使得一个文件可能面临三种用户的访问:

  • 文件所有者;
  • 同组用户;
  • 其他用户。

内核在处理一个进程或用户访问一个文件的请求时,要根据进程的f_uid和f_gid以及访问模式来确定该进程是否具有访问这个文件的权限。对于一个用户来说,可以有读、写和执行三种文件权限,这三种权限和三种用户就共有9中组合,即文件的访问权限可以用9个bit来表示,并将其保存在文件的dentry中。

结构中的域f_pos记录了进程对文件读写位置的当前值,可以通过调用函数llseek进程移动。

结构中的f_op执向结构file_operations,该结构封装了对文件进行操作的函数,定义如下:

struct file_operations {struct module *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);unsigned int (*poll) (struct file *, struct poll_table_struct *);int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);long (*compat_ioctl) (struct file *, unsigned int, unsigned long);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 *);ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);int (*check_flags)(int);int (*dir_notify)(struct file *filp, unsigned long arg);int (*flock) (struct file *, int, struct file_lock *);
};

从上面的代码可以看到,结构中是一系列函数的指针,这里有我们比较熟悉的read、open、write和close等函数的指针。进程就是通过这些函数访问一个文件的,file_operations是linux虚拟文件系统VFS和进程之间的接口。

2.文件描述符

下面进一步介绍进程对自己所访问的file对象的管理方法。linux中使用一个数组来管理进程打开的文件的file对象,数组中的每个元素都存放一个纸箱进程所打开的文件的file对象。既然用一个数组来存放file对象,那么用数组的下标来访问文件就是一件顺理成章的方法,于是,linux就把数组元素的下标叫做该数组元素所对应的文件的文件描述符,该描述符就是系统对文件的标识,这个数组也叫文件描述符数组,如下图所示:

内核通过系统调用dup、dup2和fctl可以使数组中的多个元素指向同一个文件的file对象,也就是说,在linux中,同一个文件可以有多个文件描述符。

3.进程打开文件表

进程描述符数组中存放了一个进程所访问的所有文件,把这个文件描述符数组和这个数组在系统中的一些动态信息组合到一起,就形成了一个新的数据结构——进程打开文件表,即file_struct,其定义如下:

/** Open file table structure*/
struct files_struct {atomic_t count;                               //引用计数spinlock_t file_lock;     /* Protects all the below members.  Nests inside tsk->alloc_lock */struct fdtable *fdt;                          //管理文件描述符struct fdtable fdtab;                         //管理文件描述符fd_set close_on_exec_init;                    //位图fd_set open_fds_init;                         //位图struct file * fd_array[NR_OPEN_DEFAULT];      //文件描述符数组
};

显然,这个结构应该属于进程的私有数据,所以进程控制块task_struct用指针files指向它。

struct task_struct {...
/* open file information */struct files_struct *files;...
};

进程与其打开文件之间的关系如下图所示。

4.文件描述符的管理

file_struct中的fdt和fdtab用于管理文件文件描述符,一个是fdtable类型,另一个是其指针类型。fdtable的定义如下:

struct fdtable {unsigned int max_fds;               //可以代开的最大文件数int max_fdset;                      //位图的最大长度int next_fd;                        //下一个可用的fdstruct file ** fd;      /* current fd array 指向files_struct的fd_array */fd_set *close_on_exec;fd_set *open_fds;                   //打开的文件标记,比如第2位为0,则打开了2号文件struct rcu_head rcu;struct files_struct *free_files;struct fdtable *next;
};

下图可以很直观的说明文件描述符fd的管理。

linux内核中的文件描述符(一)--基础知识简介相关推荐

  1. Linux中文件描述符1,linux内核中的文件描述符(一)--基础知识简介

    原标题:linux内核中的文件描述符(一)--基础知识简介 Kernel version:2.6.14 CPU architecture:ARM920T Author:ce123(http://blo ...

  2. linux内核中的文件描述符(四)--fd的分配--get_unused_fd

    linux内核中的文件描述符(四)--fd的分配--get_unused_fd Kernel version:2.6.14 CPU architecture:ARM920T Author:ce123( ...

  3. linux内核中的文件描述符(三)--fd的回收

    linux内核中的文件描述符(三)--fd的回收 Kernel version:2.6.14 CPU architecture:ARM920T Author:ce123(http://blog.csd ...

  4. 简述linux内核中,Linux内核中的文件描述符(一)——基础知识简介

    2.文件描述符 下面进一步介绍进程对自己所访问的file对象的管理方法.linux中使用一个数组来管理进程打开的文件的file对象,数组中的每个元素都存放一个纸箱进程所打开的文件的file对象.既然用 ...

  5. linux 内核 遍历文件夹,Linux内核中通过文件描述符获取绝对路径

    背景 在Linux内核中,已知一个进程的pid和其打开文件的文件描述符fd,如何获取该文件的绝对路径?基本思路是先获取该文件在内核中的file结构体,再通过d_path()获取到整个文件的绝对路径. ...

  6. linux c中的文件描述符与打开文件之间的关系

    转载请说明出处:http://blog.csdn.net/cywosp/article/details/38965239 1. 概述     在Linux系统中一切皆可以看成是文件,文件又可分为:普通 ...

  7. 理解Unix/Linux系统中的文件描述符

    简介 文件描述符是针对Unix/Linux的每个进程而言的,每个进程都维护了一个文件指针表,指针指向操作系统的文件.这里的文件是指的Unix/Linux系统所说的文件,Unix/Linux下一切皆文件 ...

  8. Linux中的文件描述符与打开文件之间的关系

    1. 概述 在Linux系统中一切皆可以看成是文件,文件又可分为:普通文件.目录文件.链接文件和设备文件.文件描述符(file descriptor)是内核为了高效管理已被打开的文件所创建的索引,其是 ...

  9. Linux中对文件描述符的操作(FD_ZERO、FD_SET、FD_CLR、FD_ISSET

    在Linux中,内核利用文件描述符(File Descriptor)即文件句柄,来访问文件.文件描述符是非负整数.打开现存文件或新建文件时,内核会返回一个文件描述符.读写文件也需要使用文件描述符来指定 ...

最新文章

  1. 现代hy-9600音响_从音响工程师到软件工程师-为什么我要学习编码
  2. 用研究新范式破解生命科学难题
  3. python乘法口诀表-用python打印99乘法口诀表
  4. container_of 和 offsetof 宏详解
  5. sourcetree打开快捷_Sourcetree使用:拉取打开项目的步骤
  6. Java sqlite事务方法,Java SQLiteDatabase.insert方法代码示例
  7. css比较特殊选择器汇总(持续更新)
  8. QueryWrapper 一些常用操作 or like in 大于 小于 操作
  9. 绘制直方图的方法大全
  10. java 配置dbcp_java – 使用DBCP进行Tomcat配置
  11. pass样本量_基于PASS两样本均数比较的样本量计算
  12. WPF ScrollViewer 仿苹果 细长 滚动条
  13. 吉大计算机学院田地,吉林大学研究生专业介绍:地质工程
  14. 麻省理工学院计算机科学与工程博士,2020年麻省理工学院博士读几年
  15. Visual Basic
  16. C# 制作excel图表
  17. 朋友圈长文不折叠神器
  18. 2022安全员-C证上岗证题目及答案
  19. java 单例模式双重检索_单例模式:为什么要双重检测
  20. SpringBoot-生成验证码

热门文章

  1. hss网元 java_在NB-IoT建构和流程中,作为网元实体的MME和HSS进行了哪些功能方面的升级?...
  2. 爬取网络数据到excel表
  3. 纯javascript的HTML在线编辑器
  4. 微积分学 \ 线性代数 \ 概率论与数理统计
  5. Yolov3-v5正负样本匹配机制
  6. 代码diff服务改进方案
  7. 西门子PLC1200学习之比较指令
  8. 怎么在短时间内快速提高网站排名
  9. 数值积分:龙贝格求积
  10. 谈谈数据库里的时间戳