open表和closed表_Linux文件管理通识锁定文件和文件描述符表

“本文档描述了锁定文件(结构文件)和文件描述符表(结构文件)的工作方式。”

ed1ecc50c4c94ddb2cafa5ad0885b0c1.png 直到2.6.12,文件描述符表已通过锁(files-> file_lock)和引用计数(files-> count)进行保护。-> file_lock保护访问表的所有文件相关字段。-> count用于在使用CLONE_FILES标志克隆的任务之间共享文件描述符表。通常,posix线程就是这种情况。与内核中的通用引用计数模型一样,最后一个执行put_files_struct()的任务将释放文件描述符(fd)表。文件(结构文件)本身受引用计数(-> f_count)保护。 在新的文件描述符管理无锁定模型中,引用计数相似,但是锁定基于RCU。文件描述符表包含多个元素-fd集(open_fds和close_on_exec,文件指针数组,集的大小和数组等)。为了使更新对于无锁阅读器来说是原子的,文件描述符表的所有元素都在单独的结构struct fdtable中。files_struct包含一个指向struct fdtable的指针,通过该指针可以访问实际的fd表。最初,fdtable嵌入在files_struct本身中。在fdtable的后续扩展中,分配了新的fdtable结构,并且files-> fdtab指向新结构。使用RCU释放了fdtable结构,并且无锁读取器会看到旧的fdtable或新的fdtable,使更新显得原子。以下是fdtable结构的锁定规则- 对fdtable的所有引用都必须通过files_fdtable()宏来完成:
struct fdtable *fdt;rcu_read_lock();fdt = files_fdtable(files);....if (n <= fdt->max_fds)        .......rcu_read_unlock();
files_fdtable()使用 rcu_dereference() 宏,该宏负责无锁解除引用的内存屏障要求。fdtable指针必须在读取侧关键部分内读取。 如上所述,必须通过 rcu_read_lock() / 保护fdtable的读取 rcu_read_unlock() 。 对于fd表的任何更新,必须保留files-> file_lock。 要查找给定fd的文件结构,读者必须使用fcheck()或fcheck_files()API。由于无锁查找,这些功能可满足对屏障的要求。 一个例子:
struct file *file;rcu_read_lock();file = fcheck(fd);if (file) {        ...}....rcu_read_unlock();
文件结构的处理很特殊。 由于fd(fget()/ fget_light())的查找是无锁的,因此查找可能与文件结构上的最后一次put()操作竞争。 使用-> f_count上的atomic_long_inc_not_zero()可以避免这种情况:
rcu_read_lock();file = fcheck_files(files, fd);if (file) {        if (atomic_long_inc_not_zero(&file->f_count))                *fput_needed = 1;        else        /* Didn't get the reference, someone's freed */                file = NULL;}rcu_read_unlock();....return file;
atomic_long_inc_not_zero()检测引用计数是否已经为零或在递增期间变为零。如果是这样,我们将使fget()/ fget_light()失败。 由于fdtable和文件结构都可以无锁查找,因此必须使用 rcu_assign_pointer()  API 进行安装。如果查找它们是无锁的,则 rcu_dereference()  必须使用。但是,建议使用files_fdtable()和fcheck()/ fcheck_files()来解决这些问题。 更新时,必须在按住files-> file_lock的同时查找fdtable指针。如果删除了-> file_lock,则另一个线程将扩展文件,从而创建新的fdtable并使较早的fdtable指针失效。 例如:
spin_lock(&files->file_lock);fd = locate_fd(files, file, start);if (fd >= 0) {        /* locate_fd() may have expanded fdtable, load the ptr */        fdt = files_fdtable(files);        __set_open_fd(fd, fdt);        __clear_close_on_exec(fd, fdt);        spin_unlock(&files->file_lock);.....
由于locate_fd()可以删除-> file_lock(并重新获取-> file_lock),因此必须在locate_fd()之后加载fdtable指针(fdt)。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值