Androidメモリ圧力テストツール(memtester移植)
この記事は次のように転載されています.
https://blog.csdn.net/csh86277516/article/details/52584390
https://blog.csdn.net/sweetmilkcake/article/details/83241592
DRRリファレンス配置OKの後、まずDDRに対して圧力テストを行ってDDRの安定性を保証する必要があります.そうしないと、DDRに問題が発生した後、奇妙な問題を引き起こしやすく、問題の原因を分析するのは難しいです.
memtesterの説明:
memtesterは主にメモリ安定性の公式サイトをテストするために使用されます.http://pyropus.ca/software/memtester/バージョン:memtester-4.3.0.tar.gz(現在の最新バージョン-2018.10.21)は、Linuxシステムのバイナリファイルの大部分をプリコンパイルし、直接使用することができ、Androidシステムに移植しました.
移植する
まずMakefileファイルがLinuxシステムでどのようにコンパイルされているかを見てみましょう.ここでmemtester-4.3.0を移植します.tar.gz圧縮パッケージのファイルは変更する必要はありません.
上のMakefileから分かるように、memtesterをコンパイルするにはmemtesterをコンパイルする必要がある.cとtests.cと関連するヘッダファイルなので、次のAndroidを書くことができます.mkファイル.
memtester-4.3.0.tar.gzはsystem/core/ディレクトリの下に解凍し、memtesterディレクトリと命名し、Android.mkは同じディレクトリに配置されます.ファイルは以下のように表示されます.
まずモジュールにコンパイルしてテストします.
そして
最後にデバイスに追加します.mkでは、システムのフルコンパイル時にシステムにパッケージ化されるため、deviceが必要である.mkで定義する
テスト
使用方法:Usage:memtester[-p physaddrbase[-d device][B|K|M|G][loops]例えばmemtester 5 M 1、対応テスト1回5 Mメモリ
システムの空きメモリを表示し、251 M
デモンストレーション:memtester 5 M 1、ここではデモンストレーションだけで、5 Mメモリを1回テストします.実際のプロジェクトでは、この2つのパラメータはできるだけ大きくなければなりません.
Android APKの応用
APKはコードにシステム権限を与える:
ファイルをandroidコードで携帯電話system/binの下にプリセットすると、携帯電話にスクリプト環境が設定されます.
linux組み込み環境での使用:
このスクリプトを実行します.
sh memory.sh -c -l -m
-c:memtesterをいくつか実行
-l:何回か実行
-m:どれだけのメモリをテストして、直接テストの総数を記入すればいいです.プログラムは自動的にmemtesterごとに平均値を割り当てます.このように私たちの計算を省いて、いくつかの端末を開く必要はありません.単位MB、例えば私は4コアCPU、32 Gメモリの機械を持っていて、このように運行することができます.
sh memory.sh -c 4 -l 1 -m 3100
このスクリプトでは、24時間実行したいなど、時間を限定することもできます.
sh memory.sh -t 24h -c 4 -m 3100
https://blog.csdn.net/csh86277516/article/details/52584390
https://blog.csdn.net/sweetmilkcake/article/details/83241592
DRRリファレンス配置OKの後、まずDDRに対して圧力テストを行ってDDRの安定性を保証する必要があります.そうしないと、DDRに問題が発生した後、奇妙な問題を引き起こしやすく、問題の原因を分析するのは難しいです.
memtesterの説明:
memtesterは主にメモリ安定性の公式サイトをテストするために使用されます.http://pyropus.ca/software/memtester/バージョン:memtester-4.3.0.tar.gz(現在の最新バージョン-2018.10.21)は、Linuxシステムのバイナリファイルの大部分をプリコンパイルし、直接使用することができ、Androidシステムに移植しました.
移植する
まずMakefileファイルがLinuxシステムでどのようにコンパイルされているかを見てみましょう.ここでmemtester-4.3.0を移植します.tar.gz圧縮パッケージのファイルは変更する必要はありません.
memtester: \
$(OBJECTS) memtester.c tests.h tests.c tests.h conf-cc Makefile load extra-libs
./load memtester tests.o `cat extra-libs`
上のMakefileから分かるように、memtesterをコンパイルするにはmemtesterをコンパイルする必要がある.cとtests.cと関連するヘッダファイルなので、次のAndroidを書くことができます.mkファイル.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := memtester.c tests.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_MODULE := memtester
include $(BUILD_EXECUTABLE)
memtester-4.3.0.tar.gzはsystem/core/ディレクトリの下に解凍し、memtesterディレクトリと命名し、Android.mkは同じディレクトリに配置されます.ファイルは以下のように表示されます.
~/project$ tar -zxvf memtester-4.3.0.tar.gz -C AndroidO_8827LGO_20181207/system/core/
~/project$ cd AndroidO_8827LGO_20181207/system/core/memtester
~/project/AndroidO_8827LGO_20181207/system/core/memtester$tree
.
├── Android.mk
├── BUGS
├── CHANGELOG
├── conf-cc
├── conf-ld
├── COPYING
├── extra-libs.sh
├── find-systype.sh
├── make-compile.sh
├── Makefile
├── make-load.sh
├── make-makelib.sh
├── memtester.8
├── memtester.c
├── memtester.h
├── README
├── README.tests
├── sizes.h
├── tests.c
├── tests.h
├── trycpp.c
├── types.h
└── warn-auto.sh
まずモジュールにコンパイルしてテストします.
~/project/AndroidO_8827LGO_20181207/system/core/memtester$ mm -j8
........
5 warnings generated.
[100% 6/6] Install: out/target/product/petrel-p1/system/bin/memtester
make: Leaving directory '/home/lemon/Develop/OrangePi_Lite2/android'
#### make completed successfully ####
そして
adb push memtester /system/bin/
adb shell "chmod 777 /system/bin/memtester"
adb shell memtester
最後にデバイスに追加します.mkでは、システムのフルコンパイル時にシステムにパッケージ化されるため、deviceが必要である.mkで定義する
PRODUCT_PACKAGES += memtester
テスト
使用方法:Usage:memtester[-p physaddrbase[-d device][B|K|M|G][loops]例えばmemtester 5 M 1、対応テスト1回5 Mメモリ
PS C:\Users\zhaojr\Documents\adb> ./adb root
adbd is already running as root
PS C:\Users\zhaojr\Documents\adb> ./adb remount
remount succeeded
PS C:\Users\zhaojr\Documents\adb> ./adb shell
8227LGO_demo:/ # memtester
memtester version 4.3.0 (32-bit)
Copyright (C) 2001-2012 Charles Cazabon.
Licensed under the GNU General Public License version 2 (only).
pagesize is 4096
pagesizemask is 0xfffff000
need memory argument, in MB
Usage: memtester [-p physaddrbase [-d device]] [B|K|M|G] [loops]
システムの空きメモリを表示し、251 M
8227LGO_demo:/ # free -h
free -h
total used free shared buffers
Mem: 443M 432M 11M 328K 576K
-/+ buffers/cache: 431M 12M
Swap: 329M 73M 256M
8227LGO_demo:/ #
デモンストレーション:memtester 5 M 1、ここではデモンストレーションだけで、5 Mメモリを1回テストします.実際のプロジェクトでは、この2つのパラメータはできるだけ大きくなければなりません.
8227LGO_demo:/ # memtester 5M 1
memtester version 4.3.0 (32-bit)
Copyright (C) 2001-2012 Charles Cazabon.
Licensed under the GNU General Public License version 2 (only).
pagesize is 4096
pagesizemask is 0xfffff000
want 5MB (5242880 bytes)
got 5MB (5242880 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
Done.
8227LGO_demo:/ #
Android APKの応用
:
package com.example.ddr;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
public class MainActivity extends Activity {
private static final String TAG = null;
private static TextView test_result = null;
static String test_setText = "";
static int Testing_times = 0;
String asdddd1 = "screencap -p /sdcard/screen1.png";
String asdddd2 = "screencap -p /sdcard/screen2.png";
String dir = "/data/data/com.example.ddr/files/";
Context ctxDealFile = null;
String oldPath1 = "file:///android_asset/memtester";
String oldPath2 = "file:///memtester";
String newPath1 = Environment.getRootDirectory().getPath();//"system/";//"system/bin/";
String MemtesterFileName = "/data/memtester_result.txt";
String simpleMemtester_1 = "memtester -b -g -f 1190400--1190400 64M 1";
String complexMemtester_1 = "memtester -b -j 0 -k 4 -g -l 40 -a 64M";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
test_result = (TextView)findViewById(R.id.Memtester_01);
System.out.println("csh ddr star");
Memtester(simpleMemtester_1);
Memtester(complexMemtester_1);
//ReadTxtFile(MemtesterFileName);
//copyFile(oldPath2,newPath1);
/*String uiFileName = "memtester";
try {
ctxDealFile = this.createPackageContext("com.example.ddr",
Context.CONTEXT_IGNORE_SECURITY);
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
deepFile(ctxDealFile, uiFileName);*/
}
public void deepFile(Context ctxDealFile, String path) {
try {
String str[] = ctxDealFile.getAssets().list(path);
if (str.length > 0) {
System.out.println("csh deepFile 1");
File file = new File("/system/" + path);
file.mkdirs();
for (String string : str) {
path = path + "/" + string;
System.out.println("zhoulc:\t" + path);
// textView.setText(textView.getText()+"\t"+path+"\t");
deepFile(ctxDealFile, path);
path = path.substring(0, path.lastIndexOf('/'));
}
} else {
System.out.println("csh deepFile 2");
InputStream is = ctxDealFile.getAssets().open(path);
//FileOutputStream fos = new FileOutputStream(new File(getFilesDir().getAbsolutePath()+"/memtester"));
FileOutputStream fos = ctxDealFile.openFileOutput(path,
ctxDealFile.MODE_WORLD_READABLE |ctxDealFile.MODE_WORLD_WRITEABLE);
byte[] buffer = new byte[1024];
int count = 0;
while (true) {
count++;
int len = is.read(buffer);
if (len == -1) {
break;
}
fos.write(buffer, 0, len);
}
is.close();
fos.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Process p;
Process p2;
try {
p = Runtime.getRuntime().exec("chmod 777 " + dir + path);
p.waitFor();
p2 = Runtime.getRuntime().exec("cp /data/data/com.example.ddr/files/memtester > /data/data/com.example.ddr/files/memtester2");
p2.waitFor();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void Memtester(String command)
{
Runtime r = Runtime.getRuntime();
Process p;
Testing_times ++;
try {
p = r.exec(command);
BufferedReader br = new BufferedReader(new InputStreamReader(p
.getInputStream()));
String inline;
while ((inline = br.readLine()) != null) {
System.out.println(inline);
}
br.close();
p.waitFor();
ReadTxtFile(MemtesterFileName);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/*public void Memtester2(String command)
{
DataOutputStream os = null;
Process p;
try{
p =Runtime.getRuntime().exec(isRoot?COMMAND_SU:COMMAND_SH);
os = new DataOutputStream(p.getOutputStream());
for (String command:commands){
if(command==null){
continue;
}
//donnotuseos.writeBytes(commmand),avoidchinesecharseterror
os.write(command.getBytes());
os.writeBytes(COMMAND_LINE_END);
os.flush();
try{
}catch(Exception e){
e.printStackTrace();
}
}*/
public static String ReadTxtFile(String strFilePath)
{
String path = strFilePath;
String content = "";
File file = new File(path);
if (file.isDirectory())
{
Log.d("TestFile", "The File doesn't not exist.");
}
else
{
try {
InputStream instream = new FileInputStream(file);
if (instream != null)
{
InputStreamReader inputreader = new InputStreamReader(instream);
BufferedReader buffreader = new BufferedReader(inputreader);
String line;
while (( line = buffreader.readLine()) != null) {
content += line + "
";
//if(inline.equals("SUCCESS")){
if(line.indexOf("SUCCESS")!=-1){
test_setText += Testing_times + " : " + "SUCCESS
";
test_result.setText(test_setText);
}else{
test_setText += Testing_times + " : " + "FAIL
";
test_result.setText(test_setText);
}
}
instream.close();
}
}
catch (java.io.FileNotFoundException e)
{
Log.d("TestFile", "The File doesn't not exist.");
}
catch (IOException e)
{
Log.d("TestFile", e.getMessage());
}
}
return content;
}
/*
private void simpleMemtester(){
Log.d(TAG, "do simple memory test");
openCmdList1.clear();
try {
openCmdList1.add("memtester -b -g -f 1190400--1190400 64M 1");
exec(openCmdList1);
memoryTestResult();
} catch (Exception e) {
e.printStackTrace();
}
}
private void complexMemtester(){
Log.d(TAG, "do complex memory test");
openCmdList1.clear();
try {
openCmdList1.add("memtester -b -j 0 -k 4 -g -l 40 -a 64M");
exec(openCmdList1);
memoryTestResult();
} catch (Exception e) {
e.printStackTrace();
}
}
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
APKはコードにシステム権限を与える:
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_CERTIFICATE := platform
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_SDK_VERSION := current
LOCAL_PACKAGE_NAME := ddr
include $(BUILD_PACKAGE)
# Use the following include to make our test apk.
include $(call all-makefiles-under,$(LOCAL_PATH))
UID :
ファイルをandroidコードで携帯電話system/binの下にプリセットすると、携帯電話にスクリプト環境が設定されます.
CSH_DDR_PATH := packages/apps/ddr/assets
PRODUCT_COPY_FILES := $(CSH_DDR_PATH)/memtester:system/bin/memtester $(PRODUCT_COPY_FILES)
linux組み込み環境での使用:
#!/bin/sh
# Memory Tester Scripts
# by KaKa
# version = date
VERSION="Fri Oct 19 11:56:57 CST 2007"
# trap for irruptions
MEMTESTER=${PWD}/memtester
PPIDKILL=$$
SIDKILL=$$
trap "pkill -9 -P ${PPIDKILL};kill -9 $$" INT
trap "pkill -9 -P ${PPIDKILL};kill -9 $$" KILL
cat <&2
Version: ${VERSION}
PID: $$
PPIDKILL: ${PPIDKILL}
SIDKILL: ${PPIDKILL}
EOF_vpps
CORE_NUM=$(grep -i ^processor /proc/cpuinfo|wc -l)
MEMTESTERCOPY=${CORE_NUM}
MEM_TOTAL_K=$(awk '/^MemTotal/{print $2}' /proc/meminfo)
MEM_RESERVE_PERCENTAGE=$((1000*50/1024))
MEM_RESERVED=$((MEM_TOTAL_K/1024*MEM_RESERVE_PERCENTAGE/1000))
MEM_TOTAL_TOBETESTED=$((MEM_TOTAL_K/1024-MEM_RESERVED))
MEM_PER_COPY=$((MEM_TOTAL_TOBETESTED/MEMTESTERCOPY))
RUN_DURATION_TIME=0
RUN_LOOPS=-1
RUN_DURATION_TIME_FLAG=0
RUN_LOOPS_FLAG=0
DDPERCOPY_TIME=6s
LOGDIR=/tmp/memtester-log-${$}
mkdir -p ${LOGDIR}
show_help () {
cat <&2
Version: ${VERSION}
Usage: $(basename ${0})
-r Directory: the root location of memtester binary file
-c NUMBER: the copies of memtester should be run
-m NUMBER: how many memory should be tested totally (in MB)
-t TIME: duration mode, how long will the tests go
-l NUMBER: loops mode,how many loops will each memtester should go
The option -t and -l are exclusive, which means tests could work
only with 1. duration mode or 2. loops mode
RUN 4 copies memtester with in 24 hours, to test total 4000 MB memory:
$(basename ${0}) -t 24h -c 4 -m 4000
RUN 2 copies memtester with in 1 hours, to test total 4000 MB memory:
$(basename ${0}) -t 1h -c 4 -m 4000
RUN 4 copies memtester with in 2 loops, to test total 3600 MB memory:
$(basename ${0}) -l 2 -c 4 -m 3600
-V/-h/-H: show this info.
HELPEOF
exit 0
}
while getopts :c:m:t:l:r:p:hHVvx OPTION
do
case ${OPTION} in
c)
#echo "-c ${OPTARG}"
MEMTESTERCOPY=${OPTARG}
;;
m)
#echo "-m ${OPTARG} MB"
MEM_TOTAL_TOBETESTED=${OPTARG}
MEM_RESERVED=$((MEM_TOTAL_K/1024-MEM_TOTAL_TOBETESTED))
;;
t)
#echo "-t ${OPTARG}"
[ 0 -ne ${RUN_LOOPS_FLAG} ] && echo "-t and -l are exclusive." && exit 222
RUN_DURATION_TIME=${OPTARG}
RUN_DURATION_TIME_FLAG=1
;;
l)
#echo "-l ${OPTARG}"
[ 0 -ne ${RUN_DURATION_TIME_FLAG} ] && echo && echo "-t and -l are exclusive." && show_help && echo && exit 223
RUN_LOOPS=${OPTARG};
RUN_LOOPS_FLAG=1
;;
d)
#echo "-r ${OPTARG}"
MEMTESTER=${OPTARG}/memtester
;;
p)
#echo "-p ${OPTARG}"
MEMTESTER=${OPTARG}
;;
V|h|H)
show_help
;;
v)
set -v
;;
x)
set -x
;;
?)
echo "Error...";
echo "?Unknown args..."
exit 224
;;
*)
#echo "*Unknown args..."
esac
done
#exit
[ 0 -eq ${RUN_DURATION_TIME_FLAG} ] && [ 0 -eq ${RUN_LOOPS_FLAG} ] &&
echo && echo "Please specified which mode should we run... -t or -l" &&
show_help && echo && exit 225
MEM_PER_COPY=$((MEM_TOTAL_TOBETESTED/MEMTESTERCOPY))
echo "Mem total: " $((MEM_TOTAL_K/1024)) MB
echo "Core total: "${CORE_NUM}
echo "Memtester copys: " ${MEMTESTERCOPY}
echo "Mem per copy: "${MEM_PER_COPY}
echo "Mem total to used: "${MEM_TOTAL_TOBETESTED} MB
if [ ${MEM_RESERVED} -lt 1 ]; then
echo "Mem reserved: -- No more memory reserved..."
else
echo "Mem reserved: "${MEM_RESERVED} MB
fi
#exit
# GOGOGO
if [ 0 -ne ${RUN_DURATION_TIME_FLAG} ]; then
echo "Run within a duration: ${RUN_DURATION_TIME}"
elif [ 0 -ne ${RUN_LOOPS_FLAG} ]; then
echo "Run within a loop: ${RUN_LOOPS}"
fi
echo "Working directory: " $PWD
echo "Memtester: " ${MEMTESTER}
echo "LOGs directory: " $LOGDIR
echo
echo -n "Jobs started at date: "
date #+%Y/%m/%d\ %H:%M
echo
#exit
########################
# Run testing within a duration time.
if [ 0 -ne ${RUN_DURATION_TIME_FLAG} ]; then
# prepareing the sleeping killers
sleep ${RUN_DURATION_TIME}
echo -n "End of testing(TIMEOUT)... "
echo "KILL CHILD" && kill -9 $(pgrep -P ${PPIDKILL} memtester) && echo
"Childen processes - KILLED."
# attention to how the memtesters are forked...
echo "KILL PARENT" && kill $$ && echo "KILLED." &
echo "Finished the memtester"
echo -n "Jobs finished at date: "
date #+%Y/%m/%d\ %H:%M
fi &
echo -n "Waiting (PID: $$) for ${MEMTESTERCOPY}
memtesters(${MEM_PER_COPY}MB for each). "
if [ 0 -ne ${RUN_DURATION_TIME_FLAG} ]; then
echo -n "For time: ${RUN_DURATION_TIME} "
fi
if [ 0 -ne ${RUN_LOOPS_FLAG} ]; then
echo -n "For loops: ${RUN_LOOPS} "
fi
echo "..."
while true
do
MEMTESTER_NUM=0
echo -n "{"
while [ ${MEMTESTER_NUM} -lt ${MEMTESTERCOPY} ]
do
echo -n " ${MEMTESTER_NUM} "
if [ 0 -ne ${RUN_DURATION_TIME_FLAG} ]; then
RUN_LOOPS=0
fi
${MEMTESTER} ${MEM_PER_COPY} ${RUN_LOOPS} 2>&1 >> ${LOGDIR}/${MEMTESTER_NUM}.log &
# set loops = 0 to make memtester run loop infinitely...
# .pogo version will run only one loop by default
sleep ${DDPERCOPY_TIME}
MEMTESTER_NUM=$(expr $MEMTESTER_NUM + 1)
done
echo -n "}"
wait
[ 0 -ne ${RUN_LOOPS_FLAG} ] && break
# memtesters' loops...
done
########################
echo
echo -n "End of testing(Excution ended)... "
pkill -9 -P ${PPIDKILL}
kill $$
echo "Finished the memtester"
echo -n "Jobs finished at date: "
date #+%Y/%m/%d\ %H:%M
このスクリプトを実行します.
sh memory.sh -c -l -m
-c:memtesterをいくつか実行
-l:何回か実行
-m:どれだけのメモリをテストして、直接テストの総数を記入すればいいです.プログラムは自動的にmemtesterごとに平均値を割り当てます.このように私たちの計算を省いて、いくつかの端末を開く必要はありません.単位MB、例えば私は4コアCPU、32 Gメモリの機械を持っていて、このように運行することができます.
sh memory.sh -c 4 -l 1 -m 3100
このスクリプトでは、24時間実行したいなど、時間を限定することもできます.
sh memory.sh -t 24h -c 4 -m 3100