前言
最近的一個項目中,想要統計make整個項目的時間,并添加到中,生成鏡像后,自動輸出時間到屏幕。
調研了,發現可以使用以下兩種方式來實現。
一、time工具
最簡單的方式,使用time工具來統計運行腳本時間,百度百科對time命令的解釋:
time命令常用于測量一個命令的運行時間
測試環境是.04, 在終端輸入time命令
time
real 0m0.000s
user 0m0.000s
sys 0m0.000s
以一個驅動demo編譯過程為例。
在編譯目錄下,運行的make動作。
make
make -C /lib/modules/`uname -r`/build M=/home/xxx/Desktop/xxx/test/driver modules
make[1]: Entering directory '/usr/src/linux-headers-5.13.0-41-generic'
CC [M] /home/xxx/Desktop/xxx/test/driver/msg_test.o
MODPOST /home/xxx/Desktop/xxx/test/driver/Module.symvers
CC [M] /home/xxx/Desktop/xxx/test/driver/msg_test.mod.o
LD [M] /home/xxx/Desktop/xxx/test/driver/msg_test.ko
BTF [M] /home/xxx/Desktop/xxx/test/driver/msg_test.ko
Skipping BTF generation for /home//home/xxx/Desktop/xxx/test/driver/msg_test.ko due to unavailability of vmlinux
make[1]: Leaving directory '/usr/src/linux-headers-5.13.0-41-generic'
real 0m14.638s
user 0m0.663s
sys 0m0.560s
可以看到整個過程,耗時14.638秒, 用戶態與內核態消耗的時間分別是0.663秒、0.560秒。
二、自行實現 思路
我們只需要在開始運行時,記錄一個時間戳。執行完成時記錄一個時間戳,在進行時間的相減,就可以獲取總的運行時間。
1、獲取開始時間戳。
可以采用linux系統的/proc/uptime來獲取當前時間。
可以先分析一下/proc/uptime里面的內容,里面記錄了Linux系統運行時間。
cat /proc/uptime
4643.14 34329.17
2、提取時間戳的思路
只需要用awk命令,通過.分割/proc/uptime里面的內容,就可以獲取到秒的時間戳。
cat /proc/uptime | awk -F "." '{print $1}'
4643
只要在運行結束時,再獲取一次/proc/time里面的秒數,前后數值相減,便可以得到時間差,即項目的運行時間。
3、date命令轉換時間戳為 年月日時分秒 格式
可以通過data --help命令來查看data的用法。
data -d @時間戳 [format]
format用到以下的參數,獲取日、時、分、秒
%j day of year (001..366)
%H hour (00..23)
%M minute (00..59)
%S second (00..60)
此時輸入的時間戳是以1970年開始作為運算。如上面獲取的4643, 由于博主時UTC-8的時間,所以時間+了8小時,4643對應是9點17分23秒。
date -d @4643
1970年 01月 01日 星期四 09:17:23 CST
\- u選項
加上-u選項,可以讓時間以UTC為參考,不加時區偏移。
date -u -d@4643
1970年 01月 01日 星期四 01:17:23 UTC
就可以看到時間是1點17分23秒,正好是我們的系統運行時間,4643秒。
格式化截取時分秒
date -u -d @4643 +%Hh:%Mm:%Ss
01h:17m:23s
+%Hh:%Mm:%Ss命令中的%H、%M、%S分別獲取了時分秒,并以h:m:s這樣的格式輸出。與printf函數類似。至此便可以獲取到運行時間的時分秒。
實現
原來的
DIR = $(shell pwd)
KER_DIR = /lib/modules/`uname -r`/build
obj-m = msg_netlink.o
all:
make -C $(KER_DIR) M=$(PWD) modules
clean:
make -C $(KER_DIR) M=$(PWD) clean
改動后的
DIR = $(shell pwd)
KER_DIR = /lib/modules/`uname -r`/build
START_TIME = $(shell cat /proc/uptime | awk -F "." '{print $$1}') # Makefile進入,獲取時間戳
obj-m = msg_netlink.o
all: module showruntime
module:
make -C $(KER_DIR) M=$(PWD) modules
clean:
make -C $(KER_DIR) M=$(PWD) clean
showruntime:
@current_time=`cat /proc/uptime | awk -F "." '{print $$1}'`; \
time_interval=`expr $${current_time} - $(START_TIME)`; \
runtime=`date -u -d @$${time_interval} +%Hh:%Mm:%Ss`; \
echo "######## runtime: $${runtime} ########"
分析
小知識:
中,調用自身的變量,用$符號,比如中的。中,target執行的shell命令,定義的變量,需要用$$符號調用,比如中的,因為是shell運行過程生成的變量,需要用$$來調用.同樣 = $(shell cat /proc/uptime | awk -F "." '{print $$1}')中,在終端命令中,獲取awk參數用$1即可,但由于是在中,調用shell,所以需要用$$1才可以獲取到分割數值。運行的target中,如,里面的shell命令,如果需要做多個shell命令,需要用; \符號來連續整個shell命令,否則會報錯,詳細查看里面的內容。中@字符shell命令可以隱藏shell命令運行打印。
如
showruntime:
current_time=`cat /proc/uptime | awk -F "." '{print $$1}'`; \
time_interval=`expr $${current_time} - $(START_TIME)`; \
runtime=`date -u -d @$${time_interval} +%Hh:%Mm:%Ss`; \
echo "######## runtime: $${runtime} ########"
輸出如下, 可以看到整個shell命令都打印出來了:
make -C /lib/modules/`uname -r`/build M=/home/xxx/Desktop/xxx/test/driver modules
make[1]: Entering directory '/usr/src/linux-headers-5.13.0-41-generic'
make[1]: Leaving directory '/usr/src/linux-headers-5.13.0-41-generic'
current_time=`cat /proc/uptime | awk -F "." '{print $1}'`; \
time_interval=`expr ${current_time} - 6710 `; \
runtime=`date -u -d @${time_interval} +%Hh:%Mm:%Ss`; \
echo "######## runtime: ${runtime} ########"
######## runtime: 00h:00m:00s ########
加上@符號后, 只會打印echo出來的字符。
showruntime:
@current_time=`cat /proc/uptime | awk -F "." '{print $$1}'`; \
time_interval=`expr $${current_time} - $(START_TIME)`; \
runtime=`date -u -d @$${time_interval} +%Hh:%Mm:%Ss`; \
echo "######## runtime: $${runtime} ########"
輸出如下:
make -C /lib/modules/`uname -r`/build M=/home/xxx/Desktop/xxx/test/driver modules
make[1]: Entering directory '/usr/src/linux-headers-5.13.0-41-generic'
make[1]: Leaving directory '/usr/src/linux-headers-5.13.0-41-generic'
######## runtime: 00h:00m:00s ########
這里運行時間為0,是因為驅動已經編譯過,沒有改動,make clean后,再重新編譯,即可以看到運行時間。
make clean
ake -C /lib/modules/`uname -r`/build M=/home/xxx/Desktop/xxx/test/driver clean
make[1]: Entering directory '/usr/src/linux-headers-5.13.0-41-generic'
CLEAN /home/xxx/Desktop/xxx/test/driver/Module.symvers
make[1]: Leaving directory '/usr/src/linux-headers-5.13.0-41-generic'
time make # 用了time一起統計時間
make -C /lib/modules/`uname -r`/build M=/home/xxx/Desktop/xxx/test/driver modules
make[1]: Entering directory '/usr/src/linux-headers-5.13.0-41-generic'
CC [M] /home/xxx/Desktop/xxx/test/driver/msg_test.o
MODPOST /home/xxx/Desktop/xxx/test/driver/Module.symvers
CC [M] /home/xxx/Desktop/xxx/test/driver/msg_test.mod.o
LD [M] /home/xxx/Desktop/xxx/test/driver/msg_test.ko
BTF [M] /home/xxx/Desktop/xxx/test/driver/msg_test.ko
Skipping BTF generation for /home/xxx/Desktop/xxx/test/driver/msg_test.ko due to unavailability of vmlinux
make[1]: Leaving directory '/usr/src/linux-headers-5.13.0-41-generic'
######## runtime: 00h:00m:02s ########
real 0m2.107s
user 0m0.821s
sys 0m0.301s
可以看到 time make統計到的時間,與計算得到的時間都是2秒左右。實驗結果ok。
總結 熟悉/proc/uptime里面參數的含義??梢圆挥?proc/uptime來獲取時間戳,可以用date +%s獲取當前時間戳,代替cat /proc/uptime熟悉date命令的時候,獲取時間戳、格式化獲取日期。仔細觀看實現的小知識,這里面涉及到很多細節內容,建議反復觀看。中的target依賴問題,仔細觀看所在位置。中$`符號 與 $$符號的區別
*請認真填寫需求信息,我們會在24小時內與您取得聯系。