zoukankan      html  css  js  c++  java
  • 对memtester源码分析

    测试环境:Linux

        代码工具:source insight

        Memtester版本:4.3.0

        下载地址: http://pyropus.ca/software/memtester/

    Memtester是一个很好的内存测试工具。其代码也不是很复杂。最主要的就是memtester.c和test.c,这两文件。其他脚本是一些配置编译选项,对分析这个源码没有什么影响。

    我们先从memtester.c开始分析。

    在memtester.c的134行中有

    check_posix_system();

    pagesize = memtester_pagesize();

    pagesizemask = (ptrdiff_t) ~(pagesize - 1);

    printf("pagesizemask is 0x%tx ", pagesizemask);

     

    check_posix_system是确认所测试的系统支不支持标准的POSIX接口。下面很多函数需要用到标准的接口,如果不支持,则只有error。

    memtester_pagesize是用接口测试系统是32位还是64位,这涉及到其后的很多方方面面。

    Pagesizemask是得出最大的地址范围。

     

    下面很重要的就是:

    while ((opt = getopt(argc, argv, "p:d:")) != -1) {

    这句话是用来处理用户输入的数据的。关于getopt函数的解析,后面会有地址链接。

    case 'p': 是用来处理-p后面的参数的。

    physaddrbase = (off_t) strtoull(optarg, &addrsuffix, 16);

    上面这句话是将-p后面的参数转化数字并赋值给physaddrbase

    下面的就是一些错误处理。

     

    case 'd': 是用来处理-d后面的参数的。

    if (stat(optarg,&statbuf)) {

    上面这句话是用来获取所指定设备的参数细节的。

     

    接下来到203行

    if (device_specified && !use_phys) {

    这句话的意思是如果有-d选项,必须要有-p选项,否者就会出错。

     

    接下来就是处理错误和获取最后内存大小的参数。

    wantraw = (size_t) strtoul(argv[optind], &memsuffix, 0);

    上面的代码是将输入的参数转化为数字,并且赋值给wantraw.其后就是对这个参数的单位的处理。

    最后 wantmb = (wantbytes_orig >> 20); 将单位转化为M并赋值给wantmb。

     

    248-243行基本上是处理错误和获取循环的次数。最后输出。

     

    接下来代码分为两块 一块为有-p选项的处理方法。一块为没有-p选项的处理方法。

    最先处理的是有-p选项的情况。

    其中最重要的代码为:

    buf = (void volatile *) mmap(0, wantbytes, PROT_READ | PROT_WRITE,

    MAP_SHARED | MAP_LOCKED, memfd,

    physaddrbase);

     

    这一行是将内存的具体地址映射到具体的进程地址空间里面。这样便于处理其后的操作。具体每个参数的含义,其后会有讲解。

     

    其余的代码就是处理错误的情况。并且给申请到的内存加锁。加锁的原因是避免操作系统对内存进行一下操作。

     

    下面的:

    while (!done_mem) {

    就是处理没有-p选项的情况。

    buf = (void volatile *) malloc(wantbytes); 这句话是申请内存。

        余下的最重要的操作就是对齐和加锁了。关于对齐的原因是内存是以一块一块来申请和释放的。

          

        if ((size_t) buf % pagesize) {

    /* printf("aligning to page -- was 0x%tx ", buf); */

    aligned = (void volatile *) ((size_t) buf & pagesizemask) + pagesize;

    /* printf(" now 0x%tx -- lost %d bytes ", aligned,

    * (size_t) aligned - (size_t) buf);

    */

    bufsize -= ((size_t) aligned - (size_t) buf);

    }

        上面就是对齐的代码。

          

    if (mlock((void *) aligned, bufsize) < 0) {

    加锁的代码很简单,其余的都是处理错误的代码。

     

    到375行 进入正式的循环。 for(loop=1; ((!loops) || loop <= loops); loop++) {

    第一个分开测试的是 test_stuck_address

    这个比较简单 就是先在申请的内存里面写入数据,然后读出来与其对比。这样反复对比16次。

     

    for (i=0;;i++) {

    if (!tests[i].name) break;

    /* If using a custom testmask, only run this test if the

    bit corresponding to this test was set by the user.

    */

    if (testmask && (!((1 << i) & testmask))) {

    continue;

    }

    printf(" %-20s: ", tests[i].name);

    if (!tests[i].fp(bufa, bufb, count)) {

    printf("ok ");

    } else {

    exit_code |= EXIT_FAIL_OTHERTEST;

    }

    fflush(stdout);

    }

     

    最核心的就是上面的这段代码,这段代码不断的调用测试的函数,不断的输出测试的报告。

    不断调用的代码为:

    if (!tests[i].fp(bufa, bufb, count)) {

    这里利用了函数的指针,用法比较经典。

  • 相关阅读:
    闭包
    保存数据
    Browers Object Model
    JavaScript中的null和undefined
    魔法查询函数
    《黑客与画家》 读书感想
    CakePHP查询数据
    HDFS写入和读取流程
    回调函数
    JAVA中的指针
  • 原文地址:https://www.cnblogs.com/pslfree/p/4451091.html
Copyright © 2011-2022 走看看