我查看了linux kernel 4.4.0-57-generic的内核源代码,在writev()源代码中没有看到任何锁。我是不是漏掉了什么?我看不出writev()是原子的或线程安全的。
发布于 2017-01-28 18:13:17
我不是这里的内核专家,但无论如何我都会分享我的观点。如果有任何错误,请随时找出来。
浏览内核(v4.9,尽管我不期望它会有如此大的不同),并尝试跟踪writev(2)系统调用,我可以观察到后续的函数调用创建了以下路径:
现在,路径进行了分支,这取决于是否实现了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中,路径看起来非常相似:
然后,它取决于作为struct file的struct file_operations中的字段的write_iter方法是否为NULL,就像上面描述的v4.9中的情况一样。
发布于 2017-01-28 21:11:18
虚拟文件系统本身并不保证writev()调用的原子性。它只调用struct file_operations的特定于文件系统的.write_iter方法。
使方法自动写入文件是特定文件系统实现的责任。
例如,在ext4文件系统函数中,ext4_file_write_iter使用
mutex_lock(&inode->i_mutex);用于使写入原子化。
发布于 2017-01-30 12:23:42
在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);再次感谢。
https://stackoverflow.com/questions/41906824
复制相似问题