顯示包含「Linux embeded system」標籤的文章。顯示所有文章
顯示包含「Linux embeded system」標籤的文章。顯示所有文章

2024年2月29日星期四

在Yocto Project中,在還沒建立 rootfs的 image之前,刪除一些rootfs當中的 Library

 今天遇到一個問題,因為 gstreamer 執行時間過長,此過長的原因,是因為Library開啟太多

 另外不太了解 gstreamer 哪個Library是對應到哪個 plug-in(Package)

 所以打算用刪除 rootfs當中的 Library方式,來解決此問題


先找到下面這個檔案
meta/poky/meta/classes/rootfs-postcommands.bbclass

然後你可以發現,這個bbclass檔案,是被下面的檔案引用的
meta/poky/meta/classes/image.bbclass


接著就去修改,rootfs-postcommands.bbclass,加入以下內容
修改的重點就是,
1. 刪除想刪的檔案,這邊提一下,檔案中的變數 ${IMAGE_ROOTFS},會指到mtk-core-image-tiny/1.0-r0/rootfs/,並非我們要刪除的rootfs的路徑,因此這邊我們需要確定並改為指到 mtk-image-2735/1.0-r0/rootfs/
2. 必須確保刪除的檔案有存在,不然Yocto就會 build error,所以我們會加入check function,如果檔案存在,我們才做remove


最後加入以下內容,Device flash image之後,可以看到 /usr/lib64/gstreamer-1.0/ 路徑底下的 Library,該刪的都刪掉了!


### For resolving the gstreamer issue
ROOTFS_POSTPROCESS_COMMAND += "remove_gstreamer_lib ;"


# Remove gstreamer check
remove_file_if_exists() {
    local file_path="$1"
    if [ -f "$file_path" ]; then  # -e: if file_path exist, will return TRUE
        rm "$file_path"
        echo "Removed: $file_path"
    else
        echo "File does not exist: $file_path"
    fi
}


## ${IMAGE_ROOTFS} is apps/build/tmp/work/auto2735evb_ivt_vp2-poky-linux/mtk-core-image-tiny/1.0-r0/rootfs/

## But the real locate of the library is in apps/build/tmp/work/auto2735evb_ivt_vp2-poky-linux/mtk-image-2735/1.0-r0/rootfs/

# Remove gstreamer library

remove_gstreamer_lib () {
       remove_file_if_exists "${IMAGE_ROOTFS}/../../../mtk-image-2735/1.0-r0/rootfs/usr/lib64/gstreamer-1.0/libgsta52dec.so"
       remove_file_if_exists "${IMAGE_ROOTFS}/../../../mtk-image-2735/1.0-r0/rootfs/usr/lib64/gstreamer-1.0/libgstaccurip.so"
       remove_file_if_exists "${IMAGE_ROOTFS}/../../../mtk-image-2735/1.0-r0/rootfs/usr/lib64/gstreamer-1.0/libgstadder.so"
       remove_file_if_exists "${IMAGE_ROOTFS}/../../../mtk-image-2735/1.0-r0/rootfs/usr/lib64/gstreamer-1.0/libgstadpcmdec.so"
       remove_file_if_exists "${IMAGE_ROOTFS}/../../../mtk-image-2735/1.0-r0/rootfs/usr/lib64/gstreamer-1.0/libgstadpcmenc.so"
       remove_file_if_exists "${IMAGE_ROOTFS}/../../../mtk-image-2735/1.0-r0/rootfs/usr/lib64/gstreamer-1.0/libgstaiff.so"
}


這邊列出網路找到的一些資料
Ref: https://embeddedguruji.blogspot.com/2019/03/run-commands-after-rootfs-creation-in.html 

2023年12月5日星期二

如何在chroot當中,reboot 或是 shutdown 你的裝置 (/proc/sysrq-trigger 的用法)

 今天有個需求,是必須在chroot當中,執行 power-off

想當然爾,第一個想到的是使用 shutdown now

於是馬上把shutdown 這個指令,移植到 chroot,執行後出現以下的訊息,但無法 poweroff

System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down
Failed to talk to init daemon

另外也試過,在chroot當中使用 kill -9 1 ,沒有出現錯誤訊息,但是一樣沒作用
(有在chroot當中kill某個 process,ex: kill -9 24, 是可以成功的)

google上面找到一個 /proc/sysrq-trigger 的方法,如下:

Step1:
先執行 echo 1 > /proc/sys/kernel/sysrq

Step2:
poweroff:
=>  echo "o" > /proc/sysrq-trigger

reboot:
=>  echo "b" > /proc/sysrq-trigger

更多用法可以參考
Ref: http://www.unixlinux.online/unixlinux/linuxjc/gylinux/201703/95680.html

# 立即重新啟動裝置
echo "b" > /proc/sysrq-trigger

# 立即關閉裝置
echo "o" > /proc/sysrq-trigger

# 導出內存分配的信息 (可以用/var/log/message 查看)
echo "m" > /proc/sysrq-trigger

# 導出當前CPU寄存器信息和標志位的信息
echo "p" > /proc/sysrq-trigger

# 導出線程狀態信息
echo "t" > /proc/sysrq-trigger

# 故意讓系統崩潰(kernel panic)
echo "c" > /proc/sysrq-trigger

# 立即重新掛載所有的文件系統
echo "s" > /proc/sysrq-trigger

# 立即重新掛載所有的文件系統為只讀
echo "u" > /proc/sysrq-trigger

Documentation for sysrq.c

Based on kernel version 2.6.38. Page generated on 2011-03-22 22:20 EST.

調整某個Daemon的 nice值(priority),從service 來調整 Linux Nice

當有個Daemon占據CPU太多的使用率時,我們可以透過調整nice值來降低其佔據CPU的使用率

今天我們以 mnld 這個daemon來當作範例,mnld是一個GNSS使用的Daemon

說明一下怎麼修改nice數值,也就是調整其優先順序

如下圖,我們可以在系統或是你的 Source Code 當中找到 mnld.service

然後我們可以修改如下圖,Nice值範圍為 -20 ~ 19 (高優先 ~ 低優先),default is 0









改完之後,下次重啟設備,我們可以使用指令,來觀察Nice值  =>  ps -fl -C "mnld"
command ref: 
https://www.thegeekstuff.com/2013/08/nice-renice-command-examples/







2023年11月29日星期三

編譯 Yocto SDK toochain 包含 Linux kernel 的 header 與 source (Build Yocto sdk include kernel header and source)

Step1:
我使用的
Yocto Project為2.6版,編譯SDK的指令如下: (以 MTK平台為例, xxxx 帶入自己的platform)
bitbake mtk-image-xxxx -c populate_sdk  


Step2:

用以上指令,編譯出來的Toolchain並不包含kernel header或是 kernel source,查詢網頁之後,得知需要再包含編譯這個Package “kernel-devsrc”


Step3:
接著我們在mtk-image-xxxx.bb 裡面,加上這個package,IMAGE_INSTALL_append += "kernel-devsrc"
Path: meta/meta-mediatek-mtxxxx/recipes-core/images/mtk-image-xxxx.bb
如下圖:





Step4:
接著編譯SDK,會遇到以下的錯誤訊息:

Fix kernel-devsrc package failing during install This issue is due to the upstream script hardcodes /bin/awk whereas we ship /usr/bin/awk. The installation check will break in this case. Fix it by changing the path in the script.

Step5:
從網路上,也看到有人在討論同樣的議題,有人提供patch方法,如下Link:

https://gerrit.automotivelinux.org/gerrit/c/AGL/meta-agl/+/11173/3/meta-agl-bsp/meta-ti/recipes-kernel/linux/linux-ti-staging_%2525.bbappend

於是我把這些修改加入meta/meta-mediatek-mtxxxx/recipes-kernel/linux/linux-mtk-extension_4.19.bbappend如下:





Step6:
接著繼續編譯SDK,結果出現以下的問題:
ERROR: mtk-image-xxxx-1.0-r0 do_populate_sdk: Could not invoke dnf. Command 
主要的錯誤訊息如下

Error:

 Problem: package target-sdk-provides-dummy-1.0-r0.sdk_provides_dummy_target conflicts with /bin/sh provided by busybox-1.29.3-r0.aarch64
- package kernel-devsrc-1.0-r0.autoxxxxevb_ivt_vp2 requires /usr/bin/awk, but none of the providers can be installed
- conflicting requests

Step7:
看了上面的錯誤訊息,其中一個錯誤是說,我們沒有安裝awk這個工具,因此我們試著安裝gawk. 我們接著到Yocto網站master branch底下,poky的路徑底下,搜尋awk

https://git.yoctoproject.org/poky/tree/?id=0a04692279f83637c0049cb1f91ac684f3fccf1f

於是可以看到如下的畫面,接著隨便點一個link,會到下面第二個頁面,我們可以從第二個頁面看到實際gawk的路徑為”meta/recipes-extended/gawk/”


















Step8:
接著就可以回到Yocto Tree的路徑,接著按照下圖步驟,可以找到gawk的reciepe. 

https://git.yoctoproject.org/poky/tree/meta?id=0a04692279f83637c0049cb1f91ac684f3fccf1f



















Step9:

我們選擇使用版本gawk-4.1.3,因為我們的Yocto為2.6版比較舊,選太新的recipe,有語法寫法不相同的問題(ex: gawk-5.x).於是分別把gawk_4.1.3.bb以及 gawk_4.1.3資料夾,放到我們的Yocto Project (這個網站不知道怎麼下載檔案,目前我是用複製內容,再vi gawk_4.1.3.bb 到Yocto Project當中)
path:meta/meta-mediatek-mtxxxx/recipes-extended/gawk_4.1.3.bb



Step10:

另外要記得,還要再從mtk-image-xxxx.bb那邊打開gawk,這樣才會編譯到gawk.去修改meta/meta-mediatek-mtxxxx/recipes-core/images/mtk-image-xxxx.bb






Step11:

再重新編譯一次,就可以成功編譯出包含kernel-devsrc的toolchain
*註:加入kernel-devsrc&gawk之後,整個 編譯後的 image增加了100MB

如何編譯Static library & 如何使用 (How to build a static library and share to others using)

這邊簡單寫一個example

====== printf.c ========

#include <stdio.h>
int print_hello()
{
    printf("This is a simple API example\n");
    return 0;

寫好這個API source code之後,先編譯出.o檔

gcc -c printf.c -o printf.o -I.


接著把.o檔,轉成.a檔

ar rcs printf.a printf.o


接著就可以寫一個主程式,去呼叫此API

如何使用此 Static Library,使用下面command編譯,可以產生test_main:

gcc main.c printf.a -o test_main -I.


也可以簡單寫一個 Makefile去做編譯(這邊解說Makefile 一小部分)
這邊是順帶的解說 Makefile語法,最主要還是要介紹,怎麼產生像是 printf.a 的 Static Library

###### Makefile 範例解說 #######

my_target: source_file.c header_file.h

gcc -o $@ $< -I.

$@: 表示目標,也就是 "my_target"

$<: 表示第一個依賴文件

2023年11月16日星期四

mpstat 的source code路徑,Yocto package名稱,與mpstat的用法

mpstat 與 top 指令,都是用來監控 CPU 使用率的工具
mpstat 是 Multiprocessor Statistics 的縮寫,它是 sysstat 這個套件裡面的一個工具

所以當我們要在Yocto裡面開啟這個工具,請記得是開啟 sysstat


如果要使用 mpstat這個工具,也可以用以下的 apt-get指令來安裝

apt-get install sysstat

sysstat 的opensource,我們可以從以下的網站來下載:
https://github.com/sysstat/sysstat


另外簡單介紹一下mpstat的使用方式

直接使用指令 mpstat:



使用指令 mpstat -P ALL 5 2:
參數所代表的意思為
    -P ALL: -P表示要監控哪個CPU,這邊帶入ALL,表示列出所有CPU的狀態
    5: 表示5秒印出一次
    2: 表示印2個回合



2023年11月5日星期日

Linux 更改 Mac Address 指令

 #先把ethernet0 停用
ifconfig eth0 down

#更改MAC Address
ifconfig eth0 hw ether AA:BB:CC:DD:EE:FF

#啟用ethernet0
ifconfig eth0 up


#最後在使用ifconfig 檢查
ifconfig

2023年10月25日星期三

GStreamer debug 的方式 - 第一次開機執行GStreamer command  會慢1~2秒

 這邊先記錄debug的方式

  我們可以在Linux作業系統底下,使用這個command

  =>  export GST_DEBUG="*:6"

實驗1:

我們使用gstreamer的debug mode發現幾件事情

1. 執行 get-lauch-1.0 之後,會在檔案系統中產生名為 “registry.aarch64.bin”的檔案

2. 這個cache檔案存放在 /home/root/.cache/gstreamer-1.0/

接著我們寫了簡單的script,會去執行這個command

=> /usr/bin/gst-launch-1.0 filesrc location=/etc/Track.awb ! decodebin ! audio convert ! audio resample ! audio/x-raw,rate=48000,channels=2,format=S16LE ! volume volume=2 ! alsasink device="hw:0,0"

接著我們計算有cache檔案的執行時間,去比較沒有cache檔案的執行時間

=> 有cache: 0.2 sec    沒有cache: 1 sec  (計算時間方式,使用teraterm的timestamp 去計算)







實驗2:

事先儲存好這個cache檔,重新更新這個device的韌體,刷新後把cache檔案放到 /home/root/.cache/gstreamer-1.0/

結果會跟實驗1當中,有cache的結果一樣,約執行0.2秒


2023年7月3日星期一

在Linux當中,應用程式,計算執行時間的範例程式

這個範例,計算單位為 microSecond(10-6)

#include <time.h>

 


clock_t start, end;

double cpu_time_used;

 

 

printf("** Start to measure time **\n");

start = clock();

...

...

...

end = clock();


cpu_time_used = ((double) (end - start))*1000000 / (CLOCKS_PER_SEC);

printf("** execution time:%f microseconds\n", cpu_time_used);

printf("** End of measure time **\n");


Linux kernel 4.19版 中,計算執行時間的方法,範例程式

首先需要 include 這個 header file 

#include <linux/time.h>


然後使用下面的方式,搭配 printk 在kernel 端印出計算時間,
這邊我們取 microseconds (10-6)

struct timeval start_time, end_time;

unsigned long elapsed_time;


 printk(KERN_ERR "#### measure time start %s ####\n", __func__);

do_gettimeofday(&start_time);   // Get the starting time

...

...

...

do_gettimeofday(&end_time);     // Get the ending time

 

// Calculate the executing time

elapsed_time = (end_time.tv_sec - start_time.tv_sec) * 1000000 +

                              (end_time.tv_usec - start_time.tv_usec);


printk(KERN_ERR "#### Elapsed time: %lu microseconds\n", elapsed_time);

printk(KERN_ERR "#### measure time end %s ####\n", __func__);



另外在 kernel 較新的版本當中,如果 do_gettimeofday() 無法使用,可以試試看下列方法

#include <linux/ktime.h>
#include <linux/types.h>

ktime_t start, end;
s64 elapsed_ns, 
elapsed_us;

start = ktime_get();

...
...
...

end = ktime_get();

elapsed_ns = ktime_to_ns(ktime_sub(end, start));
elapsed_us = ktime_to_us(elapsed_ns );

printk(KERN_ERR "#### Elapsed time: %lld microseconds\n", elapsed_us);


2023年5月9日星期二

Linux底下,一個控制CPU Loading的 Open Source tool,cpulimit (Tool使用方式)

 此篇直接介紹 cpulimit 該如何使用,讓我們做stress-test 可以直接指定想要的CPU Loading

先假設我們的設備為 雙核心(dual-core)的device

我們先撰寫一個loop的shell script,這個script可以把一個CPU使用率,占用到100%
====== loop_1.sh ======
#!/bin/sh

while [ 1 ]
do
    echo 5566 > /dev/null
done
====================

上面這個簡單的小程式,就可以占用100%的一個CPU使用率
所以如果是雙核心的device,很簡單,我們就再搞一個loop script

====== loop_2.sh ======
#!/bin/sh

while [ 1 ]
do
    echo 5566 > /dev/null
done
====================


接著我們再去撰寫一個主要的shell script,可以帶起 loop_1.sh 與 loop_2.sh
並且會去使用 cpulimit 去限制這兩個 loop程式的 cpu 使用率
進而達到我們想要維持的 CPU 使用率

====== cpuload.sh =======
#!/bin/sh

if [ "$#" -lt "1" ]; then
    echo "ex: ./cpuload.sh 40 (limit at 40%)"
    exit
fi

VAL=$1

killall loop_1.sh loop_2.sh

./loop_1.sh &
L1=`ps | grep loop_1.sh | awk -F ' ' '{print $1}'`     #get pid
./loop_2.sh &
L2=`ps | grep loop_2.sh | awk -F ' ' '{print $1}'`     #get pid

./cpulimit --limit=$VAL --pid=$L1 &
./cpulimit --limit=$VAL --pid=$L2 &

=======================

Linux底下,一個控制CPU Loading的 Open Source tool,cpulimit (Cross-compile)

 今天要跟大家介紹一個好用的工具,可以限制某一個Process只允許他使用多少的CPU Loading
 另外,如果要做壓力測試(stress test),只要稍微再搭配一些自己撰寫的shell script
 可以達到自行指定壓力測試所要的cpu loading

 先介紹這個open source,名為 "cpulimit",source code link如下:
 https://github.com/opsengine/cpulimit

 如果要在你的平台上,作壓力測試,請先自行做 Cross Compile,這邊先簡單教你如何編譯出你平台可以使用的tool

 我們可以看到此opensouce的目錄結構如下圖:

 










Step1:

在你下載好的source code,如上圖的路徑底下,先指定好你的CC環境變數
ex: 我要編譯電腦x86 用的tool,我的Toolchain就會是 /usr/bin/gcc,於是我用以下方式指定CC
=>   export CC=/usr/bin/gcc

Step2:

執行make,就可以成功編譯出我們要的工具,"cpulimit"
(如果要重新編譯,記得先make clean)







Step3:

編譯出來的執行程式,會在cpulimit-master/src/ 路徑底下,如下圖:




Step4:

執行cpulimit,可以看到使用方式,如下圖:
我們主要會用到 limit 與 pid 這兩個參數







下一篇文章,再來繼續介紹,怎麼加一些shell script,來做到壓力測試!

2023年1月29日星期日

[C Language] linux signal 範例程式

 下面介紹一個範例程式名為 "signal",編譯此程式之後,把此程式run在背景,可以使用下面幾個指令,來觸發此程式當中的 printf來印出相對應的訊息,當然你也可以把 printf 改成你想做的事情

 kill -SIGHUP `pidof signal`
 kill -SIGINT `pidof signal`
 kill -SIGQUIT `pidof signal`


======================= signal.c =================

#include <signal.h>
#include <unistd.h>
#include <stdio.h>

void sigroutine(int sig_num) {
    switch(sig_num) {
        case 1:
                printf("Get a signal - SIGHUP \n");
        case 3:
                
printf("Get a signal - SIGQUIT \n");
        case 10:
                printf("Get a signal - SIGUSR1 \n");
    }
    return;
}

int main() {
    printf("process id is %d\n", getpid());
    signal(SIGHUP, 
sigroutine);
    signal(SIGQUIT, sigroutine);
    signal(SIGUSR1, sigroutine);
    for (;;) ;
}

==============================================


另外列出,所有可以帶入 kill 後面的sigmal列表(Reference from google)
2 - 就是我們常見的鍵盤中斷 CTRL+c
9 - 就是我們常用來kill process的 signal



信號取值默認動作含義(發出信號的原因)
SIGHUP1Term終端的掛斷或進程死亡
SIGINT2Term來自鍵盤的中斷信號
SIGQUIT3Core來自鍵盤的離開信號
SIGILL4Core非法指令
SIGABRT6Core來自abort的異常信號
SIGFPE8Core浮點例外
SIGKILL9Term殺死
SIGSEGV11Core段非法錯誤(內存引用無效)
SIGPIPE13Term管道損壞:向一個沒有讀進程的管道寫數據
SIGALRM14Term來自alarm的計時器到時信號
SIGTERM15Term終止
SIGUSR110Term用戶自定義信號1
SIGUSR212Term用戶自定義信號2
SIGCHLD20,17,18Ign子進程停止或終止
SIGCONT19,18,25Cont如果停止,繼續執行
SIGSTOP17,19,23Stop非來自終端的停止信號
SIGTSTP18,20,24Stop來自終端的停止信號
SIGTTIN21,21,26Stop後台進程讀終端
SIGTTOU22,22,27Stop後台進程寫終端
SIGBUS10,7,10Core總線錯誤(內存訪問錯誤)
SIGPOLLTermPollable事件發生(Sys V),與SIGIO同義
SIGPROF27,27,29Term統計分佈圖用計時器到時
SIGSYS12,-,12Core非法系統調用(SVr4)
SIGTRAP5Core跟踪/斷點自陷
SIGURG16,23,21Ignsocket緊急信號(4.2BSD)
SIGVTALRM26,26,28Term虛擬計時器到時(4.2BSD)
SIGXCPU24,24,30Core超過CPU時限(4.2BSD)
SIGXFSZ25,25,31Core超過文件長度限制(4.2BSD)
SIGIOT6CoreIOT自陷,與SIGABRT同義
SIGEMT7,-,7Term
SIGSTKFLT-,16,-Term協處理器堆棧錯誤(不使用)
SIGIO23,29,22Term描述符上可以進行I/O操作
SIGCLD-,-,18Ign與SIGCHLD同義
SIGPWR29,30,19Term電力故障(System V)
SIGINFO29,-,-與SIGPWR同義
SIGLOST-,-,-Term文件鎖丟失
SIGWINCH28,28,20Ign窗口大小改變(4.3BSD, Sun)
SIGUNUSED-,31,-Term未使用信號(will be SIGSYS)


另外在Linux底下,輸入 kill -l 也可以看到這些SIGXXX 所定義的編號,如下:

$ kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX



使用 lsblk 印出 emmc 每個 partition的"名字"與"size"

使用以下的command可以印出 eMMC的 partition資訊 lsblk --bytes --output name,partlabel,size   參數說明 --bytes: partition的大小,以byte的方式輸出 --output: 後面可以指定要輸出的內容...