linux各种模式下io路径跟踪

       接上一篇:https://my.oschina.net/fileoptions/blog/3061997 ,linux的io路径比较复杂,通常我们在阅读内核源码的时候,有时候也很难完整的跟踪整个路径。其实,我们可以使用工具跟踪代码的io路径,看一下一次完成的open、write、read都调用了哪些内核函数,这里我使用ftrace工具。假设要跟踪的代码编译成iotrace ,则可以使用trace-cmd 对iotrace的io路径进行跟踪(命令如下)。 

 sudo trace-cmd record -p function -F ./iotrace

      trace-cmd 会启动iotrace程序,然后开始跟踪它的内核函数调用(并不是所有内核函数都会被跟踪到,只有ftrace支持的才可以),   由于代码很少,因此这里trace会很快结束,然后使用trace-cmd report命令将产生的trace文件格式化为人类可读的文本,就可以清晰的看到io的调用路径和层次关系。    

     由于我不想在虚拟机Linux上做这些测试(总感觉虚拟机会带来很多没必要的虚拟机相关的代码调用,增加复杂性),而我又没有运行Linux的物理机,怎么办呢?幸好在我玩硬件的时候入手了一块树莓派3B+,上面运行着完整的linux系统,而且我还把内核升级到5.x版本,更重要的是,在树莓派上可以尽情的编写、加载内核模块和修改内核,而不用担心把内核搞core dump,大不了快速重启或者重新烧写内核。

6b6859102d6b586a09ce6afb42bb39fc360.jpg  

       iotrace的源码如下,测试了7中io场景,主要为了测试普通模式、带O_DIRECT、O_SYNC标志、mmap模式、fsync和msync的调用路径等。

#define _GNU_SOURCE
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>

#define BUF_SIZE 1024

int main(void)
{
    int fd,size,len;
    int ret = 0;

    /*1. 普通io模式 */
    char * normal_write_buf = "normal io";
    len = strlen(normal_write_buf);
    char normal_read_buf[100] = {0};

    /* mark start */
    pid_t pid  = getpid();

    if ((fd = open("hello.c", O_CREAT | O_TRUNC | O_RDWR,0666 ))<0) {
        perror("open:");
        exit(1);
    }  

    /* 第一次wrirte,此时文件应该还不在page cache */
    if ((size = write( fd, normal_write_buf, len)) < 0){
        perror("write:");
        exit(1);
    }  

    /* 第二次wrirte,此时文件应该在page cache,因此路径会比上一次端 */
    if ((size = write( fd, normal_write_buf, len)) < 0){
        perror("write:");
        exit(1);
    }  
  
    lseek(fd, 0, SEEK_SET );
    
    if ((size = read( fd, normal_read_buf, len))<0) {
        perror("read:");
        exit(1);
    }  

    if(strncmp(normal_read_buf,normal_write_buf,len) != 0){
       perror("strncmp:");
       exit(1); 
    }

    /* 强制刷盘 */
    if(fsync(fd) < 0){
        perror("fysnc:");
        exit(1);
    }

    if ( close(fd) < 0 )    {
        perror("close:");
        exit(1);
    }  

    /*2. direct io模式*/
    
    char *direct_write_buf,*direct_read_buf;
    ret = posix_memalign((void **)&direct_write_buf, 512, BUF_SIZE);
    if (ret) {
        perror("posix_memalign:");
        exit(1);
    }

    ret = posix_memalign((void **)&direct_read_buf, 512, BUF_SIZE);
    if (ret) {
        perror("posix_memalign:");
        exit(1);
    }

    strcpy(direct_write_buf,"direct mode");
    len = strlen("direct mode");

    /* mark start */
    pid  = getpid();

    if ((fd = open("hello.c", O_CREAT | O_TRUNC | O_RDWR | O_DIRECT,0666 ))<0) {
        perror("open:");
        exit(1);
    }  

    if ((size = write(fd, direct_wri
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值