來源:百問網
作者:韋東山
本文字數:3408,閱讀時長:5分鐘
使用 buildroot 來給 ARM 板編譯程序、編譯庫會很簡單,以后系統講解 buildroot 時再使用 buildroot。現在我們還是手工交叉編譯 freetype,這種方法在編譯、安裝一些小程序時很有用。
1. 編譯程序時去哪找頭文件?
系統目錄:就是交叉編譯工具鏈里的某個 include 目錄;
也可以自己指定:編譯時用 “ -I dir ”選項指定。
2. 鏈接時去哪找庫文件?
系統目錄:就是交叉編譯工具鏈里的某個 lib 目錄;
也可以自己指定:鏈接時用 “ -L dir ”選項指定。
3. 運行時去哪找庫文件?
系統目錄:就是板子上的/lib、/usr/lib 目錄;
也可以自己指定:運行程序用環境變量 LD_LIBRARY_PATH 指定。
4. 運行時不需要頭文件,所以頭文件不用放到板子上
1. 頭文件問題
編譯時找不到頭文件。在程序中這樣包含頭文件:#include <xxx.h>
對于尖括號里的頭文件,去哪里找它?
系統目錄:就是交叉編譯工具鏈里的某個 include 目錄;
也可以自己指定:編譯時用 “ -I dir ”選項指定。
怎么確定“系統目錄”?
執行下面命令確定目錄:
echo 'main(){}'| arm-buildroot-linux-gnueabihf-gcc -E -v -
它會列出頭文件目錄、庫目錄(LIBRARY_PATH)。
你需要在頭文件目錄中確定有沒有這個文件,或是自己指定頭文件目錄。
2. 庫文件問題
鏈接程序時如果有這樣的提示:undefined reference to `xxx',它表示 xxx 函數未定義。
那么解決方法有 2:
① 去寫出這個函數
② 或是使用庫函數,那需要在鏈接時指定庫
怎么指定庫?想鏈接 libabc.so,那鏈接時加上:-labc。
庫在哪里?
① 系統目錄:就是交叉編譯工具鏈里的某個 lib 目錄
② 也可以自己指定:鏈接時用 “ -L dir ”選項指定
怎么確定“系統目錄”?執行下面命令確定目錄:
echo 'main(){}'| arm-buildroot-linux-gnueabihf-gcc -E -v –
它會列出頭文件目錄、庫目錄(LIBRARY_PATH),你編譯出庫文件時,可以把它放入系統庫目錄。
3. 運行問題
運行程序時找不到庫:
error while loading shared libraries: libxxx.so:
cannot open shared object file: No such file or directory
找不到庫,庫在哪?
① 系統目錄:就是板子上的/lib、/usr/lib 目錄
② 也可以自己指定:
運行程序用環境變量 LD_LIBRARY_PATH 指定,執行以下的命令:
export LD_LIBRARY_PATH=/xxx_dir ; ./test
或
LD_LIBRARY_PATH=/xxx_dir ./test
如果交叉編輯工具鏈的前綴是 arm-buildroot-linux-gnueabihf-,比如 arm-buildroot-linux
gnueabihf-gcc,交叉編譯開源軟件時,如果它里面有 configure,萬能命令如下:
./configure --host=arm-buildroot-linux-gnueabihf --prefix=$PWD/tmp
make
make install
就可以在當前目錄的 tmp 目錄下看見 bin, lib, include 等目錄,里面存有可執行程序、庫、頭文件。
1. 把頭文件、庫文件放到工具鏈目錄里
如果你編譯的是一個庫,請把得到的頭文件、庫文件放入工具鏈的 include、lib 目錄里。別的程序要
使用這些頭文件、庫時,會很方便。
工具鏈里可能有多個 include、lib 目錄,放到哪里去?
執行下面命令來確定目錄:
echo 'main(){}'| arm-buildroot-linux-gnueabihf-gcc -E -v –
它會列出頭文件目錄、庫目錄(LIBRARY_PATH)。
2. 把庫文件放到板子上的/lib 或/usr/lib 目錄里
程序在板子上運行時,需要用到板子上/lib 或/usr/lib 下的庫文件;程序運行時不需要頭文件。
使用 GIT 下載所有源碼后,本節源碼位于如下目錄:
01_all_series_quickstart\
04_嵌入式 Linux 應用開發基礎知識\source\10_freetype\
freetype-2.10.2.tar.xz
libpng-1.6.37.tar.xz
本節文檔以 STM32MP157 開發板,對于其他開發板:工具鏈可能不一樣,請靈活變通。
1. 確定頭文件、庫文件在工具鏈中的目錄
以 STM32MP157 開發板為例,它的工具鏈是 arm-buildroot-linux-gnueabihf-gcc,可以執行以下命令:
echo 'main(){}'| arm-buildroot-linux-gnueabihf-gcc -E -v -
可以確定頭文件的系統目錄為:
/home/book/100ask_stm32mp157_pro-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/arm-buildroot-linux-gnueabihf/sysroot/usr/include
庫文件的系統目錄為:
/home/book/100ask_stm32mp157_pro-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/arm-buildroot-linux-gnueabihf/sysroot/usr/lib
2. 交叉編譯、安裝 libpng
freetype 依賴于 libpng,所以需要先編譯、安裝 libpng。命令如下:
book@PC$ tar xJf libpng-1.6.37.tar.xz
book@PC$ cd libpng-1.6.37
book@PC$ ./configure --host=arm-buildroot-linux-gnueabihf --prefix=$PWD/tmp
book@PC$ make
book@PC$ make install
book@PC$ cd tmp
book@PC$ cp include/* -rf /home/book/100ask_stm32mp157_pro-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/arm-buildroot-linux-gnueabihf/sysroot/usr/include
book@PC$ cp lib/* -rfd /home/book/100ask_stm32mp157_pro-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/arm-buildroot-linux-gnueabihf/sysroot/usr/lib
3. 交叉編譯、安裝 freetype
命令如下:
book@PC$ tar xJf freetype-2.10.2.tar.xz
book@PC$ cd freetype-2.10.2
book@PC$ ./configure --host=arm-buildroot-linux-gnueabihf --prefix=$PWD/tmp
book@PC$ make
book@PC$ make install
book@PC$ cd tmp
book@PC$ cp include/* -rf /home/book/100ask_stm32mp157_pro-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/arm-buildroot-linux-gnueabihf/sysroot/usr/include
book@PC$ cp lib/* -rfd /home/book/100ask_stm32mp157_pro-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/arm-buildroot-linux-gnueabihf/sysroot/usr/lib
「新品首發」STM32MP157開發板火爆預售!首批僅300套
本文是通過學習極客時間專欄《Linux性能優化實戰》05 | 基礎篇:某個應用的CPU使用率居然達到100%,我該怎么辦?
***為了維護 CPU 時間,Linux 通過事先定義的節拍率(內核中表示為 HZ),觸發時間中斷,并使用全局變量 Jiffies 記錄了開機以來的節拍數。每發生一次時間中斷,Jiffies 的值就加 1。
節拍率 HZ 是內核的可配選項,可以設置為 100、250、1000 等。不同的系統可能設置不同數值,你可以通過查詢 /boot/config 內核選項來查看它的配置值。比如在我的系統中,節拍率設置成了 250,也就是每秒鐘觸發 250 次時間中斷。
$ grep 'CONFIG_HZ=' /boot/config-$(uname -r)
CONFIG_HZ=250
同時,正因為節拍率 HZ 是內核選項,所以用戶空間程序并不能直接訪問。為了方便用戶空間程序,內核還提供了一個用戶空間節拍率 USERHZ,它總是固定為 100,也就是 1/100 秒。這樣,用戶空間程序并不需要關心內核中 HZ 被設置成了多少,因為它看到的總是固定值 USERHZ。
Linux 通過 /proc 虛擬文件系統,向用戶空間提供了系統內部狀態的信息,而 /proc/stat 提供的就是系統的 CPU 和任務統計信息。比方說,如果你只關注 CPU 的話,可以執行下面的命令:
# 只保留各個CPU的數據
$ cat /proc/stat | grep ^cpu
cpu 280580 7407 286084 172900810 83602 0 583 0 0 0
cpu0 144745 4181 176701 86423902 52076 0 301 0 0 0
cpu1 135834 3226 109383 86476907 31525 0 282 0 0 0
這里的輸出結果是一個表格。其中,第一列表示的是 CPU 編號,如 cpu0、cpu1 ,而第一行沒有編號的 cpu ,表示的是所有 CPU 的累加。其他列則表示不同場景下 CPU 的累加節拍數,它的單位是 USER_HZ,也就是 10 ms(1/100 秒),所以這其實就是不同場景下的 CPU 時間。
當然,這里每一列的順序并不需要你背下來。你只要記住,有需要的時候,查詢 man proc 就可以。不過,你要清楚 man proc 文檔里每一列的涵義,它們都是 CPU 使用率相關的重要指標,你還會在很多其他的性能工具中看到它們。下面,我來依次解讀一下。
top 和 ps 是最常用的性能分析工具:top 顯示了系統總體的 CPU 和內存使用情況,以及各個進程的資源使用情況。ps 則只顯示了每個進程的資源使用情況。
# 默認每3秒刷新一次
$ top
top - 11:58:59 up 9 days, 22:47, 1 user, load average: 0.03, 0.02, 0.00
Tasks: 123 total, 1 running, 72 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.3 us, 0.3 sy, 0.0 ni, 99.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 8169348 total, 5606884 free, 334640 used, 2227824 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 7497908 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 78088 9288 6696 S 0.0 0.1 0:16.83 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.05 kthreadd
4 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/0:0H
...
這個輸出結果中,top 默認顯示的是所有 CPU 的平均值,這個時候你只需要按下數字 1 ,就可以切換到每個 CPU 的使用率了。
繼續往下看,空白行之后是進程的實時信息,每個進程都有一個 %CPU 列,表示進程的 CPU 使用率。它是用戶態和內核態 CPU 使用率的總和,包括進程用戶空間使用的 CPU、通過系統調用執行的內核空間 CPU 、以及在就緒隊列等待運行的 CPU。在虛擬化環境中,它還包括了運行虛擬機占用的 CPU。
用 pidstat 吧,它正是一個專門分析每個進程 CPU 使用情況的工具。下面的 pidstat 命令,就間隔 1 秒展示了進程的 5 組 CPU 使用率,包括:
# 每隔1秒輸出一組數據,共輸出5組
$ pidstat 1 5
15:56:02 UID PID %usr %system %guest %wait %CPU CPU Command
15:56:03 0 15006 0.00 0.99 0.00 0.00 0.99 1 dockerd
...
Average: UID PID %usr %system %guest %wait %CPU CPU Command
Average: 0 15006 0.00 0.99 0.00 0.00 0.99 - dockerd
使用 perf 分析 CPU 性能問題,我來說兩種最常見、也是我最喜歡的用法。
第一種常見用法是 perf top,類似于 top,它能夠實時顯示占用 CPU 時鐘最多的函數或者指令,因此可以用來查找熱點函數,使用界面如下所示:
$ perf top
Samples: 833 of event 'cpu-clock', Event count (approx.): 97742399
Overhead Shared Object Symbol
7.28% perf [.] 0x00000000001f78a4
4.72% [kernel] [k] vsnprintf
4.32% [kernel] [k] module_get_kallsym
3.65% [kernel] [k] _raw_spin_unlock_irqrestore
...
輸出結果中,第一行包含三個數據,分別是采樣數(Samples)、事件類型(event)和事件總數量(Event count)。比如這個例子中,perf 總共采集了 833 個 CPU 時鐘事件,而總事件數則為 97742399。
再往下看是一個表格式樣的數據,每一行包含四列,分別是:
$ perf record # 按Ctrl+C終止采樣
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.452 MB perf.data (6093 samples) ]
$ perf report # 展示類似于perf top的報告
測試一下這個 Nginx 服務的性能
# 并發10個請求測試Nginx性能,總共測試100個請求
$ ab -c 10 -n 10000 http://192.168.0.10:10000/
This is ApacheBench, Version 2.3 <$Revision: 1706008 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd,
...
Requests per second: 11.63 [#/sec] (mean)
Time per request: 859.942 [ms] (mean)
...
新開一個終端運行 top 命令,并按下數字 1 ,切換到每個 CPU 的使用率:
$ top
怎么知道是 php-fpm 的哪個函數導致了 CPU 使用率升高呢?我們來用 perf 分析一下。在第一個終端運行下面的 perf 命令:
# -g開啟調用關系分析,-p指定php-fpm的進程號21515
$ perf top -g -p 21515
CPU 使用率是最直觀和最常用的系統性能指標,更是我們在排查性能問題時,通常會關注的第一個指標。所以我們更要熟悉它的含義,尤其要弄清楚用戶(%user)、Nice(%nice)、系統(%system) 、等待 I/O(%iowait) 、中斷(%irq)以及軟中斷(%softirq)這幾種不同 CPU 的使用率。比如說:
本文由博客一文多發平臺 https://openwrite.cn?from=article_bottom 發布!