我正在查看旧的Linux内核代码(3.10.1),尤其是IO路径。
因此,当IO进入VFS层时,将调用函数vfs_write()
。
在这里我可以看到对file->f_op->write()
的调用,这是一个阻塞调用,正如系统调用write()
的手册页所说。
代码中的另一个选项是未定义file->f_op->write
指针时,在这种情况下vfs_write()
会调用do_sync_write()
。
do_sync_write()
继续调用filp->f_op->aio_write()
,这是一个异步调用,正如aio_write()
的手册页所述。
现在,我的问题是,当函数do_sync_write()
显然可以继续调用异步IO函数时,为什么将其命名为“ sync”?
我可能会丢失一些东西,或者那段时间曾经在这里犯过大错?
函数定义供参考,
ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
{
ssize_t ret;
if (!(file->f_mode & FMODE_WRITE))
return -EBADF;
if (!file->f_op || (!file->f_op->write && !file->f_op->aio_write))
return -EINVAL;
if (unlikely(!access_ok(VERIFY_READ, buf, count)))
return -EFAULT;
ret = rw_verify_area(WRITE, file, pos, count);
if (ret >= 0) {
count = ret;
file_start_write(file);
if (file->f_op->write)
ret = file->f_op->write(file, buf, count, pos);
else
ret = do_sync_write(file, buf, count, pos);
if (ret > 0) {
fsnotify_modify(file);
add_wchar(current, ret);
}
inc_syscw(current);
file_end_write(file);
}
return ret;
}
ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
{
struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = len };
struct kiocb kiocb;
ssize_t ret;
init_sync_kiocb(&kiocb, filp);
kiocb.ki_pos = *ppos;
kiocb.ki_left = len;
kiocb.ki_nbytes = len;
ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos);
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&kiocb);
*ppos = kiocb.ki_pos;
return ret;
}
答案 0 :(得分:0)
当函数
do_sync_write()
显然可以继续调用异步IO函数时,为什么将其命名为“ sync”?
它调用异步功能,然后使用
等待其完成
ret = wait_on_sync_kiocb(&kiocb);
因此,从do_sync_write
函数的调用者的角度来看,整个函数的行为都是同步的。