• linux系统IO操作


    本文重点说明下面内容:

    • 什么是标准IO,什么是文件IO?
    • 什么是Direct IO? O_SYNC标识有什么意义?
    • 各个层面的缓存如何同步?
    • 还在page cache中的脏页可以读写吗?

    IO路径上的各层buff

    Application buff
    |
    clib buff
    |
    page cache
    |
    disk cache

    标准IO

    • 标准IO操作的是流(File对象)
    • 标准IO可以设置缓存,这个缓存是用户态buffer,一般称为clib buff
      api
    #include <stdio.h>
    
    //打开流
    FILE *fopen(const char *pathname, const char *type);
    
    //关闭流
    int fclose(File *fp);
    
    // 刷新流
    int fflush(FILE *fp);
    
    // 一次读写一个字符
    int fgetc(FILE *fp);
    int fputc(FILE *fp);
    
    // 一次读写一行
    char* fgets(char* buf, int n, FILE* fp);
    int fputs(const char *str, FILE* fp);
    
    // 二进制读写
    size_t fread(void *ptr, size_t size, size_t nobj, FILE *fp);
    size_t fwrite(const void *ptr, size_t size, size_t nobj, FILE *fp);
    
    // 格式化输入输出
    int fprintf(FILE *fp, const char* format, ...);
    int fscanf(FILE *fp, const char *format, ...);
    
    // 示例
    #include <stdio.h>
    #include <stdlib.h>
    int main(void){
        char buf[1024];
    
        while (fgets(buf, 1024, stdin) != NULL)
            if (fputs(buf, stdout) == EOF)
                printf("output error");
    
        if (ferror(stdin))
            printf("input error");
        
        exit(0);
    }
    

    说明

    • 调用fwrite, fputc, fputs系列函数后,数据被保存到clib buf中,依然处于用户态,如果此时应用进程crash掉,这些数据将丢失。
    • 在调用fflush可将clib buf中的数据写入内核的page cache中。
    • 调用fclose也会将clib buff中的数据刷新到内核,并且把clib buff中的输入数据丢弃。
      从这些标准IO的API可看出,标准IO比文件IO要简洁很多,没有各种标识,没有sync, nonblock等。
      上列API具体使用细节可参考《unix环境高级编程》第5章。

    文件IO

    文件IO是直接操作linux系统调用,大部分的问题都是使用文件IO带来的。
    

    api

    
    int open(const char *pathname, int oflag);
    
    int close(int filedes);
    
    ssize_t read(int filedes, void* buff, size_t nbytes);
    
    ssize_t write(int filedes, const void* buff, size_t nbytes);
    
    int fsync(int filedes);
    
    int fcntl(int filedes, int cmd);
    
    int ioctl(int filedes, int request);
    

    说明

    • O_SYNC标识打开的文件,会在write系统调用时,会等待IO从底层返回;O_SYNC仅对写有意义。
    • O_DIRECT标识打开的文件不经过page cache; O_DIRECT对读写都是有意义的。
    • O_NONBLOCK标识打开的文件(一般是网络IO,终端设备IO) ,在不可读写时立即返回EAGAIN等错误码。
    • O_SYNC, O_DIRECT有区别如下,
    size_t wirte_file()
    {
        if(o_DIRECT)
            direct_io();
        else
            buffered_io();
    
        if( O_SYNC )
            wait_data_synced();
    }
    
    上述API细节可参考《unix环境高级编程》第3章。
    

    mmap

    api

    #include <sys/mman.h>
    void *mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset);
    
    mmap在calling process的虚拟地址空间中创建一个映射,主要有以下两种常用方式:
    
    • 对文件创建一个mapping,读写文件可以用读写内存替代。

    • 匿名映射,传入的fd为-1

      创建mapping后,省掉了数据从在用户态buff和内核page cache的拷贝


    后续整理下linux系统文件IO流程

  • 相关阅读:
    MySQL忘记root密码的找回方法
    MySQL中的备份和恢复
    MySQL中的锁(表锁、行锁)
    设计模式之: 策略模式
    MySQL流程函数
    高效查看MySQL帮助文档的方法
    php动态获取函数参数
    设计模式之: 代理模式
    网站性能优化指标
    设计模式之: 状态模式
  • 原文地址:https://www.cnblogs.com/holidays/p/linux_io.html
Copyright © 2020-2023  润新知