例子是從《Android系統源代碼情景分析》第二章抄過來的,在學習的過程中還是遇到了不少的問題。
個人體會:在學習第二章之前應該把《Linux設備驅動程序》這本書至少前四章要讀一遍,理解一些基礎概念和背景知識,不過這本書還是略舊,比如sysfs就沒有解釋,多google吧。
本書第二章要理解透了再往下進行,因為這個簡單的例子從下往上貫穿了Android系統各層,是理解后面各章的基礎。
下面列出我遇到的問題和解決辦法。
-
三類文件系統接口的關系、作用分別是什么?
它實現了proc文件系統接口、傳統的設備文件系統接口和devfs文件系統接口。
類Unix系統有一條基本的設計哲學:幾乎所有的數據實體都被抽象成統一的接口——文件來看待。procfs、devfs和sysfs都是這種設計的體現。
/dev目錄下每一個文件對應一個設備,通過操作這些文件可以實現與內核的交互,但devfs存在一些缺點,如命名不靈活,不能任意指定文件名,而且所有文件都在/dev/根目錄下。進而演生出sysfs,它把實際連接到系統上的設備組織成一個分級的文件體系,比devfs更清晰更便於管理,sysfs掛載在/sys下面。
/proc文件系統中主要包含三大類內容:進程相關部分、系統信息部分和系統自信息部分。顯然在本例中,procfs和sysfs部分的接口,作為入門第一個樣例來說並不必要。
因此我打算只實現傳統設備文件系統接口的部分,sysfs和procfs暫不實現。我認為依然可以完整地正常工作。
-
編譯問題
- 每次編譯和運行模擬器之前需要把各環境變量重設一遍:
$ cd WORKING_DIRECTORY $ source build/envsetup.sh $ lunch aosp_arm-eng $ cd kernel $ cd goldfish $ export ARCH=arm $ export SUBARCH=arm $ export CROSS_COMPILE=arm-eabi- $ export PATH=WORKING_DIRECTORY/prebuilts/gcc/darwin-x86/arm/arm-eabi-4.8/bin:$PATH $ make goldfish_armv7_defconfig $ make menuconfig $ make -j8 $ emulator -kernel arch/arm/boot/zImage &
-
在__freg_setup_dev函數中,對函數init_MUTEX的調用編譯出錯,這是因為該函數已經被啟用,改成如下即可:
sema_init(&(dev->sem), 1);
- 修改內核Kconfig文件。我編譯的內核是3.4,需要在drivers/Kconfig中添加
source "drivers/freg/Kconfig"
而不是在arch/arm/Kconfig中。
-
配置
- 在Mac OSX,調用make menuconfig的時候出錯,解決辦法已經更新到《Android源碼、內核編譯》這篇博文里了。
- 進入make menuconfig配置界面后,如果要設置Enable loadable module support,這塊的交互有點坑爹。初次進入界面是這樣的,Enable loadable module support沒有被選中:
如果直接回車進入子菜單,發現前面是---,是不能被修改的:
我以為是自己的內核版本有問題,倒騰了半天才明白:應該在一級界面中先對Enable loadable module support按下Y,使之選中:
然后再回車進入才能看到並修改子項內容:
一萬頭草泥馬奔騰而過,害老子研究半天……
-
調試
-
查看內核log
我把模塊編譯到內核中,起初卻在/dev下面找不到freg文件,必須要調試代碼看在哪一步出了錯。freg.c源碼多出調用printk函數寫了日志,我在每條日志字串頭部加了[freg]的字樣,如下:
printk(KERN_ALERT"[freg]Initializing freg device.\n");
以便在浩瀚的內核日志中篩選出freg的日志。
-
方法一:可以使用dmesg查看內核打印信息,再配合grep如下:
$ adb shell $ dmesg | grep "\[freg\]" [freg]Initializing freg device. [freg]Succeeded to initialize freg device.
- 方法二:可以在運行emulator的時候加-show-kernel參數:
$ emulator -kernel arch/arm/boot/zImage -show-kernel &
-
動態加載模塊
當在make menuconfig中選擇了動態加載模塊,編譯、啟動emulator,需要通過adb把.ko模塊push到emulator:
# 啟動emulator $ emulator -kernel arch/arm/boot/zImage & # 把剛剛編譯的freg.ko拷貝到emulator的/data下 $ adb push drivers/freg/freg.ko /data $ adb shell ls -l /data/freg.ko -rw-rw-rw- root root 5281 2016-02-21 01:45 freg.ko # 加載freg.ko模塊 $ adb shell insmod /data/freg.ko