在Android模擬器和Ubuntu上測試Linux驅動


開發可統計單詞個數的Android驅動程序

      在上一篇文章中已經實現了一個簡單的Linux驅動程序,該驅動的功能是統計給定字符串中的單詞數。並且在最后已經將該Linux驅動的源代碼成功編譯成動態Linux驅動模塊word_count.ko。下一步就是測試該模塊。測試的方法很多,最常用的就是直接在Ubuntu  Linux、Android模擬器中測試。當然,這 對於本章實現的Linux驅動是沒問題的,但是對於需要直接訪問硬件的驅動在Ubuntu Linux上測試就不太方便。在這種情況下就需要在相應的硬件上進行測試。

     對於一個Linux驅動程序,一開始可以在UbuntuLinux上做前期開發和測試。對於訪問硬件的部分也可以在Ubuntu Linux用軟件進行模擬。當基本開發完成后,就需要在開發板或工程樣機上使用真實的硬件進行測試。當然,最后還需要在最終銷售的手機上進行測試。最終測 試通過,Linux驅動才能算真正開發完成。在開發Linux驅動的過程中一個重要的步驟就是測試。本節將結合實際的開發流程介紹在不同平台上測試 Linux驅動程序。這些測試平台包括UbuntuLinux、Android模擬器和S3C6410開發板。

一、使用Ubuntu Linux測試Linux驅動

      本節將介紹如何在Ubuntu Linux下測試驅動程序。由於上一節編寫的Linux驅動程序通過4個字節從設備文件(/dev/wordcount)返回單詞數,所以不能使用cat 命令測試驅動程序(cat命令不會將這4個字節還原成int類型的值顯示)。但可以使用如下命令從日志中查看單詞數。

# sh build.sh 
# echo 'I love you.'  > /dev/wordcount 
# dmesg 

 執行上面的命令后,如果輸出如圖6-13所示白框中的信息,說明驅動程序成功統計了單詞數。

       雖然使用echo和dmesg命令可以測試Linux驅動程序,但這種方式並不是真正的測試。為了使測試效果更接近真實環境,一般需要編寫專門用於測試的 程序。本節將為word_count驅動編寫一個專門的測試程序(test_word_count.c)。test_word_count.c通過直接操 作/dev/wordcount設備文件與word_count驅動進行交互。測試程序的代碼如下:

    #include <stdio.h>  
    #include <fcntl.h>  
    #include <unistd.h>  
    #include <stdlib.h>  
    #include <string.h>  
    int main(int argc, char *argv[])  
    {  
        int testdev;                //  打開設備文件(/dev/wordcount)的句柄  
        unsigned char buf[4];          //  表示單詞數的4個字節  
        //  打開設備文件  
        testdev = open("/dev/wordcount", O_RDWR);  
        //  如果open函數返回-1,表示打開設備文件失敗  
        if (testdev == -1)  
        {  
            printf("Cann't open file \n");  
            return 0;  
        }  
        //  如果test_word_count后面跟有命令行參數,程序會將第1個參數值當作待統計的字符串  
        //  如果沒有命令行參數,則只讀取設備文件中的值  
        if (argc > 1)  
        {  
            //  向設備文件寫入待統計的字符串  
            write(testdev, argv[1], strlen(argv[1]));  
            //  輸出待統計的字符串  
            printf("string:%s\n", argv[1]);  
        }  
        //  讀取設備文件中的單詞數(4個字節)  
        read(testdev, buf, 4);  
      
        int n = 0;      //  單詞數  
      
        //  將4個字節還原成int類型的值  
        n = ((int) buf[0]) << 24 | ((int) buf[1]) << 16 | ((int) buf[2]) << 8  
                | ((int) buf[3]);  
            //  分別輸出從設備文件獲取的4個字節的值  
        printf("word byte display:%d,%d,%d,%d\n", buf[0], buf[1], buf[2], buf[3]);  
        //  輸出統計出的單詞數  
        printf("word count:%d\n", n);  
        //  關閉設備文件  
        close(testdev);  
        return 0;  
    }  

       test_word_count程序可以跟1個命令行參數(多個命令行參數只會使用第1個命令行參數)。如果命令行參數值含有空格,需要使用單引號(')或雙引號(")將參數值括起來。可以使用下面的一組命令測試word_count驅動程序。

# gcc test_word_count.c  -o test_word_count  
# test_word_count  
# test_word_count "I love you."  

    執行上面的命令后,如果輸出如圖6-14所示的信息(假設word_count以前統計過一個含有4個單詞的字符串),表示word_count驅動成功測試。

二、在Android模擬器上通過原生(Native)C程序測試Linux驅動

      雖說我們開發的是Linux驅動,但本書主要介紹的是Android版的Linux內核,因此,Linux驅動只在Ubuntu Linux上測試成功還不能保證在Android設備上一定能正常工作,所以必須在Android設備上進行測試。Android設備有很多種類,如安裝 了Android的開發板,運行Android系統的手機或平板電腦等。但離我們最近的並不是這些硬件設備,而是Android模擬器。Android模 擬器可以模擬絕大多數真實的環境,所以可以利用Android模擬器測試Linux內核。

      在Android模擬器上測試Linux驅動首先應該想到的,也是最先應該做的就是將word_count.ko驅動模塊安裝在模擬器上。可能讀者使用過 adb shell命令。如果進入Android模擬器的命令提示符為“#”,說明通過命令行方式進入Android模擬器直接就是root權限(命令提示符為 “$”,表示非root權限),因此從理論上可以使用insmod命令將word_count.ko驅動模塊直接安裝在Android模擬器中。現在我們 來測試一下,看看是否可以將word_count.ko安裝在Android模擬器上。現在執行build.sh腳本,並選擇“Android模擬器”, 腳本會自動將word_count.ko文件上傳到Android模擬器的/data/local目錄,並進行安裝。如果讀者選擇的是S3C6410開發 板,在安裝word_count.ko時就會輸出如下的錯誤信息,表示編譯Linux驅動的Linux內核版本與當前Android模擬器的版本不相同, 無法安裝。所以在編譯Linux驅動時,必須選擇與當前運行的Linux內核版本相同的Linux內核進行編譯,否則就無法安裝Linux驅動。

insmod:init_module ‘/data/local/word_count.ko’ failed(Function not implemented)  

注意:建議上傳文件到Android模擬器或開發板時,將文件放到/data/local目錄,系統很多其他的目錄,如/system/bin,都 是只讀的,除非將word_count.ko文件打包進system.img,否則無法向這些目錄寫數據,即使有root權限也不行。

     用於Android模擬器的goldfish內核默認不允許動態裝載Linux驅動模塊,因此需要在編譯Linux內核之前執行如下命令配置Linux內核。

# cd ~/kernel/goldfish  
# make menuconfig  

     執行上面的命令后,會出現如圖6-15所示的設置界面。按“空格”鍵將第二項“Enable loadable module support”選中(前面是[*]),然后按“回車”進入子菜單,選中前3項,如圖6-16所示。否則Linux驅動模塊仍然無法安裝和卸載。當退出設 置菜單時保持設置。最后按4.2.3節的方法重新編譯Linux內核,


成功編譯內核后,Android模擬器可以使用新生成的zImage內核文件動態裝載Linux驅動模塊。

    現在執行build.sh腳本文件完成對word_count驅動的編譯、上傳和安裝的工作,然后進入Android模擬器的終端,使用echo和dmesg命令可以測試word_count驅動和查看測試結果,方法與上一節相同。

注意:編譯可在Android模擬器上運行的Linux驅動模塊要使用goldfish內核,使用其他的內核編譯word_count.c,安裝時會出現如下錯誤。

insmod: error inserting 'word_count.ko': -1Invalid module format  

       在Android模擬器上不僅可以使用Linux命令測試驅動,也可以像UbuntuLinux一樣使用本地C/C++程序進行測試。可能有的讀者 要問,Android不是只能運行由Java編寫的APK程序嗎?頂多是在APK程序中嵌入NDK代碼。還能直接運行普通的Linux程序嗎?答案是肯定 的。不過要滿足如下兩個條件。

1.  Android模擬器、開發板或手機需要有root權限。

2.  可執行文件需要使用交叉編譯器進行編譯,以便支持ARM處理器。

     現在使用交叉編譯器來編譯在上一節編寫的test_word_count.c文件。為了使編譯步驟盡可能簡單,我們使用Android.mk設置編譯參 數,並使用make命令進行編譯。首先在/root/drivers/ch06/word_count目錄中建立一個Android.mk文件,並輸入如 下的內容。

LOCAL_PATH:= $(call my-dir)  
  
include $(CLEAR_VARS)  
  
# 指定要編譯的源代碼文件  
  
LOCAL_SRC_FILES:= test_word_count.c  
  
# 指定模塊名,也是編譯后生成的可執行文件名  
  
LOCAL_MODULE := test_word_count  
  
LOCAL_MODULE_TAGS := optional  
  
include $(BUILD_EXECUTABLE)  

 

Android.mk文件中有如下兩個地方需要說明一下。

LOCAL_MODULE_TAGS

表示當前工程(Android.mk文件所在的目錄)在什么模式下編譯。如果設為optional,表示不考慮模式,也就是說在任何模式下都會編譯。該變量可以設置的值有user、userdebug、eng、optional。其中eng是默認值。

1.  user:限制用戶對Android系統的訪問,適合於發布產品。

2.  userdebug:類似於user模式,但擁有root訪問權限,並且可以從日志中獲取大量的調試信息。

3.  eng:一般在開發的過程中設置該模式。除了擁有userdebug的全部功能外,還會帶有大量的調試工具。

LOCAL_MODULE_TAGS 的值與TARGET_BUILD_VARIANT變量有關。TARGET_BUILD_VARIANT變量用於設置當前的編譯模式,可設置的值包括 user、userdebug和eng。如果想改變編譯模式,可以在編譯Android源代碼之前執行如下命令。

# export TARGET_BUILD_VARIANT = user

或使用lunch命令設置編譯模式。

# lunch full-eng

      其中full表示建立的目標,除了full目標(為所有的平台建立)外,還有專門為x86建立的full-x86。詳細的建立目標執行lunch命令后就會列出。在圖4-8已經顯示了Android4支持的建立目標的編譯模式。讀者可以到第4章查看該圖。

include $(BUILD_EXECUTABLE)

       BUILD_EXECUTABLE表示建立可執行的文件。可執行文件路徑是<Android源代碼目錄>/ out/target/product/generic/system/bin/test_word_count。如果想編譯成動態庫(.so)文件,可 以使用include $(BUILD_SHARED_LIBRARY)。動態庫的路徑是<Android源代碼目錄>/ out/target/product/generic/system/lib/test_word_count.so。如果想編譯成靜態庫(.a)文 件,可以使用include $(BUILD_STATIC_LIBRARY)。靜態庫的路徑是<Android源代碼目錄>/ out/target/product/generic/obj/STATIC_LIBRARIES/test_word_count_intermediates/test_word_count.

      為了將test_word_count.c文件編譯成可在Android模擬器上運行的可執行程序,可以將word_count目錄復制 到<Android源代碼目錄>的某個子目錄,也可以在<Android源代碼目錄>目錄中為word_count目錄建立一個 符號鏈接。為了方便,我們采用如下命令為word_count目錄在<Android源代碼目錄>/development目錄建立一個符號 鏈接(假設Android源代碼的目錄是/sources/android/android4/development/word_count)。

# ln -s  /root/drivers/ch06/word_count /sources/android/android4/development/word_count

現在進入/sources/android/android4目錄,執行下面的命令初始化編譯命令。

# source ./build/envsetup.sh

可以使用下面兩種方法編譯test_word_count.c。

1.     進入/sources/android/android4/development/word_count目錄,並執行如下的命令。

# mm

2.     在/sources/android/android4目錄下執行如下的命令。

# mmm  development/word_count

     成功編譯后可以在<Android源代碼目錄>/out/target/product/generic/system/bin目錄中找到 test_word_count文件。在隨書光盤和模擬環境中已經帶了編譯好的test_word_count程序(包括Emulator版本和 Ubuntu Linux版本),可執行程序一般不需要考慮Linux內核的版本,用交叉編譯器編譯的支持ARM處理器的程序即可以在Android模擬器上運行,也可 以在S3C6410開發板或其他有root權限的手機中運行。

Emulator版本的路徑

隨書光盤:<光盤根目錄>/sources/ch06/word_count/emulator/test_word_count

模擬環境:/root/drivers/ch06/word_count/emulator/test_word_count

 

Ubuntu Linux版本的路徑

隨書光盤:<光盤根目錄>/sources/ch06/word_count/ubuntu/test_word_count

模擬環境:/root/drivers/ch06/word_count/ubuntu/test_word_count

現在執行下面的命令將test_word_count文件上傳到Android模擬器。

# adb push  ./emulator/test_word_count /data/local

然后進入Android模擬器的終端,並執行下面的命令測試word_count驅動(需要先使用chmod命令設置test_word_count的可執行權限)。

# chmod 777 /data/local/test_word_count

# /data/local/test_word_count

# /data/local/test_word_count  'a bb ccc ddd eee'

執行上面的命令后,如果輸出的單詞個數是5,表示程序測試成功。

使用Android NDK和Java測試Linux驅動

本文節選至《Android深度探索(卷1):HAL與驅動開發》, 接下來幾篇文章將詳細闡述如何開發ARM架構的Linux驅動,並分別利用android程序、NDK、可執行文件測試Linux驅動。可在ubuntu Linux、Android模擬器和S3C6410開發板(可以選購OK6410-A開發板,需要刷Android)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM