V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
jdz
V2EX  ›  程序员

当 Linux 内核正在把 A 文件写入磁盘,这时另一个进程调用 write 写 A 文件,该进程会挂起么

  •  
  •   jdz · 2022-02-23 09:38:59 +08:00 · 1979 次点击
    这是一个创建于 1008 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如果不会,内核怎么处理这种竞争呢。

    9 条回复    2022-02-27 07:48:00 +08:00
    soulzz
        1
    soulzz  
       2022-02-23 09:42:08 +08:00   ❤️ 1
    另一个进程 write 写 A 失败
    msg7086
        2
    msg7086  
       2022-02-23 09:45:34 +08:00
    问题看得有点迷。内核把 A 刷入磁盘,然后进程又让内核写 A ?
    wellsc
        3
    wellsc  
       2022-02-23 09:55:58 +08:00
    了解下 io 调度算法
    cheng6563
        4
    cheng6563  
       2022-02-23 09:57:00 +08:00
    不说同文件了,如果写的超过缓冲区了同硬盘都会挂起
    jdz
        5
    jdz  
    OP
       2022-02-23 10:00:42 +08:00
    @msg7086 比如进程 M 调用了 flush(A), 然后内核就会刷新 A 到磁盘,在内核刷新到磁盘的同时,进程 N 调用 write(A),这时会发生什么呢
    msg7086
        6
    msg7086  
       2022-02-23 10:11:52 +08:00
    @jdz 会放进内存里等内核下一次 flush ?
    tomychen
        7
    tomychen  
       2022-02-23 14:49:13 +08:00
    ```C
    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);
    }

    static inline bool file_start_write_trylock(struct file *file)
    {
    if (!S_ISREG(file_inode(file)->i_mode))
    return true;
    return __sb_start_write(file_inode(file)->i_sb, SB_FREEZE_WRITE, false);
    }

    static inline void file_end_write(struct file *file)
    {
    if (!S_ISREG(file_inode(file)->i_mode))
    return;
    __sb_end_write(file_inode(file)->i_sb, SB_FREEZE_WRITE);
    }

    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;
    }
    ```
    whileFalse
        8
    whileFalse  
       2022-02-23 16:59:21 +08:00 via iPhone
    你确定另一个进程能以写方式 open 该文件?
    mayli
        9
    mayli  
       2022-02-27 07:48:00 +08:00 via Android
    不处理 写入会被序列化 后面的会覆盖之前的写入
    内核相当于写同一个文件同一个 Offset 两次
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1988 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 16:16 · PVG 00:16 · LAX 08:16 · JFK 11:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.