pretty code

顯示具有 Linux 標籤的文章。 顯示所有文章
顯示具有 Linux 標籤的文章。 顯示所有文章

2025年7月10日 星期四

Linux + Vim 真是絕配

想要得到一份兩個目錄下的檔案內容差異又不想包含 soft-link,Google 一下可以知道 diff 就有這樣的選項可以使用。

diff -r --no-dereference

為什麼要排除 soft-link?假設路徑中前後各有一個 soft-link,則比較出來的差異數量會膨脹成 4 倍。

排除了重複的資料後,diff 結果可以很容易的再用 sed 切出我們要的內容,也就是不同目錄的差異檔案清單。

如果我們把查詢出來的清單再加工成另一份清單,簡單加上一個 Vim Function,我們就可以快速的隨時瀏覽該檔案的差異項目。

diff -r --no dereference Dir1 Dir2 > diff.log
cat diff.log | sed -En 's/diff -r --no-dereference (.*) (.*)/gvim -d \1 \2/p' > diff_file_list.txt

function! CallExternalCmd()
    let l:line = getline(".")
    execute ":!" . l:line
endfunction

這是我在工作站沒有 WinMerge 這樣的軟體情況下,能夠想出的最佳解法。

當然最佳解一定是在工作站安裝 WinMerge 類似的軟體,雖然在 Linux 上 command line 才是王道,如果偶爾也有 GUI 可用,那也是個不錯的休閒時光XD

2025年6月24日 星期二

詠春三板斧

一代宗師的武術界曾提到這樣一句話:詠春來來去去就是那三板斧!

今天不知為何在工作時想到這句話?

突然發現,其實我現在的工作每天也是只有用到三板斧XD

我目前工作的三板斧為:Vim、grep、sed。

Vim 不用多說,我自己就寫了一堆 Vim script functions,即使不算自己的 Vim function,我每天用到的 Vim 功能至少就 10 個以上起跳XD

不誇張的說,沒有 Vim,我大概沒辦法工作了!

其次是 grep,很多時候我要解決的問題或是完成手上的工作,說穿了就是在一堆資料中找東東!有了 grep 的幫助,真的節省我很多時間。

最後則是 sed,grep 找到的資料透過 sed 可以輕易的切出任何我要的片段,只要下對 regex,大概事情就完成一半了XD

如果硬要加上第四板斧,我想這道板斧應該就是 find 指令無誤!

Linux 與 Vim 的世界就是這樣的樸實無華,每天都能發現新玩意?

就像是我請教我主管問題一樣,不管何時都是如沐春風!

2025年4月22日 星期二

又回來 Golang 的世界了

花了兩天時間,將之前使用 Tcl + bash script + grep + sed 寫的工具,改用 Golang 重寫。

這一年來已經習慣了 script 的 free Coding 過程,突然回到編譯型語言,還真是有些彆扭XD

距離上一個使用 Golang 開發的專案,也有三年了吧?

不過,編譯型語言還是有好處的,比如一個原本要 54 秒的 netlist 相關報表,現在只要 15 秒即可搞定(之前慢是慢在 bash script,不是 Tcl)。

Golang 還有一個額外的好處就是很容易跨平台編譯,比如我在 Windows 就可以編譯出 Linux 上跑的 ELF 執行檔。

今天在電腦的 WSL2 環境,想要驗證一下功能是否正常,突然發現,原本上面那個例子,居然要跑到 200 秒?

我連 pprof 都用上了,但還是只能看到問題是出在 System Call 上,中間一度還懷疑到我有一個很大的 struct 變數,在遞迴函數裡並不是傳遞 pointer 的緣故!

也懷疑是否是用了大量的 fmt.Sprintf 導致!

最後看到一篇文章,才發現是檔案系統的問題,但我不太確定是 NTFS 的鍋還是 WSL2 + NTFS 的鍋就是了?

總之,要在 Linux 跑程式,還是要使用 Linux 相關的檔案系統比較不會有問題,尤其我的工具就是要寫一大堆跟 cell 有關的報表。

2024年10月18日 星期五

2024 week 42 新玩意

01. nl tool 自動加上數字編號

之前用 Vim 功能將備份小老婆歌單檔案前面加上數字編號,昨天無意間在鳥哥 sed 教學文章中學到 nl 這一個 tool,不只能加上編號,數字要不要補 0 或是後面要不要加上逗號等,這個 tool 都可以搞定。

原本還以為要用 sed 再組織一次字串好方便加上後面的逗號,沒想到 nl 開發者早就想好,果然 Linux tool 的哲學就是一次只做一件事,但把那件事做好!

nl -n 'rz' -w 2 xxx.txt


02. 還在跟 PAD 奮鬥

大概是這個星期一還是星期二就把兩個星期前主管交辦事項的簡報補充的差不多了,連 PAD CELL 的方向我都找到圖片做補充了。

既然 ORFS 沒有範例,乾脆自己來試看看吧,本來是用 gcd,但這個 chip 實在太小,為了放置 IO PAD 整個面積會變很大,但 core 只佔一咪咪,重點也是會死在 global route,錯誤原因是 congestion 太高。

後來改用 jpeg_encoder,這次的 core 大小就比較合適,話雖如此,但一樣會死在 global route。

今天是難得的休假日,下午外出回來本想先不加 IO CELL,看看 pin 是如何擺放的,我再來決定 IO PAD 的位置,看看這樣是否就能解決問題,沒想到居然看不到 pin?

感覺自己沒招了,ORFS issue 列表都翻爛了也沒有 fu。

2024/11/02 更新

雖然颱風假當天的嘗試還是以失敗告終,但在知道問題出在 netlist 後,隔天終於能對症下藥,也順利的在 gcd 和 jpeg 產出結果

2024年10月12日 星期六

2024 week 41 新玩意

01. Linux Group By 功能

Linux 實在是一個很強大的作業系統,應該是說它的生態系很強大,什麼工具早就有人開發好了,根本不需要你寫半行 code 來解決問題。

就拿最近我在整理的一份 PAD 資料,突然想要做個表格放進簡報裡,regex + sort 取出資料常常在做,但要如何 group by 來加總一時還想不出來,隨便拿個程式語言做這些事當然很簡單,但人會被慣壞,有更簡單的方法當然更好囉。

老樣子,Google 一下,原來這麼簡單,我常用的 uniq 工具就可以了,加上 -c 選項即可。之後再用 sed 取出加總並調整一下順序,就可以在 Power Point 裡面用 "插入 -> 物件 -> Word",然後在跳出來的 Word 浮動視窗貼上 sed 整理好的文字,然後選 "插入 -> 表格 -> 文字轉換成表格",這樣就可以一氣呵成了。


2024/10/16 更新

忘了先前用 sed 取出 Verilog module 的技巧了,這樣才對呀!還要另存 components.txt 太 low 了XD

cat skywater130_coyote_tc.defok | sed -n '/COMPONENTS/,/END COMPONENTS/p' | grep '-' | awk '{print $3}' | sort | uniq -c


02. Tmux

以前就知道 Screen 的替代品 Tmux(嚴格說起來應該是比 Screen 功能還多),但一直沒有機會使用,工作站也沒有這個軟體可以使用,但自從在公司電腦安裝了 WSL2 後,應該是時候試用 Tmux 了。

它跟 Vim 一樣,有很多設定值可以調整,為了跟 Vim 使用體驗一致,除了前置組合按鍵外,應該要讓設定值盡量跟 Vim 看齊。

沒關係,慢慢來即可,畢竟工作環境不是一蹴可幾的事。

2023年11月3日 星期五

Magic symbol - _ZN6google15ErrnoLogMessageC1EPKciimMNS_10LogMessageEFvvE

同事最近在搞 Vitis-AI 的板子,過程中遇到一些問題,花了一天多的時間幫忙釐清並解決編譯問題,還是稍微記錄一下好了XD

這個 magic string 就是所謂的 name mangling,請看這裡

環境介紹:同事沒有使用 PetaLinux 而是使用 Ubuntu 22.04。

同事在執行下面這支 script 時發生問題,一開始就跑不起來,看了 code 後發現,並沒有人去呼叫 main function,故需要改成先帶 main 再帶 target board 型號的方式來執行此 script。(後來才發現 Xilinx 文件是錯的,4.3.2 有錯,但 4.3 有稍微提到 run_all_target.sh 這支 script,裡面就可以看到正確呼叫 run_all_cifar10_target.sh 的參數傳法)

Vitis-AI-Tutorials/Tutorials/RESNET18/files/target/run_all_cifar10_target.sh

再來還是跟執行 run_all_cifar10_target.sh 有關的錯誤。

01.  missing symbol - _ZN6google15ErrnoLogMessageC1EPKciimMNS_10LogMessageEFvvE

這個名稱是 gcc 在編譯函數等 object 時所定義的 symbol name,gcc 是 follow 這個文件,我們也可以把這串名字丟到此網站,我們就可以看到此 symbol 的原型宣告如下:

google::ErrnoLogMessage::ErrnoLogMessage(char const*, int, int, unsigned long, void (google::LogMessage::*)())

同事的問題就是在安裝的 glog 中找不到同樣名稱的函數,嚴格說起來是差在第 4 個參數,我們跟這串文字差了一個 m,而這個 m 就表示參數是 unsigned long。

同事還蠻幸運的,在降版本到第二個版本後,就順利編譯出有一樣 symbol 的 so 檔。

02. missing symbol - xclIPSetReadRange

這個問題跟上面類似,也是版本相關的 issue,後來在 review XRT 版本後,確定某些版本以前的 code 確實缺少了這個函數(XRT/src/runtime_src/core/pcie/linux/shim.cpp),後來便決定使用 202220.2.14.354。

底下是自己編譯此版本會遇到的問題。

首先在 sudo <XRT>/src/runtime_src/tools/scripts/xrtdeps.sh 時,會看到類似沒有安裝 gcc 8 的訊息,因為環境已經有 gcc 11 了。

接著執行 build.sh 發現很快就結束了,原因是 script 中,gcc 版本是 hard code 寫死,直接改成對應的版本即可,接下來就是一連串的 sudo apt-get install 地獄XD

此 script 會先執行 configure 相關工作,反正遇到什麼錯誤就 google 一下,安裝對應的 xxx-dev 版本即可,印象中有 4 ~ 5 個要裝。

最麻煩的是在 runtime_src/xdp/CMakeLists.txt:427 會報找不到 xdp_hw_emu_device_offload_plugin 錯誤,但這個東西如果我沒搞錯應該是編譯時才會編譯,懷疑是 CMakeLists.txt 沒寫好,可能跟相容 cross-compile 有關?

想了一下,直接註解 427 及 428 行即可。

接下來是一連串的 build error,最糟糕的都是直到編譯某支檔案時才會報找不到 header file 的錯誤,此時也只能一個一個 apt-get 安裝,印象編譯到 40 幾趴還會有錯誤,大概也是有 4 ~ 5 個要安裝,之後便可以順利編譯出 Debug 和 Release 版本了。

接著使用 objdump -T xxx_core.so | grep xclIPSetReadRange 確認一下,這次就可以順利看到 symbol。

由於 Release 版本還在編譯,簡單使用 export LD_LIBRARY_PATH=/XXX/Debug 來讓執行時可以找到 xxx_core.so 的 xclIPSetReadRange symbol 來驗證是否有順利解決問題。

花了一天多幫同事搞定這個問題,最後還是沒能在 target board 跑出想要的結果,但這又是另一個故事了XD

2023/11/24 更新

為了寫技術文件,從零亂的計算紙中找到蛛絲馬跡,凡走過必留下痕跡。

fix configure error

sudo apt-get install libdrm-dev
sudo apt-get install ocl-icd-opencl-dev
sudo apt-get install libncurses5-dev
sudo apt-get install libssl-dev
sudo apt-get install rapidjson-dev

-------------
CMake Error at runtime_src/xdp/CMakeLists.txt:427 (add_dependencies):
  The dependency target "xrt_hwemu" of target
  "xdp_hw_emu_device_offload_plugin" does not exist.

https://github.com/Xilinx/XRT/issues/6942

fix it
comment runtime_src/xdp/CMakeLists.txt line427, line428

-------------------------------------------------------------------
fix build error

sudo apt-get install uuid-dev
sudo apt-get install ocl-icd-dev
sudo apt-get install libcurl-dev
sudo apt-get install libudev-dev

2023年7月2日 星期日

Linux shell script 對換行字元真的很敏感

終於還是讓我新買的 Kobo Clare 2E 可以爽爽的用 Logitehch R500 翻頁器了!

原本以為是不是 github 某網友參考我 Kobo Libra 2 build 出來的 uhid.ko 有問題,今天居然福至心靈發現,原來是我的 run.sh 不是拿我之前為 Libra 2 寫好的檔案,而是直接使用文字編輯器複製貼上指令的緣故,由於我的工作環境是 Windows 作業系統,故換行字元會比 Linux 多了一個 \r。

shell script 遇到這個 Windows 獨有的換行字元會不開心,導致 insmod 的指令沒有執行,在手動砍掉句尾 \r 後,Logitech R500 也順利的在 Kobo Clare 2E 上使用。

不只如此,我的 KoboPageTurner Wi-Fi 翻頁器以及 kobofileserver 專案也是可以順利的執行,這下就只差開發 Kobo EInkBro 了?

2022年4月22日 星期五

GNU Global 一些數據參考

很久以前在做 Windows Mobile 手機時,trace code 都是使用 Global,後來比較沒機會接觸到這樣龐大的 code base,故都是用我的 UltraEdit 搞定。

最近有同事問我 trace linux kernel 的事,拿 5.17.3 版本試了一下,留下記錄當做參考。

兩種使用方式

01. VSCode + Global

可以參考這裡

02. 直接使用 Global 並產生 HTML 檔案

gtags 執行速度很快,大概不到 10 分鐘就建好 tag 資料庫。
htags - sna 總共花了約 4 小時又 43 分才建好所有 HTML。

另外,HTML 整包資料夾的大小約為 12.1G,硬碟大小則是 17.3G,裡面共產生 2,047,758 支檔案及 8 個資料夾。

我們也可以直接用指令查詢 tag 資料庫,只要記住兩個指令就好。還有下指令時不需要在 tag 檔案那層,隨便一層都可以。

global XXX  直接找 XXX 定義的地方。
global -r XXX 則是找 XXX 被使用的地方。

加上 -x 則是取得詳細的資料。


記得在使用 Global 前,要先 build 過 kernel 幾分鐘,好讓相關的 CONFIG_XXX 自動生成,其位置是在 CodeRoot/include/generated/autoconf.h

2022年4月13日 星期三

Linux kernel coding style

最近不知道為什麼喜歡看 Linux Document XD 雖然大部份都看不懂居多!


上面文章描述了 kernel coding style 的注意事項,其中開宗明義就提到最好使用 tab 字元,而縮排應該是 8,因為較深的區塊顯示可以讓工作一整天的 kernel developers 更容易的注意到縮排的區塊。如果因為縮排為 8 而讓文字超過螢幕 80 個字元的寬度,這就表示你的 code 有問題了,一般來說不應該超過 3 層。

想想還蠻有道理的,Go 語言也是提倡要用 tab 縮排。

2022年4月8日 星期五

Linux Input Subsystem 入門參考文件

Linux 果然是世界上最棒的作業系統呀 ~~

2022年4月6日 星期三

武林絕學 - 金星幻式 - 七星連線

標題雖然是布袋戲的招式名稱,但我想不到比這個貼切的標題了XD

從 3 月下旬開始,為了研究 Libra 2 的藍牙,不但買了 Libra 2 本人回來研究,還陸續買了 E-PCG233 藍牙滑鼠以及 8BitDo Zero 2 搖桿回來,正所謂孩子的學習不能等呀?

好不容易大概釐清了 Libra 2 的藍牙問題?但後續還有一個小尾巴卡在我心中,那就是為什麼滑鼠以及我的 R500 翻頁器都會按下一次鍵後觸發 2 次事件?雖然我大概已經能猜測出問題出在哪裡就是了(按下及放開的事件,Key Scan Value 都一樣)。

我認為天底下的問題只有兩種,一種是目前可以解決的,另一種則是目前無法解決的。

很顯然的,我認為這個小尾巴是屬於前者的範疇!

今天還蠻早起來的,故想直接用 cat 抓 raw data 來看,畢竟我在 KoboPageTurner 專案就已經有相關經驗了,但不知為什麼,早上突然想用 PC Linux 來測試,想說順手用 evtest 來看一下,結果發現 Linux 版的 evtest  (1.34),居然可以判讀更多的 raw data,故可以一目了然的確定問題便是出在放開按鍵的事件沒錯。


Raw Data 長這樣(不同時間抓的)。


那我們要怎麼解決 kobo-btpt 收到兩次事件的問題?一個是我之前寫的 filter,過短時間內收到相同的 event 便忽略它,可惜的是一樣的 code 只在 Elipsa 生效,Libra 2 沒有辦法成功(後來發現自己耍笨,同時執行了原本的 kobo-btpt 及自己修改的版本)。另外一個則是希望 Kobo 的 Input Subsystem 也能收到 type 1, code 272 的事件,那我們只要在 value = 1(1 是按下,0 是放開)時觸發 Kobo 藍牙翻頁函式即可,換句話說,kobo-btpt config file 要如下設定,注意這裡都是 10 進制:

prevPage 1 272 1
nextPage 1 273 1

雖然我還沒測試,但我想八九不離十可以成功。

那這個跟我們的布袋戲標題有啥關係?

此招式是天宇一好漢的武功之一,我認為作學問也是如此,雖然我們從 Google 搜尋來的都是片斷屬於點的知識,但當你一點一滴的累積之後,知識自然會從點擴展到線,最後則變成面的學問。

因此,只要是屬於目前可以解決的問題,我希望都能把它搞懂,也許將來的某一天就會派上用場也說不定。

期許自己能夠永遠的不忘初心。

題外話:我想懂 Linux Input Subsystem 的人,應該會覺得這麼簡單的事,哪來這麼多感想XD

2022年3月29日 星期二

Kobo Libra 2 vs Logitech R500

為了測試 Libra 2 這台的藍牙是否真如傳說中的不堪?狠下心來購買了它,一試之下,果然跟傳說中的一樣爛XD

在 debug 過程中,無意間發現了一支程式 /bin/bluetoothctl,查了一下似乎可以用來設定藍牙?好不容易在 unpair 和 pair 的過程中,終於可以成功與我的 Logitech R500 成功連接。


感覺研究研究,搞不好可以找到問題在哪?

另外,使用 logread 讀取 log,可以看到一個錯誤訊息。

Mar 29 23:18:52 bluetoothd[1397]: src/service.c:service_accept() input-hog profile accept failed for EF:06:4D:1A:69:69

雖然藍牙初嘗試不是很順利,但至少我的 KoboPageTurner 可以成功使用,直接使用 Elipsa 觸控封包格式即可,總算不是一事無成。

2022/03/30 更新

比對了一下 Elipsa 和 Libra 2,目前看到有兩個差異,Elipsa 的 kernel 和 Bluetooth management interface 都比 Libra 2 新,感覺是 kernel issue?


Bluetooth management interface 1.9 (1.14).

2022/03/31 更新


雖然不懂藍牙,但這幾天查了一些資料,我覺得問題可能是出現在以下幾個地方:

1. CONFIG_RFKILL kernel 未編譯進去。
2. 一樣是 kernel 哪邊的問題 (uhid)。
3. BT chip 本身的問題 (RTL8723DS vs RTL8821CS)。

看起來似乎不是改改設定就可以解決的事,至少嘗試調整 /etc/bluetooth/main.conf 或是 /etc/bluetooth/input.conf 中的參數,看起來都沒有幫助。

2022/04/01 更新

無意間在網路上看到一份 porting guide,看起來要支援 HOG,kernel 應該要打開一些功能,就不知道 RTL8723DS 本身是否有支援就是?假設不是 BT chip 的問題也不是 Kobo 為了市場區隔的問題,後續只要系統更新,應該就能支援翻頁器了。


另外,大部份的 Linux 使用的 Bluetooth Stack 都是 BlueZ,其 daemon 是 bluetoothd,路徑為 /libexec/bluetooth/bluetoothd,在 Kobo 下如果嘗試要修改設定,可以使用 kill 砍掉它,再重新背景執行 deamon 即可。

晚上使用 bluetoothd -d -n 開啟 debug 訊息,可以看到 Elipsa 對待 R500 的方式。

profiles/gap/gas.c:gap_probe() GAP profile probe (EF:06:4D:1A:69:70)
src/service.c:change_state() 0x183a8c8: device EF:06:4D:1A:69:70 profile gap-profile state changed: unavailable -> disconnected (0)
profiles/input/hog.c:hog_probe() path /org/bluez/hci0/dev_EF_06_4D_1A_69_70
src/device.c:gatt_debug() (chan 0x1837f58) ATT PDU received: 0x1b
src/device.c:gatt_debug() (chan 0x1837f58) ATT PDU received: 0x1b

上面最後兩行是按下 R500 翻頁鍵後 Elipsa 吐出來的訊息,Libra 2 雖然無法使用 R500,按下翻頁鍵後一樣能吐出相同的訊息,真的覺得更新 kernel 應該就可以正常了?

另外,Bluetooth 的 spec 看起來是公開的,目前是 Core_v5.3。

2022/04/03 更新

前幾天買了一支便宜的藍牙滑鼠,原本以為使用 kobo-btpt 專案就可以正常使用,但還是不如預期,留個 log 當記錄。


晚上又認真比對了 Elipsa 和 Libra 2 配對 R500 的行為。

Elipsa:
bluetoothd 沒有錯誤訊息,會長出一個 /dev/input/eventX 的裝置,使用 evtest 可以成功補捉左右鍵的 scan code。

Libra 2:
bluetoothd 有錯誤訊息,無法長出 /dev/input/eventX 裝置,故錯誤訊息其實不是斷線,pair 和 connect 都有成功。

2022/04/04 更新

evtest 的 value 是 16 進位數字,在修正了此錯誤後,終於可以使用我的藍牙滑鼠(E-books E-PCG233)翻頁,真是得來不易呀。雖然這個滑鼠按下一次鍵會發送 2 次 event,但我只是想要研究 Libra 2 的藍牙,故對我來說,這個學習已經完成XD

2022/04/05 更新

昨天順手在 kobo-btpt 裡加了一個 filter,避免過短時間內收到相同的 event,不過在 Libra 2 無法成功,且呼叫 Kobo 藍牙翻頁的函數感覺是非同步?但同樣的 filter 在 Elipsa 就可以正常工作。

晚上又認真的在 Elipsa 上試了一下 R500,使用 evtest 補捉的結果,一樣是按一下鍵會送 2 次 event,既然是一樣的行為,那為什麼 Kobo 只會翻一次頁,我想這裡面可能還有我不知道的事在?

Event: time 1649163457.612279, type 4 (Misc), code 4 (ScanCode), value 70050
Event: time 1649163457.612279 ------- Report Sync ------ x: 400 y: 80 p: 0 ------------
Event: time 1649163457.657992, type 4 (Misc), code 4 (ScanCode), value 70050
Event: time 1649163457.657992 ------- Report Sync ------ x: 400 y: 80 p: 0 ------------

如果要我猜的話,會不會 1 個是按下事件,1 個是放開事件?故 kobo-btpt 應該要有能力去判斷放開事件,可能要從別的 event,因為 type MISC 的 press value 應該都一樣,以上面例子來看都是 0x70050。不過問題來了,evtest 只有顯示出 Report Sync 並未顯示出其他 event ,會不會是 evtest 並沒有能力解析,故才沒有顯示呢?

2022/04/06 更新

太相信 Kobo 內附的 evtest tool 了,明明藍牙滑鼠有其他更適合的 event 可以監聽,詳此篇

最後正確的設定檔如下:

prevPage 1 272 1
nextPage 1 273 1

2022/04/07 更新

昨天晚上本來以為已經妥當了,沒想到用了 EV_KEY  後,行為還是不符預期,一樣會觸發翻頁兩次,再加上剛到的 8BitDo Zero 2 gamepad 在 Libra 2 也是時好時壞,有時候可以長出 device,有時候又不行,如果不是像我一樣 telnet 進去閱讀器的人,一定不知道到底發生了什麼事?

就在正準備睡覺的時候,熊熊想到,之前改了 kobo-btpt source code 來 debug,把原始的 libbtpt.so 改個名字,一樣放在 /usr/local/Kobo/imageformats 裡面,這個資料夾裡的 .so 檔,應該是會被 Kobo 自動載入,故我其實是同時在跑兩支 libbtpt.so 而不自知,難怪之前的 debug 訊息才會覺得如此之怪,移除之後,果然一切恢復正常,搞定收工(還是不應該使用 EV_MSC type,因為會收到兩次事件,之前的問題是組合技,既用了不該用的 type,也執行了兩支 libbtpt.so)。

2022/04/08 更新

找到檢查 Linux Kernel Config 的方法了(/proc/config.gz),看起來 Libra 2 禁用了很多 Elipsa 有打開的項目,就不知道是 Kobo 為了市場區隔,還是只是單純的因為 Libra 2 的藍牙晶片不支援的緣故呢?


2022/04/09 更新

昨天晚上下班後決定要來編譯模組了,目標放在 uhid.ko。

CONFIG_HIDRAW=y (這個也許沒影響?)
CONFIG_UHID=m


使用環境

Windows 10 + Docker Desktop (ghcr.io/pgaskin/nickeltc)
linux-4.1.15.tar.gz
Copy /proc/config.gz of Libra 2 to /linux-source/.config

make ARCH=arm CROSS_COMPILE=/tc/arm-nickel-linux-gnueabihf/bin/arm-nickel-linux-gnueabihf- oldconfig
make ARCH=arm CROSS_COMPILE=/tc/arm-nickel-linux-gnueabihf/bin/arm-nickel-linux-gnueabihf-

中間有遇到找不到 bc 及 lzop 兩個執行檔錯誤,我檢查一下 Windows 10 Docker Desktop,感覺底層還是 Windows 的那個 Linux Subsytem(WSL),故我直接複製 WSL 裡的這兩個執行檔及相關的 so 檔進去我的 docker instance,然後建立 soft link(ln -s liblzo2.so.2.0.0 liblzo2.so.2 ... ),看起來這樣就過了?雖然我前後總共重 build 了 3 次就是!

感謝有 make,只有初始檢查比較久,編譯過的都不用再重新編譯,但我的 8 歲老筆電果然很吃力呀,打文章的同時,整個程序都還沒跑完,我只是先偷跑去 /linux-source/drivers/hid 下,把 build 好的 uhid.ko 複製出來測試XD


阿母,我成功了!我的 Logitech R500 終於可以爽爽用了,要感謝的人太多了,就感謝天吧XD


2023/07/02 更新

6 月份買了一台 Clare 2E,為了取代電池快卦掉的 PW3,試了一下,藍牙跟 Libra 2 有一樣的問題,由於 kernel 版本一樣,直接拿原本的 solution 來用,完全無痛接軌。

另外,我的 KoboPageTurner 專案一樣可以用在 Clare 2E 上,raw data 使用 Elipsa 格式,觸控座標設成跟 Clare 一樣即可。

2022年1月14日 星期五

懶惰不是病,但懶下去會要人命

可能是我螢幕有設定濾藍光的緣故,每次在終端機下要看目錄名稱都很吃力,反正有 tab 可以補完我也不以為意!

今天終於受不了了,上網查了一下如何更改設定,終於可以看清楚目錄名稱了XD

add LS_COLORS in $HOME/.bashrc

export LS_COLORS=$LS_COLORS:'di=0;92:'

2021年11月1日 星期一

Linux 下開啟檔案數量限制的相關指令及設定檔

在 Linux 下,萬物幾乎皆是檔案,為了建立一個網路連線,我們就會開啟一個 file descriptor。

一個 process 可以開啟的檔案數量是有限的,預設值是 1024,我們可以使用 ulimit -n 來確定。我們可以透過修改 /etc/security/limits.conf 來放寬限制,以 Ubuntu 來說,我們可以針對一般使用者來放寬限制到 10240,注意如果是要針對 root,則第一個欄位必須明確指定 root 才行。

* soft nofile 10240
* hard nofile 10240

我們也可以使用 cat /proc/PID/limits 來看某行程目前的限制設定。

另外,我們可以使用 cat /proc/sys/fs/file-max 來看 Linux kernel 允許開啟的最大數量,而使用 cat /proc/sys/fs/file-nr 可以從第一個欄位看到目前開啟的數量。

如果我們想調整這個數字,則是修改 /etc/sysctl.conf,指定 fs.file-max = XXXX。

2021年3月30日 星期二

load average on linux

既然已提早完成部份 Q2 KR 項目,反正還有時間乾脆來跑一下測試。

一般我們都會使用 top 指令來監控系統整體狀況,在結果視窗右上角有一個 load average 資訊,從 man 可以得知這是指系統負載,但這個數字要如何解讀完全沒有頭緒,於是又拜託了 Google 大神。


上面文章是第一筆搜尋結果,講得蠻淺顯易懂的,一下子就把它看完了,當我正準備離開網站時,眼睛餘光瞄到下面有網友留言這篇文章內容有誤,於是又順著留言看了第二篇文章。


簡單來說,這個數字不只跟 CPU 有關,其負載還牽涉到 I/O 等,故不能單純拿這個數字除以 CPU 核心數來判斷系統是否過載。

該文作者建議先觀察這個數字在什麼數值時是表示工作良好,而當這個數字超過原本的數值時,我們就必須藉由其他的指標來確認發生什麼事。

我之所以如此關心這個議題,是因為我在測試時發現當查詢 mongoDB 的 collection 擁有大量筆數資料時,不但記憶體使用量會突然爆增,且 CPU 使用率也會超過 100% 好幾秒。

由於我要查詢的欄位並沒有建立索引,故直覺一定是針對常用查詢條件建立索引以減輕 CPU 負擔,但很明顯的我的系統負載也會從 0.2X 增加到 0.6X。

我的資料量目前是 3 千多萬筆,一個月後就會變成兩億一千多萬筆,而這還只是一個 collection 而已!

這也是為什麼我現在如此在意這個數字的原因,我必須實測才能得知最終結果。

2021/04/08 更新

連假前重新跑了一次模擬,昨天進終端機看,三個負載數字都來到 1.2X 左右,但是在 ESXi 過去一小時監控視窗數據顯示,CPU 使用率都還沒超過 30%,目前筆數已經來到四千多萬筆。

2021/04/12 更新

目前筆數來到八千多萬筆,查詢還是可以在秒級的單位內完成,15 分鐘負載來到 1.74 左右,唯一不一樣的是 ESXi 的最小 CPU 使用率已經超過 1 了。


2021/04/19 更新

目前筆數來到一億三千多萬筆,查詢還是可以在秒級的單位內完成,15 分鐘負載來到 1.5X 左右,唯一不一樣的是真正的 Server 已掛,但我的模擬程式還是很認真的工作。由於肩牓受傷,不方便低頭確認 Server 機器狀況,只好等到好一點再來看怎麼回事?

2020年9月2日 星期三

使用 ls 檔名出現單引號

最近在做系統轉移,要將內部使用的系統從 Windows 轉到 Linux,在執行某個功能後,發現產生出來的檔案名稱會被單引號包住。

原本第一個念頭是不是程式需要修改?檢查了一下,發現跟程式沒有關係!後來才發現,是程式產生出來的檔名裡面有特殊符號的關係。

因此使用 ls 指令時,顯示的檔名就會被單引號包住。

真是不經一事,不長一智呀。

2020年1月21日 星期二

使用一行指令砍掉某個 linux process

最近在試 MLPerf-inference,有一個 scenario 一直搞不定,常常需要手動 kill,每次都要做 2 個動作,一個是先用 ps + grep 找出 pid,接著再用 kill 砍掉。

想了一下,應該這樣就可以解決了。

id=$(ps -aux | grep '/bin/bash \./run_lo' | awk '{print $2}'); kill -9 $id

也許還有其他方式,畢竟我很少運用重導向,就先這樣吧。

2019年12月16日 星期一

Ubuntu 16.04 + NVIDIA-Linux-x86_64-410.93.run driver 循環登入視窗解決方式

當初這個系統是為了跑 TensorFlow-gpu 版本安裝的,中間一度有幫人 build tool,測試發送 ARP 廣播封包等。

最近使用 TensorFlow Lite 時偶然發現,在本機前面登入時,會一直循環登入,也就是輸入帳密後,又會回到輸入帳密的登入視窗。

有嘗試重裝同一版 driver,但過程會一直報錯,看 /var/log/nvidia-installer.log 也看不出什麼特別的,只能看出似乎幾個 c code 的 structure 有衝突,直覺是我的 GCC 版本似乎跟之前安裝時的不一致,但我印象中幫人測試 tool 時,我並沒有做額外的更新。

沒辦法,使出最後一招,下載最新版的  NVIDIA-Linux-x86_64-440.44.run,安裝後馬上恢復正常。

稍微查了一下,網路上是建議安裝 NVIDIA driver 時,不要預設使用圖型登入,聽說比較容易有問題,記錄一下,避免忘記。

2019年10月22日 星期二

Use 64 bit offset in fseek function

fseek 的 offset 在 C Spec 中是 32 bit 的長度,由於現在的硬碟都很大,加上 GPT 有關 LBA 的欄位都是 8 個 Byte,當存取較後面的 Sector 時,勢必無法使用 fseek 這類的標準 C 函式庫,故我在撰寫 WinGPT 時,一開始使用的是 Win32 API。

後來查了一下資料,GCC 類的 compiler 有一個 fseeko 的函數可用,其宣告是在 stdio.h 裡,在 Windows 下不論是使用 TDM-GCC or MinGW 都可以直接使用,但在 Ubuntu 下,我們需定義一個 macro _LARGEFILE_SOURCE,記得要在 include 其他 header 時先定義。

https://github.com/tylpk1216/WinGPT/blob/master/WinGPT.c

另外在查資料時,發現到 2 件事:

1. printf%ll 在 TDM-GCC or MinGW 編譯時,如果有設 -Wall,會有 "warning: unknown conversion type character 'l' in format" 之類的錯誤訊息,那是因為這些 compiler 底層呼叫的仍是 Windows Runtime( msvcrt-DLL ),由於它不相容 C99 標準,故會有此 warning。

解決方式: 使用 %I64

2. 可以使用 "__linux__" 區分是 Ubuntu or Windows 環境,不需使用 -D 選項就可以寫出漂亮的 code。

2019年9月16日 星期一

列出 Linux 某目錄下所有檔案與目錄名稱

太久沒用,花了 10 幾分鐘才搞定,記錄一下。

#include <stdio.h>
#include <dirent.h>
#include <string.h>

void parseDir(char *dirPath) {
    struct dirent *de;
    DIR *dr = opendir(dirPath);

    if (dr == NULL) {
        printf("Can't open folder %s \n", dirPath);
        return;
    }

    while ((de = readdir(dr)) != NULL) {
        if (strcmp(de->d_name, ".") == 0 ||
            strcmp(de->d_name, "..") == 0) {
            // do nothing
        } else if (de->d_type == DT_DIR) {
            char path[256];
            sprintf(path, "%s/%s", dirPath, de->d_name);
            printf("folder - %s \n", path);

            parseDir(path);
        } else {
            printf("file - %s/%s \n", dirPath, de->d_name);
        }
    }

    closedir(dr);
    return;
}

int main(void)
{
    parseDir("/data/imagenet/raw_data/train");
    return 0;
}