在前一篇文章中,我們介紹了如何在Ubuntu上為Android系統編寫Linux核心驅動程式。在這個名為hello的Linux核心驅動程式中,建立三個不同的檔案節點來供使用者空間訪問,分別是傳統的裝置檔案/dev/hello、proc系統檔案/proc/hello和devfs系統屬性檔案/sys/class/hello/hello/val。進一步,還通過cat命令來直接存取/proc/hello和/sys/class/hello/hello/val檔案來,以驗證驅動程式的正確性。在這一篇文章裡,我們將通過自己編寫的C可執行程式來訪問裝置檔案/dev/hello。可能讀者會覺得奇怪,怎麼能在Android系統中用C語言來編寫應用程式呢?Android系統上的應用程式不都是Java應用程式嗎?其實是可以的,讀者不妨用adb shell命令連上Android模擬器,在/system/bin目錄下可以看到很多C可執行程式,如cat命令。今天,我們就來學習一下怎麼在Android系統中添加用C語言編寫的可執行程式吧。
一. 參照在Ubuntu上為Android系統編寫Linux核心驅動程式一文,準備好Linux驅動程式。使用Android模擬器載入包含這個Linux驅動程式的核心檔案,並且使用adb shell命令串連上類比,驗證在/dev目錄中存在裝置檔案hello。
二. 進入到Android原始碼工程的external目錄,建立hello目錄:
USER-NAME@MACHINE-NAME:~/Android$ cd external
USER-NAME@MACHINE-NAME:~/Android/external$ mkdir hello
三. 在hello目錄中建立hello.c檔案:
#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#define DEVICE_NAME "/dev/hello"int main(int argc, char** argv){int fd = -1;int val = 0;fd = open(DEVICE_NAME, O_RDWR);if(fd == -1) {printf("Failed to open device %s.\n", DEVICE_NAME);return -1;}printf("Read original value:\n");read(fd, &val, sizeof(val));printf("%d.\n\n", val);val = 5;printf("Write value %d to %s.\n\n", val, DEVICE_NAME); write(fd, &val, sizeof(val));printf("Read the value again:\n"); read(fd, &val, sizeof(val)); printf("%d.\n\n", val);close(fd);return 0;}
這個程式的作用中,開啟/dev/hello檔案,然後先讀出/dev/hello檔案中的值,接著寫入值5到/dev/hello中去,最後再次讀出/dev/hello檔案中的值,看看是否是我們剛才寫入的值5。從/dev/hello檔案讀寫的值實際上就是我們虛擬硬體的寄存器val的值。
四. 在hello目錄中建立Android.mk檔案:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := hello
LOCAL_SRC_FILES := $(call all-subdir-c-files)
include $(BUILD_EXECUTABLE)
注意,BUILD_EXECUTABLE表示我們要編譯的是可執行程式。
五. 參照如何單獨編譯Android原始碼中的模組一文,使用mmm命令進行編譯:
USER-NAME@MACHINE-NAME:~/Android$ mmm ./external/hello
編譯成功後,就可以在out/target/product/gerneric/system/bin目錄下,看到可執行檔hello了。
六. 重新打包Android系統檔案system.img:
USER-NAME@MACHINE-NAME:~/Android$ make snod
這樣,重新打包後的system.img檔案就包含剛才編譯好的hello可執行檔了。
七. 運行模擬器,使用/system/bin/hello可執行程式來訪問Linux核心驅動程式:
USER-NAME@MACHINE-NAME:~/Android$ emulator -kernel ./kernel/common/arch/arm/boot/zImage &
USER-NAME@MACHINE-NAME:~/Android$ adb shell
root@android:/ # cd system/bin
root@android:/system/bin # ./hello
Read the original value:
0.
Write value 5 to /dev/hello.
Read the value again:
5.
看到這個結果,就說我們編寫的C可執行程式可以訪問我們編寫的Linux核心驅動程式了。
介紹完了如何使用C語言編寫的可執行程式來訪問我們的Linux核心驅動程式,讀者可能會問,能不能在Android的Application Frameworks提供Java介面來訪問Linux核心驅動程式呢?可以的,接下來的幾篇文章中,我們將介紹如何在Android的Application Frameworks中,增加Java介面來訪問Linux核心驅動程式,敬請期待。
老羅的新浪微博:http://weibo.com/shengyangluo,歡迎關注!