首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Linux中writev()系统调用的原子性

问Linux中writev()系统调用的原子性
EN

Stack Overflow用户
提问于 2017-01-28 13:56:16
回答 3查看 652关注 0票数 3

我查看了linux kernel 4.4.0-57-generic的内核源代码,在writev()源代码中没有看到任何锁。我是不是漏掉了什么?我看不出writev()是原子的或线程安全的。

EN

回答 3

Stack Overflow用户

发布于 2017-01-28 18:13:17

我不是这里的内核专家,但无论如何我都会分享我的观点。如果有任何错误,请随时找出来。

浏览内核(v4.9,尽管我不期望它会有如此大的不同),并尝试跟踪writev(2)系统调用,我可以观察到后续的函数调用创建了以下路径:

  1. SYSCALL_DEFINE3(writev, ..)
  2. do_writev(..)
  3. vfs_writev(..)
  4. do_readv_writev(..)

现在,路径进行了分支,这取决于是否实现了write_iter方法,并将其挂接到系统调用所引用的struct file的struct file_operations字段上。

  • 如果不是NULL,路径是:

5a。do_iter_readv_writev(..),它调用方法filp->f_op->write_iter(..) at this point。

  • 如果是NULL,则路径为:

5b。do_loop_readv_writev(..),它在循环中重复调用filp->f_op->write at this point方法。

因此,据我所知,writev()系统调用和底层的write() (或write_iter())一样是线程安全的,当然,它可以通过各种方式实现,例如在设备驱动程序中,根据它的需要和设计,可以使用锁也可以不使用锁。

编辑

在内核v4.4中,路径看起来非常相似:

  1. SYSCALL_DEFINE3(writev, ..)
  2. vfs_writev(..)
  3. do_readv_writev(..)

然后,它取决于作为struct file的struct file_operations中的字段的write_iter方法是否为NULL,就像上面描述的v4.9中的情况一样。

票数 1
EN

Stack Overflow用户

发布于 2017-01-28 21:11:18

虚拟文件系统本身并不保证writev()调用的原子性。它只调用struct file_operations的特定于文件系统的.write_iter方法。

使方法自动写入文件是特定文件系统实现的责任。

例如,在ext4文件系统函数中,ext4_file_write_iter使用

代码语言:javascript
复制
mutex_lock(&inode->i_mutex);

用于使写入原子化。

票数 1
EN

Stack Overflow用户

发布于 2017-01-30 12:23:42

在fs.h中找到的:

代码语言:javascript
复制
static inline void file_start_write(struct file *file)
{
    if (!S_ISREG(file_inode(file)->i_mode))
        return;
    __sb_start_write(file_inode(file)->i_sb, SB_FREEZE_WRITE, true);
}

然后在super.c中:

代码语言:javascript
复制
/*
 * This is an internal function, please use sb_start_{write,pagefault,intwrite}
 * instead.
 */
int __sb_start_write(struct super_block *sb, int level, bool wait)
{
    bool force_trylock = false;
    int ret = 1;

#ifdef CONFIG_LOCKDEP
/*
 * We want lockdep to tell us about possible deadlocks with freezing
 * but it's it bit tricky to properly instrument it. Getting a freeze
 * protection works as getting a read lock but there are subtle
 * problems. XFS for example gets freeze protection on internal level
 * twice in some cases, which is OK only because we already hold a
 * freeze protection also on higher level. Due to these cases we have
 * to use wait == F (trylock mode) which must not fail.
 */
  if (wait) {
    int i;

    for (i = 0; i < level - 1; i++)
        if (percpu_rwsem_is_held(sb->s_writers.rw_sem + i)) {
            force_trylock = true;
            break;
        }
  }
#endif
  if (wait && !force_trylock)
    percpu_down_read(sb->s_writers.rw_sem + level-1);
  else
    ret = percpu_down_read_trylock(sb->s_writers.rw_sem + level-1);

  WARN_ON(force_trylock & !ret);
  return ret;
}
EXPORT_SYMBOL(__sb_start_write);

再次感谢。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41906824

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档