writev()系统调用在Linux中的primefaces性

我已经在linux内核4.4.0-57-generic的内核源代码中查看,并且在writev()writev()不到任何锁。 有什么我失踪? 我没有看到writev()是如何primefaces或线程安全的。

不是这里的核心专家,但我会分享我的观点。 随时发现任何错误。

浏览内核(v4.9虽然我不希望它是如此不同),并试图跟踪writev(2)系统调用,我可以观察到后续的函数调用,创建以下路径:

  1. SYSCALL_DEFINE3(writev, ..)

  2. do_writev(..)

  3. vfs_writev(..)

  4. do_readv_writev(..)

现在路径分支,取决于是否实现了write_iter方法,并挂钩在系统调用所引用的struct filestruct file_operations字段上。

  • 如果不是NULL ,路径是:

5A。 do_iter_readv_writev(..) ,此时调用方法filp->f_op->write_iter(..)

  • 如果它是NULL ,路径是:

5B。 do_loop_readv_writev(..) ,在这个循环中重复调用filp->f_op->write方法。


所以,就我所知, 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中的情况一样。

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

make方法对文件进行原子写入是特定文件系统实现的责任

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

 mutex_lock(&inode->i_mutex); 

为了使写作原子。

在fs.h找到它:

 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中:

 /* * 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); 

再次感谢。