版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、近年來,手機(jī)移動平臺越來越火爆。打開自己的QQ算了一下,在線好友共有31個,其中用手機(jī)上的有13個,手機(jī)用戶占了42%;打開新浪微博、天涯和貓撲等網(wǎng)站,各種終端設(shè)備的發(fā)貼、回貼更是數(shù)不勝數(shù)。目前,手機(jī)平臺如日中天的要數(shù)是iOS和Android了,尤其是iOS,Symbian已沒落,WP7在掙扎。iOS一如既往地走Apple特色的封閉道路,然而它的強(qiáng)大在于能夠建立一個完整的生態(tài)系統(tǒng),喬布斯確實是天之驕子,沒有之一;相反,Android奉行開放政策。注意,Android是開放,不是開源,從Android被踢出Linux Kernel主線代碼,可以看出為什么說Android是開放而不是開
2、源的: Mac是如何被開放的IBM PC打得一敗涂地的。Google能夠重現(xiàn)IBM當(dāng)年的輝煌嗎?不好說,吃一塹,長一智,Apple還是一個偉大的公司的。然而,個人還是看好Google,看好Android. 既然看好移動平臺,看好Android,那還等什么,趕緊研究一下吧。工欲善其事,必先利其器。相信大家都知道Android的APP的是用Java寫的,運行在Dalvik虛擬機(jī)上,還有,Android的系統(tǒng)是基于Linux Kernel 2.6的。那么,要想深入了解Android系統(tǒng)的各種細(xì)節(jié),當(dāng)然少不了Linux Kernel的知識了。本人水平有
3、限,對Linux Kernel也是略知皮毛,望與大家共勉,在此,推薦幾本幾天Linux Kernel的經(jīng)典書籍: 1. Linux Kernel Development. 2. Understanding the Linux Kernel. 3. Linux Device Drivers. 4. Linux內(nèi)核源代碼情景分析.看了Linux Kernel的書,當(dāng)然也要看一下Android的書了,這
4、樣可以對Android平臺長什么樣子有一個感性的認(rèn)識,推薦下面兩本書: 1. Professional Android Application Development. 2. Google Android SDK開發(fā)范例大全. 如果可以一邊看書,一邊照著例子實戰(zhàn)一下,那就更好不過了:)。后面,我將會總結(jié)一些自己學(xué)習(xí)過程覺得有用的知識出來,與大家分享、交流。開始我們的Android之旅吧。 在Ubuntu上下載、編譯和安裝Android最
5、新源代碼分類: Android2011-06-21 23:15 4357人閱讀 評論(41) 收藏 舉報 看完了前面說的幾本書之后,對Linux Kernel和Android有一定的認(rèn)識了,是不是心里蠢蠢欲動,想小試牛刀自己編譯一把Android源代碼了呢?一直習(xí)慣使用Windows系統(tǒng),而Android源代碼是不支持在Windows上編譯上,于是決定使用虛擬機(jī)安裝Ubuntu,然后下載、編譯和安裝Android源代碼。 一. 環(huán)境準(zhǔn)備。
6、60; 1. 磁盤空間預(yù)留20G左右,內(nèi)存3G,因為一邊要跑主機(jī),一邊要跑虛擬機(jī),內(nèi)存要求還是比較高的,這樣才會比較流暢。 2. 安裝。我的操作系統(tǒng)是Win7,VMWare的版本要新一點的,舊版本的VMWare在網(wǎng)絡(luò)支持上比較差,由于要在虛擬機(jī)上下載Android源代碼,沒有網(wǎng)絡(luò)是萬萬不行的。 3. 安裝好VMWare后,接下來就安裝Ubuntu系統(tǒng)了。我選擇目前最新的版本ubuntu-11.04-alternate-i386,從網(wǎng)上查到的資料說,要編譯Android源代碼,Ubuntu的最低
7、版本是8.04。下載好后,安裝時采用一直默認(rèn)安裝即可。 4. 安裝Git工具。Android源代碼采用Git工具來管理,與SVN相比,這是一種分布式的源代碼管理工具,而SVN是集中式的源代碼管理工具。要安裝Git工具,在Ubuntu上執(zhí)行以下命令即可: USER-NAMEMACHINE-NAME:$ sudo apt-get install git-core gnupg 5. 安裝Java SDK。在Ubuntu上執(zhí)行以下命令:
8、 USER-NAMEMACHINE-NAME:$ sudo add-apt-repository ppa:ferramroberto/java USER-NAMEMACHINE-NAME:$ sudo apt-get update USER-NAMEMACHINE-NAME:$ sudo apt-get install sun-java6-jre sun-java6-plugin
9、USER-NAMEMACHINE-NAME:$ sudo apt-get install sun-java6-jdk 6. 依賴的其它包。在Ubuntu上執(zhí)行以下命令: USER-NAMEMACHINE-NAME:$ sudo apt-get install flex bison gperf libsdl-dev libesd0-
10、dev libwxgtk2.6-dev build-essential zip curl 7. 調(diào)試工具。在Ubuntu上執(zhí)行以下命令: USER-NAMEMACHINE-NAME:$ sudo apt-get install valgrind 二. 下載Android源代碼工程。 1. 下載repo工具。在Ubuntu上執(zhí)行以下命令:
11、0; USER-NAMEMACHINE-NAME:$ wget USER-NAMEMACHINE-NAME:$ chmod 777 repo USER-NAMEMACHINE-NAME:$ cp repo /bin/ 2. 下載Android最新版本源代碼。在Ubuntu上執(zhí)行以下命令: USER-NAMEMACHINE-NAME:$ mkdir Android&
12、#160; USER-NAMEMACHINE-NAME:$ cd Android USER-NAMEMACHINE-NAME:/Android$ repo init -u git:/ USER-NAMEMACHINE-NAME:/Android$ repo sync 經(jīng)過漫長的等待(我下載了兩三天)后,就可以把Android源代碼下載下來了。其間可能還有經(jīng)歷下載中斷的情況,這時只要重新執(zhí)行repo
13、 sync就可以了。 三. 編譯Android源代碼。 1. 編譯。在Android目錄下執(zhí)行以下命令: USER-NAMEMACHINE-NAME:/Android$ make 第一次編譯要等待比較久的時間,編譯成功后,可以看到下面的輸出: Target system fs image: out/target/product/generic/obj/
14、PACKAGING/systemimage_intermediates/system.img Install system fs image: out/target/product/generic/system.img Target ram disk: out/target/product/generic/ramdisk.img Target userdata fs image: out/target/product/generic/userdata.img
15、 Installed file list: out/target/product/generic/installed-files.txt 2. 編譯過程中可能會遇到的問題。 問題一:You are attempting to build on a 32-bit system. 兩個地方需要個修改: 1)修改build/core目錄下的main.mk文件:
16、0;ifeq ($(BUILD_OS),linux) build_arch := $(shell uname -m) #Change the following line for building on a 32-bit system. #ifneq (64,$(findstring 64,$(build_arch) ifneq (i686,$(findstring i686,$(build_arch)
17、60; $(warning *) $(warning You are attempting to build on a 32-bit system.) $(warning Only 64-bit build environments are supported beyond froyo/2.2.) 2)找到下列文件: /external/clearsilver/cgi/Android.mk /externa
18、l/clearsilver/cs/Android.mk /external/clearsilver/java-jni/Android.mk /external/clearsilver/util/Android.mk 修改LOCAL_CFLAGS和LOCAL_LDFLAGS變量: # This forces a 64-bit build for Java6 # Change the followin
19、g two lines for building on a 32-bit system. # LOCAL_CFLAGS += -m64 # LOCAL_LDFLAGS += -m64 LOCAL_CFLAGS += -m32 LOCAL_LDFLAGS += -m32 問題二:Undefined reference to _dso_handle'
20、; external/stlport/src/monetary.cpp:39: undefined reference to _dso_handle'out/target/product/vm/obj/SHARED_LIBRARIES/libstlport_intermediates/src/locale.o: In function _static_initialization_and_destruction_0': external/stlport/src/locale.cpp:29: undefined ref
21、erence to _dso_handle'out/target/product/vm/obj/SHARED_LIBRARIES/libstlport_intermediates/src/locale_impl.o: In function _static_initialization_and_destruction_0': external/stlport/src/locale_impl.cpp:31: undefined reference to _dso_handle'out/target/product/vm/obj/SHA
22、RED_LIBRARIES/libstlport_intermediates/src/locale_impl.o: In function std:_Locale_impl:make_classic_locale()': external/stlport/src/locale_impl.cpp:670: undefined reference to _dso_handle' external/stlport/src/locale_impl.cpp:667: undefined reference to
23、_dso_handle'out/target/product/vm/obj/SHARED_LIBRARIES/libstlport_intermediates/src/locale_impl.o:external/stlport/src/locale_impl.cpp:604: more undefined references to _dso_handle' follow collect2: ld returned 1 exit status
24、;修改external/stlport/dll_main.cpp,加入以下聲明: extern "C" void * _dso_handle = 0; 四. 編譯SDK,這一步是可選的。 1. 編譯。執(zhí)行以下命令: USER-NAMEMACHINE-N
25、AME:/Android$ make sdk 2. 編譯過程中可能會遇到的問題。 問題一:找不到bios.bin和vgabios-cirrus.bin文件 couldn't locate source file: usr/share/pc-bios/bios.bin couldn't locate source file: usr/share/pc-bios/vgabios-ci
26、rrus.bin 注意,這里的usr/share目錄指的是/Android/out/host/linux-x86目錄下的usr/share目錄,修改辦法是復(fù)制/Android/prebuilt/common下的pc-bios文件夾到/Android/out/host/linux-x86/usr/share即可: USER-NAMEMACHINE-NAME:/Android$ cp /Android/prebuilt/common/pc-bios /Android/out/host/linux-x86
27、/usr/share 問題二:找不到ddmlib-tests.jar、 ninepath-tests.jar 、common-tests.jar 和sdkuilib-tests.jar文件 在/Android/out/host/linux-x86/framework這個目錄下,可以找到以下幾個文件common.jar、ddmlib.jar、ninepatch.jar、sdkuilib.jar這四個文件,然后將它們分別復(fù)制一份,并重命名,命名的原則很簡單,就是在原有的名字后面跟上tests即可。
28、160;五. 安裝編譯好的Android鏡像到模擬器上。 1. 設(shè)置環(huán)境變量: USER-NAMEMACHINE-NAME:/Android$ export PATH=$PATH:/Android/out/host/linux-x86/bin USER-NAMEMACHINE-NAME:/Android$ export ANDROID_PRODUCT_OUT=/Android/out/target/product/generic &
29、#160;其中,/Android/out/host/linux-x86/bin有我們要執(zhí)行的emulator命令,而/Android/out/target/product/generic是Android鏡像存放目錄,下面執(zhí)行emulator命令時會用到。 2. 運行模擬器。 USER-NAMEMACHINE-NAME:/Android$ emulator 模擬器運行需要四個文件,分別是Linux Kernel鏡像zImage和Android鏡像文件system.img、user
30、data.img和ramdisk.img。執(zhí)行emulator命令時,如果不帶任何參數(shù),則Linux Kernel鏡像默認(rèn)使用/Android/prebuilt/android-arm/kernel目錄下的kernel-qemu文件,而Android鏡像文件則默認(rèn)使用ANDROID_PRODUCT_OUT目錄下的system.img、userdata.img和ramdisk.img,也就是我們剛剛編譯出來的鏡像問題。 當(dāng)然,我們也可以以指定的鏡像文件來運行模擬器,即運行emulator時,即: USER-NAMEMACHI
31、NE-NAME:/Android$ emulator -kernel ./prebuilt/android-arm/kernel/kernel-qemu -sysdir ./out/target/product/generic -system system.img -data userdata.img -ramdisk ramdisk.img 到這里,我們就可以在模擬器上運行我們自己編譯的Android鏡像文件了,是不是很酷呢?但是注意,這里說的Android鏡像文件,只是包括system.img、userdata.img和ramdisk.img這
32、三個文件,而Linux Kernel鏡像用的是Android為我們預(yù)編譯好的kernel-qemu鏡像。那么,有沒有辦法使用我們自己編譯的Linux Kernel鏡像呢?答案上肯定的,這樣我們就可以完全DIY自己的Android系統(tǒng)了!我將在下一篇文章描述如果編譯自己的Linux Kernel鏡像,敬請期待 在Ubuntu上下載、編譯和安裝Android最新內(nèi)核源代碼(Linux Kernel)分類: Android2011-06-23 22:53 3612人閱讀 評論(58) 收藏 舉報
33、60;在前一篇文章提到,從源代碼樹下載下來的最新Android源代碼,是不包括內(nèi)核代碼的,也就是Android源代碼工程默認(rèn)不包含Linux Kernel代碼,而是使用預(yù)先編譯好的內(nèi)核,也就是prebuilt/android-arm/kernel/kernel-qemu文件。那么,如何才能DIY自己的內(nèi)核呢?這篇文章一一道來。 一. 首選,參照前一篇在Ubuntu上下載、編譯和安裝Android最新源代碼準(zhǔn)備好Android源代碼目錄。 二. 下載Linux Kernel for Android
34、源代碼。 1. 使用GIT工具下載,執(zhí)行以下命令: USER-NAMEMACHINE-NAME:/Android$ mkdir kernel USER-NAMEMACHINE-NAME:/Android$ cd kernel USER-NAMEMACHINE-NAME:/Android/kernel$ 同樣是經(jīng)過漫長
35、的等待后,在kernel目錄下有一個common目錄,Linux內(nèi)核代碼就在這里了。 2. 下載完成后,可以查看下載的內(nèi)核代碼版本: USER-NAMEMACHINE-NAME:/Android/kernel$ cd common USER-NAMEMACHINE-NAME:/Android/kernel/common$ git branch 3.
36、0;下載完Android的Linux內(nèi)核代碼后,會發(fā)現(xiàn)在arch/arm/configs下沒有模擬器要使用的硬件配置文件goldfish_defconfig,而這個配置文件是編譯內(nèi)核代碼時需要用到的,因此,需要checkout goldfish版本: USER-NAMEMACHINE-NAME:/Android/kernel/common$ git branch -a 選擇: 下載完畢后,就能在arch/arm/configs下看到gol
37、dfish_defconfig這個文件了。 三. 編譯內(nèi)核代碼。 1. 導(dǎo)出交叉編譯工具目錄到$PATH環(huán)境變量中去: USER-NAMEMACHINE-NAME:/Android/kernel/common$ 2. 修改common目錄下的Makefile文件的以下兩行為: # ARCH ?= (SUBARCH)
38、; # CROSS_COMPILE?= ARCH ?= arm #體系結(jié)構(gòu)為arm CROSS_COMPILE ?= arm-eabi- #交叉編譯工具鏈前綴,參考目錄 3. 開始編譯: USER-NAMEMACHINE-NAME:/Android/kernel/common$ ma
39、ke goldfish_defconfig USER-NAMEMACHINE-NAME:/Android/kernel/common$ make 編譯成功后,可看到下面兩行: OBJCOPY arch/arm/boot/zImage Kernel: arch/arm/boot/zImage is ready 在執(zhí)行make命令前,你也可以執(zhí)行make
40、 menuconfig先配置一下編譯選項。 四. 在模擬器中運行編譯好的內(nèi)核。 1. 在啟動模擬器之前,先設(shè)置模擬器的目錄到環(huán)境變量$PATH中去: USER-NAMEMACHINE-NAME:/Android$ export PATH=$PATH:/Android/out/host/linux-x86/bin 2. 設(shè)置ANDROID_PRODUCT_OUT環(huán)境變量:
41、160;USER-NAMEMACHINE-NAME:/Android$ export ANDROID_PRODUCT_OUT=/Android/out/target/product/generic 3. 在后臺中指定內(nèi)核文件啟動模擬器: USER-NAMEMACHINE-NAME:/Android$ emulator -kernel ./kernel/common/arch/arm/boot/zImage &
42、0;4. 用adb工具連接模擬器,查看內(nèi)核版本信息,看看模擬器上跑的內(nèi)核是不是我們剛才編譯出來的內(nèi)核: USER-NAMEMACHINE-NAME:/Android$ adb shell 這時候如果是第一次運行 adb shell命令,會看到以下輸出,不用管它,再運行一次adb shell命令就可以了。 * daemon not running. start it now on port 5037 *
43、60;* daemon started successfully * error: device offline 切換到proc目錄: rootandroid:/ # cd proc rootandroid:/proc # cat version Linux version 2.6.29-gb0d93fb-dirty (luoubuntu-11-0
44、4) (gcc version 4.4.3 (GCC) ) #1 Fri Jun 3 23:17:24 HKT 2011 從機(jī)器名luoubuntu-11-04和日期1 Fri Jun 3 23:17:24 HKT 2011可以看出,模擬器使用的內(nèi)核即為剛剛編譯出來的內(nèi)核。 如何單獨編譯Android源代碼中的模塊分類: Android2011-06-24 22:07 2223人閱讀 評論(6) 收藏 舉報 第一次下載好Android源代碼工程后,我
45、們通常是在Android源代碼工程目錄下執(zhí)行make命令,經(jīng)過漫長的等待之后,就可以得到Android系統(tǒng)鏡像system.img了。以后如果我們修改了Android源代碼中的某個模塊或者在Android源代碼工程新增一個自己的模塊,是不是還是執(zhí)行make命令呢?答案是否定的,Google為我們準(zhǔn)備了另外的命令來支持編譯單獨的模塊,以及重新打包system.img的命令。在繼續(xù)學(xué)習(xí)Android源代碼之前,就讓我們先來看看這個命令吧。 一. 首先在Android源代碼目錄下的build目錄下,有個腳本文件envsetup.sh,執(zhí)行這個腳本文件
46、后,就可以獲得一些有用的工具: USER-NAMEMACHINE-NAME:/Android$ . ./build/envsetup.sh 注意,這是一個source命令,執(zhí)行之后,就會有一些額外的命令可以使用: - croot: Changes directory to the top of the tree. - m: Makes from the top of the
47、tree. - mm: Builds all of the modules in the current directory. - mmm: Builds all of the modules in the supplied directories. - cgrep: Greps on all local C/C+ files. - jgrep: Greps on all local Java f
48、iles. - resgrep: Greps on all local res/*.xml files. - godir: Go to the directory containing a file. 這些命令的具體用法,可以在命令的后面加-help來查看,這里我們只關(guān)注mmm命令,也就是可以用它來編譯指定目錄的所有模塊,通常這個目錄只包含一個模塊。 二. 使用mmm命令來編譯指定的模塊,例如Em
49、ail應(yīng)用程序: USER-NAMEMACHINE-NAME:/Android$ mmm packages/apps/Email/ 編譯完成之后,就可以在out/target/product/generic/system/app目錄下看到Email.apk文件了。Android系統(tǒng)自帶的App都放在這具目錄下。另外,Android系統(tǒng)的一些可執(zhí)行文件,例如C編譯的可執(zhí)行文件,放在out/target/product/generic/system/bin目錄下,動態(tài)鏈接庫文件放在out/
50、target/product/generic/system/lib目錄下,out/target/product/generic/system/lib/hw目錄存放的是硬件抽象層(HAL)接口文件,后面的文章里面,我們會陸續(xù)提及到,敬請關(guān)注。 三. 編譯好模塊后,還要重新打包一下system.img文件,這樣我們把system.img運行在模擬器上時,就可以看到我們的程序了。 USER-NAMEMACHINE-NAME:/Android$ make snod
51、160; 四. 參照Ubuntu上下載、編譯和安裝Android最新源代碼一文介紹的方法運行模擬器: USER-NAMEMACHINE-NAME:/Android$ emulator 這樣一切就搞定了。Android硬件抽象層(HAL)概要介紹和學(xué)習(xí)計劃分類: Android2011-06-25 13:03 3276人閱讀 評論(10) 收藏 舉報 Android的硬件抽象層
52、,簡單來說,就是對Linux內(nèi)核驅(qū)動程序的封裝,向上提供接口,屏蔽低層的實現(xiàn)細(xì)節(jié)。也就是說,把對硬件的支持分成了兩層,一層放在用戶空間(User Space),一層放在內(nèi)核空間(Kernel Space),其中,硬件抽象層運行在用戶空間,而Linux內(nèi)核驅(qū)動程序運行在內(nèi)核空間。為什么要這樣安排呢?把硬件抽象層和內(nèi)核驅(qū)動整合在一起放在內(nèi)核空間不可行嗎?從技術(shù)實現(xiàn)的角度來看,是可以的,然而從商業(yè)的角度來看,把對硬件的支持邏輯都放在內(nèi)核空間,可能會損害廠家的利益。我們知道,Linux內(nèi)核源代碼版權(quán)遵循GNU License,而Android源代碼版權(quán)遵循Apache License,前者在發(fā)布產(chǎn)品時
53、,必須公布源代碼,而后者無須發(fā)布源代碼。如果把對硬件支持的所有代碼都放在Linux驅(qū)動層,那就意味著發(fā)布時要公開驅(qū)動程序的源代碼,而公開源代碼就意味著把硬件的相關(guān)參數(shù)和實現(xiàn)都公開了,在手機(jī)市場競爭激烈的今天,這對廠家來說,損害是非常大的。因此,Android才會想到把對硬件的支持分成硬件抽象層和內(nèi)核驅(qū)動層,內(nèi)核驅(qū)動層只提供簡單的訪問硬件邏輯,例如讀寫硬件寄存器的通道,至于從硬件中讀到了什么值或者寫了什么值到硬件中的邏輯,都放在硬件抽象層中去了,這樣就可以把商業(yè)秘密隱藏起來了。也正是由于這個分層的原因,Android被踢出了Linux內(nèi)核主線代碼樹中。大家想想,Android放在內(nèi)核空間的驅(qū)動程
54、序?qū)τ布闹С质遣煌暾?,把Linux內(nèi)核移植到別的機(jī)器上去時,由于缺乏硬件抽象層的支持,硬件就完全不能用了,這也是為什么說Android是開放系統(tǒng)而不是開源系統(tǒng)的原因。 撇開這些爭論,學(xué)習(xí)Android硬件抽象層,對理解整個Android整個系統(tǒng),都是極其有用的,因為它從下到上涉及到了Android系統(tǒng)的硬件驅(qū)動層、硬件抽象層、運行時庫和應(yīng)用程序框架層等等,下面這個圖闡述了硬件抽象層在Android系統(tǒng)中的位置,以及它和其它層的關(guān)系: 在學(xué)習(xí)Android硬件抽象層的過程中,我們將會學(xué)習(xí)如何在內(nèi)核空間編寫硬件驅(qū)動程序
55、、如何在硬件抽象層中添加接口支持訪問硬件、如何在系統(tǒng)啟動時提供硬件訪問服務(wù)以及 如何編寫JNI使得可以通過Java接口來訪問硬件,而作為中間的一個小插曲,我們還將學(xué)習(xí)一下如何在Android系統(tǒng)中添加一個C可執(zhí)行程序來訪問硬件驅(qū)動程序。由于這是一個系統(tǒng)的學(xué)習(xí)過程,筆者將分成六篇文章來描述每一個學(xué)習(xí)過程,包括: 一. 在Android內(nèi)核源代碼工程中編寫硬件驅(qū)動程序。 二. 在Android系統(tǒng)中增加C可執(zhí)行程序來訪問硬件驅(qū)動程序。 三. 在Androi
56、d硬件抽象層增加接口模塊訪問硬件驅(qū)動程序。 四. 在Android系統(tǒng)中編寫JNI方法在應(yīng)用程序框架層提供Java接口訪問硬件。 五. 在Android系統(tǒng)的應(yīng)用程序框架層增加硬件服務(wù)接口。 六. 在Android系統(tǒng)中編寫APP通過應(yīng)用程序框架層訪問硬件服務(wù)。 學(xué)習(xí)完這六篇文章,相信大家對Android系統(tǒng)就會有一個更深刻的認(rèn)識了,敬請關(guān)注。 在Ubuntu上為Android系統(tǒng)編寫Linux內(nèi)核驅(qū)動程
57、序分類: Android2011-06-26 12:10 3450人閱讀 評論(33) 收藏 舉報 在智能手機(jī)時代,每個品牌的手機(jī)都有自己的個性特點。正是依靠這種與眾不同的個性來吸引用戶,營造品牌凝聚力和用戶忠城度,典型的代表非iphone莫屬了。據(jù)統(tǒng)計,截止2011年5月,AppStore的應(yīng)用軟件數(shù)量達(dá)381062個,位居第一,而Android Market的應(yīng)用軟件數(shù)量達(dá)294738,緊隨AppStore后面,并有望在8月份越過AppStore。隨著Android系統(tǒng)逐步擴(kuò)大
58、市場占有率,終端設(shè)備的多樣性亟需更多的移動開發(fā)人員的參與。據(jù)業(yè)內(nèi)統(tǒng)計,Android研發(fā)人才缺口至少30萬。目前,對Android人才需求一類是偏向硬件驅(qū)動的Android人才需求,一類是偏向軟件應(yīng)用的Android人才需求??偟膩碚f,對有志于從事Android硬件驅(qū)動的開發(fā)工程師來說,現(xiàn)在是一個大展拳腳的機(jī)會。那么,就讓我們一起來看看如何為Android系統(tǒng)編寫內(nèi)核驅(qū)動程序吧。 這里,我們不會為真實的硬件設(shè)備編寫內(nèi)核驅(qū)動程序。為了方便描述為Android系統(tǒng)編寫內(nèi)核驅(qū)動程序的過程,我們使用一個虛擬的硬件設(shè)備,這個設(shè)備只有一個4字
59、節(jié)的寄存器,它可讀可寫。想起我們第一次學(xué)習(xí)程序語言時,都喜歡用“Hello, World”作為例子,這里,我們就把這個虛擬的設(shè)備命名為“hello”,而這個內(nèi)核驅(qū)動程序也命名為hello驅(qū)動程序。其實,Android內(nèi)核驅(qū)動程序和一般Linux內(nèi)核驅(qū)動程序的編寫方法是一樣的,都是以Linux模塊的形式實現(xiàn)的,具體可參考前面Android學(xué)習(xí)啟動篇一文中提到的Linux Device Drivers一書。不過,這里我們還是從Android系統(tǒng)的角度來描述Android內(nèi)核驅(qū)動程序的編寫和編譯過程。 一. 參照前面兩篇文章在Ubuntu上下載、編
60、譯和安裝Android最新源代碼和在Ubuntu上下載、編譯和安裝Android最新內(nèi)核源代碼(Linux Kernel)準(zhǔn)備好Android內(nèi)核驅(qū)動程序開發(fā)環(huán)境。 二. 進(jìn)入到kernel/common/drivers目錄,新建hello目錄: USER-NAMEMACHINE-NAME:/Android$ cd kernel/common/drivers USER-NAMEMACHINE-NAME:/Android/kerne
61、l/common/drivers$ mkdir hello 三. 在hello目錄中增加hello.h文件:view plain1. #ifndef _HELLO_ANDROID_H_ 2. #define _HELLO_ANDROID_H_ 3. 4. #include <linux/cdev.h> 5. #include <linux/semaphore.h> 6.
62、 7. #define HELLO_DEVICE_NODE_NAME "hello" 8. #define HELLO_DEVICE_FILE_NAME "hello" 9. #define HELLO_DEVICE_PROC_NAME "hello" 10. #define HELLO_DEVICE_CLASS_NAME &quo
63、t;hello" 11. 12. struct hello_android_dev 13. int val; 14. struct semaphore sem; 15. struct cdev dev; 16. ; 1
64、7. 18. #endif 這個頭文件定義了一些字符串常量宏,在后面我們要用到。此外,還定義了一個字符設(shè)備結(jié)構(gòu)體hello_android_dev,這個就是我們虛擬的硬件設(shè)備了,val成員變量就代表設(shè)備里面的寄存器,它的類型為int,sem成員變量是一個信號量,是用同步訪問寄存器val的,dev成員變量是一個內(nèi)嵌的字符設(shè)備,這個Linux驅(qū)動程序自定義字符設(shè)備結(jié)構(gòu)體的標(biāo)準(zhǔn)方法。四.在hello目錄中增加hello.c文件,這是驅(qū)動程序的實現(xiàn)部分。驅(qū)動程序的功能主要是向上層提供訪問設(shè)備的寄存器的值,包括讀和寫。這里,提供了三種訪問設(shè)備寄存器的方法,一
65、是通過proc文件系統(tǒng)來訪問,二是通過傳統(tǒng)的設(shè)備文件的方法來訪問,三是通過devfs文件系統(tǒng)來訪問。下面分段描述該驅(qū)動程序的實現(xiàn)。首先是包含必要的頭文件和定義三種訪問設(shè)備的方法:view plain1. #include <linux/init.h> 2. #include <linux/module.h> 3. #include <linux/types.h> 4. #include <linux/fs.h> 5. #
66、include <linux/proc_fs.h> 6. #include <linux/device.h> 7. #include <asm/uaccess.h> 8. 9. #include "hello.h" 10. 11. /*主設(shè)備和從設(shè)備號變量*/ 12. static int hello_major
67、= 0; 13. static int hello_minor = 0; 14. 15. /*設(shè)備類別和設(shè)備變量*/ 16. static struct class* hello_class = NULL; 17. static struct hello_android_dev* hello_dev = NULL;
68、;18. 19. /*傳統(tǒng)的設(shè)備文件操作方法*/ 20. static int hello_open(struct inode* inode, struct file* filp); 21. static int hello_release(struct inode* inode, struct file* filp); 22. static ssize_t
69、 hello_read(struct file* filp, char _user *buf, size_t count, loff_t* f_pos); 23. static ssize_t hello_write(struct file* filp, const char _user *buf, size_t count, loff_t* f_pos)
70、; 24. 25. /*設(shè)備文件操作方法表*/ 26. static struct file_operations hello_fops = 27. .owner = THIS_MODULE, 28. .open = hello_open, 29.
71、160; .release = hello_release, 30. .read = hello_read, 31. .write = hello_write, 32. ; 33. 34. /*訪問設(shè)置屬性方法*/ 35. static ssize_t hello_v
72、al_show(struct device* dev, struct device_attribute* attr, char* buf); 36. static ssize_t hello_val_store(struct device* dev, struct device_attribute* attr, const char* buf, size_t count);
73、 37. 38. /*定義設(shè)備屬性*/ 39. static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, hello_val_show, hello_val_store); 定義傳統(tǒng)的設(shè)備文件訪問方法,主要是定義hello_open、hello_release、hello_read和hello_write這四個打開、釋放、讀和寫設(shè)備文件的方法:view
74、plain1. /*打開設(shè)備方法*/ 2. static int hello_open(struct inode* inode, struct file* filp) 3. struct hello_android_dev* dev; 4.
75、; 5. /*將自定義設(shè)備結(jié)構(gòu)體保存在文件指針的私有數(shù)據(jù)域中,以便訪問設(shè)備時拿來用*/ 6. dev = container_of(inode->i_cdev, struct hello_android_dev, dev); 7. filp->private_data = dev; 8
76、. 9. return 0; 10. 11. 12. /*設(shè)備文件釋放時調(diào)用,空實現(xiàn)*/ 13. static int hello_release(struct inode* inode, struct file* filp) 14. &
77、#160;return 0; 15. 16. 17. /*讀取設(shè)備的寄存器val的值*/ 18. static ssize_t hello_read(struct file* filp, char _user *buf, size_t count, loff_t* f_pos) 19. ssize_t
78、160;err = 0; 20. struct hello_android_dev* dev = filp->private_data; 21. 22. /*同步訪問*/ 23. if(down_inte
79、rruptible(&(dev->sem) 24. return -ERESTARTSYS; 25. 26. 27. if(count < sizeof(dev->val) 28.
80、0; goto out; 29. 30. 31. /*將寄存器val的值拷貝到用戶提供的緩沖區(qū)*/ 32. if(copy_to_user(buf, &(dev->val),&
81、#160;sizeof(dev->val) 33. err = -EFAULT; 34. goto out; 35. 36. 37. err
82、;= sizeof(dev->val); 38. 39. out: 40. up(&(dev->sem); 41. return err; 42. 43. 44. /*寫設(shè)備的寄存器值val*/ 45. static ssize_t hello_write(st
83、ruct file* filp, const char _user *buf, size_t count, loff_t* f_pos) 46. struct hello_android_dev* dev = filp->private_data; 47. ssize_t err = 0;
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- GB/T 3215-2025石油、石化和天然氣工業(yè)用離心泵
- GB/T 32219-2026筒式磨機(jī)鑄造磨段
- 創(chuàng)業(yè)培訓(xùn)教師授課信息反饋表
- 平臺穩(wěn)性操作員保密競賽考核試卷含答案
- 制材工安全文明測試考核試卷含答案
- 軋鋼精整工安全宣貫強(qiáng)化考核試卷含答案
- 橋梁支座試驗培訓(xùn)
- 銀行內(nèi)部審計報告制度
- 酒店員工獎懲與激勵機(jī)制制度
- 超市員工績效考核制度
- 北京市順義區(qū)2025-2026學(xué)年八年級上學(xué)期期末考試英語試題(原卷版+解析版)
- 中學(xué)生冬季防溺水主題安全教育宣傳活動
- 2026年藥廠安全生產(chǎn)知識培訓(xùn)試題(達(dá)標(biāo)題)
- 初中九年級上一元二次方程計算練習(xí)題及答案詳解B2
- 中國涉外律師人才研究報告2025
- 冷庫防護(hù)制度規(guī)范
- 2026年生產(chǎn)管理崗入職性格測試題及答案
- 2026年bjt商務(wù)能力考試試題
- 廣東省廣州市番禺區(qū)2026屆高一數(shù)學(xué)第一學(xué)期期末聯(lián)考試題含解析
- 2026年廣東省佛山市高三語文聯(lián)合診斷性考試作文題及3篇范文:可以“重讀”甚至“重構(gòu)”這些過往
- 老年住院患者非計劃性拔管分析2026
評論
0/150
提交評論