<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          嵌入式里如何給內(nèi)存做壓力測試?不妨試試memtester

          共 10655字,需瀏覽 22分鐘

           ·

          2021-04-24 01:38



          大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家介紹的是內(nèi)存讀寫正確性壓力測試程序memtester。

          在嵌入式系統(tǒng)中,內(nèi)存(RAM)的重要性不言而喻,系統(tǒng)性能及穩(wěn)定性都與內(nèi)存息息相關(guān)。關(guān)于內(nèi)存性能有很多個不同指標(biāo),其中最基礎(chǔ)的指標(biāo)便是訪問可靠性(即讀寫的正確性),只有穩(wěn)定可靠的內(nèi)存訪問才能確保系統(tǒng)正常運行。很多時候簡單地內(nèi)存讀寫測試并不能發(fā)現(xiàn)隱藏的問題,因此我們需要一個完備的內(nèi)存訪問壓力測試程序,今天痞子衡就和大家詳細(xì)聊一聊memtester。

          一、內(nèi)存性能測試程序集

          在講memtester之前,痞子衡先給大家科普一下Linux系統(tǒng)下常用的內(nèi)存性能測試工具,它們分別是mbw、memtester、lmbench、sysbench。這幾個測試工具(程序)各有側(cè)重點:

          內(nèi)存帶寬測試工具            --mbw;
          內(nèi)存壓力測試工具 --memtester;
          內(nèi)存綜合性能測試工具 --lmbench;
          內(nèi)存申請與讀寫速度測試工具 --sysbench;

          二、memtester程序

          memtester是Simon Kirby在1999年編寫的測試程序(v1版),后來由Charles Cazabon一直維護(hù)更新(v2及之后版本),主要面向Unix-like系統(tǒng),官方主頁上介紹的是“A userspace utility for testing the memory subsystem for faults.”,其實就是為了測試內(nèi)存(主要DDR)的讀寫訪問可靠性(僅正確性,與速度性能無關(guān)),這是驗證板級硬件設(shè)備必不可少的一項測試。

          整個memtester測試的視角就是從用戶的角度來看的,從用戶角度設(shè)立不同的測試場景即測試用例,然后針對性地進(jìn)行功能測試,注意是從系統(tǒng)級來測試,也就是說關(guān)注的不單單是內(nèi)存顆粒了,還有系統(tǒng)板級的連線、IO性能、PCB等等相關(guān)的因素,在這些因素的影響下,內(nèi)存是否還能正常工作。

          2.1 獲取程序

          memtester程序的最新版本是4.5.0,早期的v1/v2/v3版本目前下載不到了,2012年Charles Cazabon重寫了程序并發(fā)布了全新v4.0.0,此后一直不定期更新,v4.x也是當(dāng)前最流行的版本。

          核心程序下載:http://pyropus.ca/software/memtester/

          核心程序包下載后,在\memtester-4.5.0\下可找到源代碼。詳細(xì)源文件目錄如下:

          \memtester-4.5.0
          \memtester.h
          \memtester.c --主程序入口
          \sizes.h --關(guān)于系統(tǒng)位數(shù)(32/64bit)的一些定義
          \types.h --所用數(shù)據(jù)類型的定義
          \tests.h
          \tests.c --測試算法子程序

          如果是移植到ARM Cortex-M平臺下裸系統(tǒng)運行,一般只需要簡單修改memtester.c文件即可,其他源文件就是一些頭文件包含方面的改動,memtester本身并沒有太多移植工作,其源碼本是用作在Unix-like系統(tǒng)上運行的,而在嵌入式系統(tǒng)里運行僅需要把一些跟系統(tǒng)平臺相關(guān)的代碼刪除即可,此外就是打印函數(shù)的實現(xiàn)。

          2.2 配置參數(shù)

          memtester源碼里的配置選項主要是如下五個宏:

          /* 如下需用戶自定義 */
          ULONG_MAX -- 確定系統(tǒng)是32bit還是64bit
          TEST_NARROW_WRITES -- 確定是否要包含8/16 bit寫測試

          /* 如下借助linux頭文件 */
          _SC_VERSION -- posix system版本檢查
          _SC_PAGE_SIZE -- 內(nèi)存page大小獲取
          MAP_LOCKED -- Linux里mmap里的swap特性

          2.3 程序解析

          讓我們嘗試分析memtester主函數(shù)入口main,main()函數(shù)最開始都是一些輸入?yún)?shù)解析,其實主要就是為了獲取三個重要變量:內(nèi)存測試起始地址、內(nèi)存測試總長度、壓力測試循環(huán)次數(shù),有了這三個變量值之后便開始逐一跑tests.c文件里各項測試算法小函數(shù):

          struct test {
              char *name;
              int (*fp)();
          };

          struct test tests[] = {
              { "Random Value", test_random_value },
              { "Compare XOR", test_xor_comparison },
              { "Compare SUB", test_sub_comparison },
              { "Compare MUL", test_mul_comparison },
              { "Compare DIV",test_div_comparison },
              { "Compare OR", test_or_comparison },
              { "Compare AND", test_and_comparison },
              { "Sequential Increment", test_seqinc_comparison },
              { "Solid Bits", test_solidbits_comparison },
              { "Block Sequential", test_blockseq_comparison },
              { "Checkerboard", test_checkerboard_comparison },
              { "Bit Spread", test_bitspread_comparison },
              { "Bit Flip", test_bitflip_comparison },
              { "Walking Ones", test_walkbits1_comparison },
              { "Walking Zeroes", test_walkbits0_comparison },
          #ifdef TEST_NARROW_WRITES    
              { "8-bit Writes", test_8bit_wide_random },
              { "16-bit Writes", test_16bit_wide_random },
          #endif
              { NULLNULL }
          };

          /* Function definitions */
          void usage(char *me) {
              fprintf(stderr"\n"
                      "Usage: %s [-p physaddrbase [-d device]] <mem>[B|K|M|G] [loops]\n",
                      me);
              exit(EXIT_FAIL_NONSTARTER);
          }

          int main(int argc, char **argv) {
              ul loops, loop, i;
              size_t bufsize, halflen, count;
              void volatile *buf, *aligned;
              ulv *bufa, *bufb;
              ul testmask = 0;

              // 省略若干變量定義代碼

              printf("memtester version " __version__ " (%d-bit)\n", UL_LEN);
              printf("Copyright (C) 2001-2020 Charles Cazabon.\n");
              printf("Licensed under the GNU General Public License version 2 (only).\n");
              printf("\n");

              // 省略若干初始檢查代碼
              // 從輸入?yún)?shù)里獲取physaddrbase計算出內(nèi)存測試起始地址aligned
              // 從輸入?yún)?shù)里獲取mem及B|K|M|G計算出內(nèi)存測試總長度bufsize

              halflen = bufsize / 2;
              count = halflen / sizeof(ul);
              bufa = (ulv *) aligned;
              bufb = (ulv *) ((size_t) aligned + halflen);

              // 壓力測試的重要變量, loops即重復(fù)次數(shù)
              for(loop=1; ((!loops) || loop <= loops); loop++) {
                  printf("Loop %lu", loop);
                  if (loops) {
                      printf("/%lu", loops);
                  }
                  printf(":\n");
                  printf("  %-20s: ""Stuck Address");
                  fflush(stdout);

                  // 第一個測試 stuck_address
                  if (!test_stuck_address(aligned, bufsize / sizeof(ul))) {
                       printf("ok\n");
                  } else {
                      exit_code |= EXIT_FAIL_ADDRESSLINES;
                  }

                  // 遍歷tests.c里的所有測試子程序
                  for (i=0;;i++) {
                      if (!tests[i].name) break;
                      if (testmask && (!((1 << i) & testmask))) {
                          continue;
                      }
                      printf("  %-20s: ", tests[i].name);
                      // 可以看到將內(nèi)存測試總空間一分為二,傳給子程序做處理的
                      if (!tests[i].fp(bufa, bufb, count)) {
                          printf("ok\n");
                      } else {
                          exit_code |= EXIT_FAIL_OTHERTEST;
                      }
                      fflush(stdout);
                      /* clear buffer */
                      memset((void *) buf, 255, wantbytes);
                  }
                  printf("\n");
                  fflush(stdout);
              }
          }

          tests.c文件里才是最核心的壓力測試算法子程序,一共17個函數(shù),涉及各種內(nèi)存訪問經(jīng)驗操作,具體可以看網(wǎng)上的一篇詳細(xì)解析文章 https://www.jianshu.com/p/ef203c360c4f。

          測試函數(shù)名測試作用
          test_stuck_address先全部把地址值交替取反放入對應(yīng)存儲位置,然后再讀出比較,重復(fù)n次
          test_random_value等效test_random_comparison(bufa, bufb, count):數(shù)據(jù)敏感型測試用例
          test_xor_comparison與test_random_value比多了個異或操作
          test_sub_comparison與test_random_value比多了個減法操作
          test_mul_comparisone與test_random_value比多了個乘法操作
          test_div_comparison與test_random_value比多了個除法操作
          test_or_comparison在test_random_comparison()里面合并了
          test_and_comparison在test_random_comparison()里面合并了
          test_seqinc_comparison是 test_blockseq_comparison的一個子集;模擬客戶壓力測試場景
          test_solidbits_comparison固定全1后寫入兩個buffer,然后讀出比較,然后全0寫入讀出比較;這就是Zero-One算法
          test_blockseq_comparison一次寫一個count大小的塊,寫的值是拿byte級的數(shù)填充32bit,然后取出對比,接著重復(fù)256次;也是壓力用例,只是次數(shù)變多了;
          test_checkerboard_comparison把設(shè)定好的幾組Data BackGround,依次寫入,然后讀出比較
          test_bitspread_comparison還是在32bit里面移動,只是這次移動的不是單單的一個0或者1,而是兩個1,這兩個1之間隔著兩個空位/td>
          test_bitflip_comparison也是32bit里面的一個bit=1不斷移動生成data pattern然后,每個pattern均執(zhí)行
          test_walkbits1_comparison與test_walkbits0_comparison同理
          test_walkbits0_comparison就是bit=1的位置在32bit里面移動,每移動一次就全部填滿buffer,先是從低位往高位移,再是從高位往低位移動
          test_8bit_wide_random以char指針存值,也就是每次存8bit,粒度更細(xì);
          test_16bit_wide_random以unsigned short指針存值,也就是每次存16bit,不同粒度檢測;

          2.4 結(jié)果格式

          在Unix-like系統(tǒng)下使用make && make install命令進(jìn)行編譯可得到一個可執(zhí)行的memtester,可以隨便執(zhí)行memtester 10M 1,即申請10M的內(nèi)存測試1次,結(jié)果如下:

          [root@as150 ~] memtester 10M 1

          memtester version 4.5.0 (64-bit)
          Copyright (C) 2001-2020 Charles Cazabon.
          Licensed under the GNU General Public License version 2 (only).

          pagesize is 4096
          pagesizemask is 0xfffffffffffff000
          want 10MB (10485760 bytes)
          got 10MB (10485760 bytes), trying mlock ...locked.
          Loop 1/1:
          Stuck Address: ok
          Random Value: ok
          Compare XOR: ok
          Compare SUB: ok
          Compare MUL: ok
          Compare DIV: ok
          Compare OR: ok
          Compare AND: ok
          Sequential Increment: ok
          Solid Bits: ok
          Block Sequential: ok
          Checkerboard: ok
          Bit Spread: ok
          Bit Flip: ok
          Walking Ones: ok
          Walking Zeroes: ok
          8-bit Writes: ok
          16-bit Writes: ok

          Done.

          至此,內(nèi)存讀寫正確性壓力測試程序memtester痞子衡便介紹完畢了,掌聲在哪里~~~






          推薦閱讀:
          專輯|Linux文章匯總
          專輯|程序人生
          專輯|C語言
          我的知識小密圈

          關(guān)注公眾號,后臺回復(fù)「1024」獲取學(xué)習(xí)資料網(wǎng)盤鏈接。

          歡迎點贊,關(guān)注,轉(zhuǎn)發(fā),在看,您的每一次鼓勵,我都將銘記于心~



          瀏覽 59
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  色就是色欧美setu | 久久久久久无码日韩欧美电影 | 日韩一级成人影片 | 强开小嫩苞一区二区三区视频 | A片免费网站在线观看 |