linux write()的真正实现逻辑是什么

nnt7mjpx  于 2023-06-29  发布在  Linux
关注(0)|答案(2)|浏览(99)

我知道在linux上,内核经常缓存对磁盘的读写访问,就像下面的代码,它在写调用和返回之后将msg保存到一个缓冲区,然后在缓冲区满的时候进行实际的写操作。

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

int
main()
{
    int fd = open("./test.txt", O_RDWR, 0766);
    if (fd < 0) {
        printf("open file failed %d\n", errno);
        return -1;
    }
    
    char msg[100] = "write this msg to disk";
    write(fd, msg, strlen(msg));

    return 0;
}

我不知道write()的实现,我的问题是:如果缓冲区在内存中,内核会将msg复制到类似memcpy的缓冲区中,这样的复制会很耗时吗?

x6492ojm

x6492ojm1#

在内存中复制比IO到磁盘更快。磁盘IO非常慢,比在内存中复制慢得多。
(We在特殊情况下,可以绕过缓冲区直接发出磁盘IO。例如,有一个用户空间缓冲区,您希望避免复制它两次。)
使用内核缓冲区,内核可以对写入进行集群和调度,以发出更少的磁盘IO,发出大的顺序IO,甚至在文件被删除时取消一些IO。
如果你在libc中使用fwrite,还有一个用户空间缓冲区可以避免太频繁地陷入内核。

aydmsdu9

aydmsdu92#

write()的真正实现逻辑是什么?
write()函数将调用其他函数,如sys_write()
sys_write()如下代码:

int32_t sys_write(int32_t fd, const void* buf, uint32_t count){
    if(fd < 0){
        printk("sys_write: fd error\n");
    }
    if(fd == stdout_no){
        char tmp_buf[1024] = {0};
        memcpy(tmp_buf, buf, count);
        console_put_str(tmp_buf);
        return count;
    }
    uint32_t _fd = fd_local2global(fd);
    struct file* wr_file = &file_table[_fd];
    if(wr_file->fd_flag & O_WRONLY || wr_file->fd_flag & O_RDWR){
        uint32_t byte_written = file_write(wr_file, buf, count);
        return bytes_written;
    }else{
        console_put_str("sys_write: not allowed to write file without flag O_RDWR or O_WRONLY\n");
        return -1;
    }
}

相关问题