2017年12月28日 星期四

[QEMU] 模擬一個實際的 ARM Linux 嵌入式系統

本篇紀錄手動自行建置系統的過程。若想盡可能的自動化進行建置,請使用 yocto 或是 buildroot。

1. 安裝 qemu
$ sudo apt-get install qemu-system-arm

2. 建立測試目錄,下載 toochain 以及 kernel
$ mkdir qemu_test
$ cd qemu_test
$ wget https://releases.linaro.org/components/toolchain/binaries/6.4-2017.11/arm-linux-gnueabihf/ gcc-linaro-6.4.1-2017.11-i686_arm-linux-gnueabihf.tar.xz
$ tar xvf gcc-linaro-6.4.1-2017.11-i686_arm-linux-gnueabihf.tar.xz
$ wget https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.14.tar.xz
$ tar xvf ./linux-4.14.tar.xz

3. 修改環境變數
$ vi ~/.bashrc
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
export PATH=$PATH:/home/albert/qemu_test/gcc-linaro-6.4.1-2017.11-i686_arm-linux-gnueabihf/bin
$ source ~/.bashrc 

4. 編譯 kernel
$ cd linux-4.14
$ vi arch/arm/configs/vexpress_defconfig
參考此篇 http://awe31402-blog.logdown.com/posts/528593 
$ make vexpress_defconfig
$ make clean;make
$ ls -al arch/arm/boot/dts/*.dtb
此時應該會出現 vexpress-v2p-ca9.dtb
$ ls -al ./arch/arm/boot/
此處應該會出現 zImage

5. 建立虛擬網卡介面
$ sudo apt-get install uml-utilities
$ sudo tunctl -t tap0 -u albert
$ sudo ifconfig tap0 192.168.7.1 netmask 255.255.255.0 promisc

6. 建立 nfs 使用的 rootfs (之前已經透過 yocto 建立,此步驟省略)

7. 執行程式
$ cd ~/qemu_test
$ QEMU_AUDIO_DRV=none qemu-system-arm -kernel ./linux-4.14/arch/arm/boot/zImage  -M vexpress-a9 -m 512 \
-dtb ./linux-4.14/arch/arm/boot/dts/vexpress-v2p-ca9.dtb \
-append "/dev/nfs nfsroot=192.168.7.1:/srv/nfs/qemuarm rw ip=192.168.7.2:192.168.7.1:255.255.255.0 console=ttyAMA0,115200" \
-smp 1 -net nic,vlan=0 -net tap,vlan=0,ifname=tap0,script=no -nographic

參考資料:
http://awe31402-blog.logdown.com/posts/528593
http://daydreamer.idv.tw/rewrite.php/read-42.html




2017年7月9日 星期日

mp3 檔案移除封面資訊

現在網路上取得的 mp3 檔案,大多已經幫忙作了封面圖片。
但是在比較舊的車用多媒體機器上(例如:舊款的 skoda),其實是無法辨識此資訊的。因此需要先將此資訊移除才能在車機上播放。

以下提供一個 script,可以批次移除所有 mp3 檔案的封面圖片。

#!/bin/bash 
for i in *.mp3 
do ffmpeg -i "$i" -vn -codec:a copy -map_metadata -1 "../${i%mp3}mp3" 
done


2017年5月14日 星期日

mtrace 與 libmemleak

本篇參考 https://en.wikibooks.org/wiki/Linux_Applications_Debugging_Techniques/Leaks
測試文中兩個偵測 memory leakage 的方法,分別是 mtrace 與 libmemleak,並且紀錄測試過程。

1. 使用 mtrace
a. 針對單一程式: 
a1. 在程式碼中 #include  ,並且在需要檢視 leakage 的區間分別加入 mtrace(),muntrace(),程式碼範例可參考此連結。 
a2. 編譯以及偵測方法
$ gcc -g dleaker.c -o dleaker
$ MALLOC_TRACE=test1/mtrace.plain.log  ./dleaker
$ mtrace  ./dleaker  test1/mtrace.plain.log  > test1/mtrace.plain.leaks.log 
a3. 原理簡介
mtrace() 執行之後,會將後續所有 malloc 相關函數全部置換。並且記錄 malloc/free 使用過程。每次配置記憶體使用 "+" 紀錄,釋放記憶體使用 "-" 紀錄,最後統計沒有被釋放的記憶體,就是 memory leakage
如下: 
$ cat  mtrace.plain.log
= Start
@ ./dleaker:[0x80484cb] + 0x9dde378 0xa
@ ./dleaker:[0x80484db] + 0x9dde388 0x14
@ ./dleaker:[0x80484ec] - 0x9dde378
= End 
$ cat mtrace.plain.leaks.log
Memory not freed:
-----------------
Address     Size     Caller
0x09dde388     0x14  at /home/albert/test/libtrace/dleaker.c:13 
a4. 注意:編譯時要加入 "-g" ,這樣 mtrace 才能夠顯示出正確的檔案名稱與行號。 
b. 有時候僅知道行號,還是無法確認問題,最好是有上 backtrace,提供更清楚的呼叫流程,實驗過程如下:
b1. 替換原本的 malloc,在記憶體配置之後,打印 backtrace。
extern void *__libc_malloc(size_t size);
extern void *malloc(size_t size)
{
    void *ptr = __libc_malloc(size);
    fprintf(stderr,"%s\n", __func__);
    _ShowBacktrace();
    return ptr;
b2. 一開始使用下列方法實作 _ShowBacktrace()
#include
static void _ShowBacktrace(void)
{
    void *bt[1024];
    int bt_size;
    char **bt_syms;
    int i;
    bt_size = backtrace(bt, 1024);
    bt_syms = backtrace_symbols(bt, bt_size);
    for (i = 1; i < bt_size; i++)
    {
printf("%s", bt_syms[i]);
    }
    free(bt_syms);
結果程式會掛掉,因為 backtrace() 會再一次呼叫 malloc,因此此項修改會不斷的呼叫 malloc,最後導致 stack overflow。所以需要加上 flag 避免此無限迴圈。相關討論可參考 https://patchwork.ozlabs.org/patch/442890/
若對 mtrace 內部實作有興趣,可以直接參考此檔案 http://code.metager.de/source/xref/gnu/glibc/malloc/mtrace.c


2. 使用 libmemleak.so
a. 首先自行編譯 libmemleak.so (實驗時使用 ubuntu 16.04)
$ sudo apt-get update
$ sudo apt-get install binutils-dev libiberty-dev libreadline-dev doxygen
$ wget https://github.com/CarloWood/libmemleak/releases/download/v0.1.1/libmemleak-0.1.1.tar.gz
$ tar zxvf libmemleak-0.1.1.tar.gz
$ cd libmemleak-0.1.1
$ ./configure
$ make
$ sudo make install 
b. 編譯測試範例
$ git clone https://github.com/alb423/memory_leakage.git
$ cd memory_leakage
$ make  
c. 執行測試程式,動態偵測記憶體資訊
$ export LIBMEMLEAK_SOCKNAME=./memleak_sock
$ cd ~/libmemleak-0.1.1
$ LD_PRELOAD='/usr/local/lib/libmemleak.so' ./hello
$ memleak_control 
d. 若要讓程式一開始就偵測記憶體,需加入 MEMLEAK_CONFIG 定義
$ export MEMLEAK_CONFIG=mtraceinit
$ cd ~/memory_leakage
$ LD_PRELOAD='/usr/local/lib/libmemleak.so' ./dleaker3
$ memleak_control
e.執行結果畫面截圖如下:







3. 編譯 ARM 平台上面的 libmemleak.so
先安裝 arm tool chain 
$ sudp apt-get update
$ sudp apt-get upgrade
$ sudo apt-get install gcc-arm-linux-gnueabihf 
編譯 libcurses.a
$ wget http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.9.tar.gz
$ tar -pxzf ncurses-5.9.tar.gz
$ ./configure --host=arm-linux-gnueabihf --without-debug --without-ada --without-shared --enable-widec CPPFLAGS="-P"
$ sudo make install DESTDIR=$HOME/
註:此處編譯 library 成功,但是編譯測試程式仍然有誤,上述步驟應該有需要改善。
編譯 libreadline.so 
直接參考此篇即可,最後再安裝到相同目錄 (也許此處可以直接使用靜態編譯)  
$ sudo make install DESTDIR=$HOME/ 
編譯 libmemleak
$ CC=arm-linux-gnueabihf-gcc ./configure --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf LDFLAGS="-L$HOME/usr/local/lib -L$HOME/usr/lib -lreadline -lncursesw"
$ make
$ sudo make install DESTDIR=$HOME/


Reference:
  1. https://how-to-build-for-arm.wikispaces.com/readline
  2. http://www.plunk.org/~hatch/goodies/backtracefilt.C
  3. https://github.com/CarloWood/libmemleak
  4. http://stackoverflow.com/questions/34732/how-do-i-list-the-symbols-in-a-so-file
  5. https://en.wikibooks.org/wiki/Linux_Applications_Debugging_Techniques/Leaks

2017年4月1日 星期六

TDD(Test Driven Development)

www.throwtheswitch.org 設計了一套用來作單元測試的工具。對於使用 TDD(Test Driven Development)開發流程的人員,挺方便的,其中共包含四套工具,分別是 Unity,CMock,CExpection,Ceedling。

摘錄官方說明如下:
  • Unity - Curiously Powerful Unit Testing in C for C.
  • CMock - Automagical generation of stubs and mocks for Unity Tests.
  • CException - Lightweight exception handling for C.
  • Ceedling - Test build management.
以下將針對這幾個工具稍做介紹。

2017年2月27日 星期一

偵測 Race Condition 的方法

在並行運算領域,哲學家就餐問題(英語:Dining philosophers problem)是一個經典問題,此問題可能會導致死結(deadlock)或飢餓(starvation)。

常見的解決方式有服務生解法,資源分級解法,Chandy/Misra解法。細節可參考 wiki 的 哲學家就餐問題

解決此問題的基本概念,便是讓共享的資源在不同執行緒內可以受到控制,但有時因為設計不良,便會出現競爭危害(race hazard)。又稱為競爭條件(race condition)

本篇將針對 race condition 的偵測及解決方式作一介紹。

2017年2月25日 星期六

Cross compile valgrind for ARM-Linux

紀錄一下編譯 valgrind 的過程,也許有天會用得到。

1. Download valgrind
使用的版本是 valgrind 3.12.0 -- 20 October 2016.
可從此處下載 http://www.valgrind.org/downloads/valgrind-3.12.0.tar.bz2

2. 編譯程式
$ wget http://www.valgrind.org/downloads/valgrind-3.12.0.tar.bz2
$ tar jxvf ./valgrind-3.12.0.tar.bz2
$ cd valgrind-3.12.0/
先修改目錄下的 configure, 尋找 armv7, 取代成 arm 
$ CC=arm-none-linux-gnueabi-gcc  ./configure --host=arm-none-linux-gnueabi --target=arm-none-linux-gnueabi --prefix=$HOME/test/valgrind  CFLAGS=-static
$ make
$ make install

3. 確認檔案編譯正確,並用 qemu-arm 檢查檔案是否可以正確執行
$ file valgrind
valgrind: ELF 32-bit LSB  executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 2.6.16, not stripped
4. 若安裝路徑有問題,可以使用下列方式安裝
./configure --prefix=/target/board/path
make install DESTDIR=/local/path
Reference:

2017年2月9日 星期四

RTSP SDP 的 profile-level-id

晚上看到對岸同胞的部落格,將重點整理如下,作一記錄。

在 RTSP Describe 所回覆的 SDP 內容中,會出現下列的描述,此處 packetization-mode 與 profile-level-id 各是什麼意思呢
a=fmtp:96 packetization-mode=1;profile-level-id=4D0029;sprop-parameter-sets=Z00AKZpigPAET8uAtQEBAUAAAPoAADqYOhgA9CAAA7msrvLjQwAehAAAdzWV3lwo,aO48gA==

2017年1月29日 星期日

JPEG 編碼解碼流程

網路串流影像的主流格式是 H.264, H.265 以及 VP9,不過針對特殊應用,仍有使用 JPEG的地方。本篇參考WIKI 說明,整理 JPEG 編解碼流程,以及 JFIF 格式封裝方法,方便自己遇到問題時可以當作參考。

JPEG 編碼流程

  1. 將 RGB 轉換為 YUV。
  2. 將 YUV444 轉換為 YUV422 或 YUV420。
  3. 將 Y 區域劃分成多個 8x8 子區域,每個區域使用 DCT 轉換到頻率空間。轉換之後,每個子區域的左上角會使用差分編碼,其他欄位會使用行程編碼
  4. 量化,把人眼不容易辨別的差異移除。其實現方式就是把很多更高頻率的成份捨位成為接近0,且剩下很多會變成小的正或負數。這是整個壓縮過程中的主要失真運算。
  5. entropy coding:將影像成份以Z字型(zigzag)排列,把相似頻率群組在一起(矩陣中往左上方向是越低頻率之係數,往右下較方向是較高頻率之係數),插入長度編碼的零,且接著對剩下的使用霍夫曼編碼

2017年1月28日 星期六

Git 常用命令摘要

此處參考 O'Reilly 書籍"版本控制使用Git",整理一些常用的 Git 命令,方便自己查找。

1. 取得 Repository 的資料
$ git clone https://github.com/alb423/wsdiscovery.git

2. 設定基本資訊
$ git config --global user.name "Albert Liao"
$ git config --global user.email "alb423@gmail.com"

3. 檢視目前狀態
$ git log
$ git status
$ git diff
$ git diff -S"TheSearchString"
$ git diff --cached 等同於 $ git diff --staged
$ git ls-files --stage

4. 放棄修改
移除一個已經被加入,但並未送交的檔案
$ git checkout -- . 
移除一個已經被送交的檔案
$ git rm  commited_file

5. 上傳資料
$ git add  aaa.c
$ git commit
$ git push

6. 修改上次 commit 的說明
$ git commit --amend

7. 切換至其他 branch
$ git branch
   bug/pr-1
   bug/pr-2
 *dev
   master
$ git checkout bug/pr-1

8. 合併,將 alternate 的資料合併至 master
$ git checkout master
$ git status
$ git merge alternate
$ git log --graph --pretty=oneline --abbrev-commit 
$ git diff --ours
$ git diff --theirs
$ git ls-files -u

9. Undo a git merge that hasn't been pushed yet
$ git reset --merge ORIG_HEAD
$ git reset --hard ORIG_HEAD
10. 上傳資料之前,需先更新remote資料,避免造成衝突
$ git pull --rebase
參考 http://gitready.com/advanced/2009/02/11/pull-with-rebase.html
11. 在Mac、Linux 终端显示 Git 当前所在分支


TBD




2017年1月27日 星期五

[Embedded] 如何檢視 Thread 狀態

以下參考 http://ask.xmodulo.com/view-threads-process-linux.html,整理幾個在 linux 系統下,檢視 Thread 狀態的方法。
方法一:ps
舉例: $ ps -T -p $(pidof NetworkManager)
方法二:top
舉例:$ top -H -p $(pidof NetworkManager)
方法三:htop
可參考以下幾篇部落格的介紹

履歷表寫作參考資料

此處收集一些履歷表寫作,以及轉職的參考資料。

將 H.265 的資料封裝成 MP4 檔案

此篇紀錄將 H.265 資料儲存成 mp4 檔案的過程。