1. 程式人生 > >Android系統移植:驅動篇

Android系統移植:驅動篇

音視頻 理念 rom 利用 定時 垃圾回收 ipc track 進程間

【導語】在Android系統移植中,有很重要的一個部分工作,就是為新平臺上的硬件設備移植驅動程序。因為Android系統是基於Linux kernel內核構建,所以這裏說的移植驅動程序,其實就是基於Android系統平臺開發適應移動設備的Linux內核驅動程序。

一. Android系統中Linux內核與設備驅動

Android系統中使用了Linux內核作為自己的操作系統,除了linux的通用代碼之外,主要還包含三個方面的東西:

  • 體系結構和處理器
    體系結構處理器和標準的設備驅動程序這兩個方面是和硬件相關的,但是對於同一種硬件,在Android系統和標準的Linux系統中基本上是一樣的。

  • Android專用的驅動程序
    Android的專用驅動程序,通常是和硬件無關的驅動程序,僅僅在Android系統中使用。

  • 標準的linux設備驅動程序

Android系統中Linux內核與設備驅動的結構如下圖示:

技術分享圖片

Android系統通常用於移動設備和其他的嵌入式設備,因此都基於ARM體系結構,在ARM體系結構具有多種處理器。因此,對於不同對的處理器,基於相同的外圍設備,驅動程序也可能不一樣。

需要說明的是上圖中的Goldfish:

Android模擬器通過運行一個Goldfish的虛擬CPU ,Goldfish用來運行arm926t指令集(arm926t屬於armv5構架),並且仿真了輸入/輸出,比如鍵盤輸入和LCD 輸出。這個模擬器其實是在qemu之上開發的,輸入/輸出是基於libSDL的。既然Goldfish是被模擬器運行的虛擬CPU,那麽當Android在真實的硬件設備上運行時,我們就需要去掉它。

二. Android系統上的設備驅動

  • 基本圖形用戶界面(GUI)部分:包括顯示部分、用戶輸入部分和硬件相關的加速部分,還包括媒體編解碼和OpenGL等。
  • 音視頻輸入輸出部分:包括音頻、視頻輸出和攝像頭等。
  • 連接部分:包括無線局域網、藍牙、GPS等。
  • 電話部分:包括通話、GSM等。
  • 附屬部件:包括傳感器、背光、振動器等。

具體來說是有以下:

  • [x] Display顯示部分:包括FrameBuffer驅動和Gralloc模塊。
  • [x] Input用戶輸入部分:包括Event驅動和EventHub。
  • [x] Codec多媒體編解碼:包括硬件Codec驅動和Codec插件,例如OpenMax。
  • [x] 3DAccelerator(3D加速器)部分:包括硬件OpenGL驅動和OpenGL插件。
  • [x] Audio音頻部分:包括Audio驅動和Audio硬件抽象層。
  • [x] VideoOut視頻輸出部分:包括視頻顯示驅動和Overlay硬件抽象層。
  • [x] Camera攝像頭部分:包括Camera驅動(通常是v4l2)和Camera硬件抽象層。
  • [x] Phone電話部分:包括Modem驅動程序和RIL庫。
  • [x] GPS全球定位系統部分:包括GPS驅動(例如串口)和GPS硬件抽象層。
  • [x] Wi-Fi無線局域網部分:包括Wlan驅動和協議和Wi-Fi的適配層。
  • [x] BlueTooth藍牙部分:包括BT驅動和協議及BT的適配層。
  • [x] Sensor傳感器部分:包括Sensor驅動和Sensor硬件抽象層。
  • [x] Vibrator振動器部分:包括Vibrator驅動和Vibrator硬件抽象層。
  • [x] Light背光部分:包括Light驅動和Light硬件抽象層。
  • [x] Alarm警告器部分:包括Alarm驅動和RTC系統和用戶空間調用。
  • [x] Battery電池部分:包括電池部分驅動和電池的硬件抽象層。

在實際應用中,通過下面的圖,感受下一個量產的平板中用到了哪些硬件,體會下其中涉及到的驅動:

技術分享圖片

三.Android系統專用驅動

看一下Google為基於Linux kernel而定制的Android系統專用驅動程序:

(1)Android Binder

Android Binder是基於OpenBinder框架的一個驅動,用於Android平臺的進程間通信(InterProcess
Communication,IPC)。原來的Linux系統上層應用的進程間通信主要是D-bus(Desktop bus),采用消息總線的方式來進行IPC。
源代碼位於drivers/staging/android/binder.c。

(2)Android電源管理

Android電源管理是基於標準Linux電源管理系統的輕量級Android電源管理驅動,針對嵌入式設備做
了很多優化。利用鎖和定時器來切換系統狀態,控制設備在不同狀態下的功耗,已達到節能的目的。
源代碼位於:
- [ ] kernel/power/earlysuspend.c
- [ ] kernel/power/consoleearlysuspend.c
- [ ] kernel/power/fbearlysuspend.c
- [ ] kernel/power/wakelock.c
- [ ] kernel/power/userwakelock.c

Android5.0版本引用JobSchedule調度程序,以便增加設備續航時間。

(3)低內存管理器(Low Memory Killer)

比Linux的標準的OOM(Out Of Memory)機制更加靈活,它可以根據需要
殺死進程以釋放需要的內存。源代碼位於 drivers/staging/ android/lowmemorykiller.c。

(4)匿名共享內存(Ashmem)

為進程間提供大塊共享內存,同時為內核提供回收和管理這個內存的機制。源代碼位於
mm/ashmem.c。

(5)Android PMEM(Physical)

PMEM用於向用戶空間提供連續的物理內存區域,DSP和某些設備只能工作在連續的物
理內存上。
源代碼位於drivers/misc/pmem.c。

(6)Android Logger

一個輕量級的日誌設備,用於抓取Android系統的各種日誌,是Linux所沒有的。
源代碼位於drivers/staging/android/logger.c。

(7)Android Alarm

提供了一個定時器,用於把設備從睡眠狀態喚醒,同時它還提供了一個即使在設備睡眠時也會
運行的時鐘基準。源代碼位於drivers/rtc/alarm.c。

(8)USB Gadget驅動

一個基於標準 Linux USB gadget驅動框架的設備驅動,Android的USB驅動是基於gaeget框架的。
源代碼位於
- [ ] drivers/usb/gadget/android.c
- [ ] drivers/usb/gadget/f_adb.c
- [ ] drivers/usb/gadget/f_mass_storage.c

(9)Android Ram Console

為了提供調試功能,Android允許將調試日誌信息寫入一個被稱為RAM Console的設備
裏,它是一個基於RAM的Buffer。源代碼位於drivers/staging/android / ram_console.c。

(10)Android timed device

提供了對設備進行定時控制的功能,目前支持vibrator和LED設備。源代碼位於
drivers/staging/android /timed_output.c(timed_gpio.c)。

(11)Yaffs2 文件系統

Android采用Yaffs2作為MTD nand flash文件系統,源代碼位於fs/yaffs2/目錄下。
Yaffs2是一個快速穩定的應用於NAND和NOR Flash的跨平臺的嵌入式設備文件系統,同其他Flash文件系統相比,
Yaffs2能使用更小的內存來保存其運行狀態,因此它占用內存小。Yaffs2的垃圾回收非常簡單而且快速,因此能表
現出更好的性能。Yaffs2在大容量的NAND Flash上的性能表現尤為突出,非常適合大容量的Flash存儲。

四.Android驅動開發主要工作

Linux系統將設備驅動分為以下三類:

  • (1)字符設備

    指只能一個字節一個字節讀寫的設備,不能隨機讀取設備內存中的某一數據,讀取數據需要按照先後數據。字符設備是面向流的設備,常見的字符設備有鼠標、鍵盤、串口、控制臺和LED設備等。

  • (2)塊設備

    指可以從設備的任意位置讀取一定長度數據的設備。塊設備包括硬盤、磁盤、U盤和SD卡等。

  • (3)網絡設備

    為支持通過文件接口處理網絡連接,Linux使用了源於BSD的套接字抽象,套接字keil看作應用程序、文件接口、內核的網絡之間的代理。

驅動程序是介於系統和硬件之間的橋梁,實現硬件和系統之間的交互是我們底層開發的主要任務。在Android系統中,我們一般需要編寫內核級和用戶級的程序來完成具體的任務。

4.1 實現系統和硬件之間交互的幾種方式

  • (1).編寫自己的系統調用
    系統調用是用戶級程序訪問內核最基本的方法,Linux提供了很多標準的系統調用(參見內核代碼樹中的include/asm-i386/unistd.h和arch/i386/kernel/entry.S文件),並且允許我們添加自己的系統調用來實現和內核的信息交換;

  • (2).編寫驅動程序
    Linux有一個重要的理念就是“一切皆文件”(everything is a file)。

    用戶空間的應用程序通過系統提供的統一交互接口 open() —— read() —— write() —— ioctl() —— close()方法,訪問文件系統中/dev/目錄下的一個文件來訪問運行於內核空間的驅動程序,並通過驅動程序中實現的功能達到對硬件的訪問。

  • (3). 使用proc 文件系統

    proc是Linux提供的一種特殊的文件系統,推出它的目的就是提供一種便捷的用戶和內核間的交互方式。proc 文件系統相對是比較簡單的,不過proc文件的讀寫並不統一,讀數據的buf指針直接指向的就是用戶態的地址,可以用sprintf進行寫入;而寫方法卻是內核態的地址,需要用get_user或者 copy_from_user之類的方法。

  • (4).使用虛擬文件系統

    有些內核開發者認為利用ioctl()系統調用往往會似的系統調用意義不明確,而且難控制。而將信息放入到proc文件系統中會使信息組織混亂,因此也不贊成過多使用。他們建議實現一種孤立的虛擬文件系統來代替ioctl()和/proc,因為文件系統接口清楚,而且便於用戶空間訪問,同時利用虛擬文件系統使得利用腳本執行系統管理任務更家方便、有效。

  • (5).使用內存映像

    Linux通過內存映像機制來提供用戶程序對內存直接訪問的能力。內存映像的意思是把內核中特定部分的內存空間映射到用戶級程序的內存空間去。也就是說,用戶空間和內核空間共享一塊相同的內存。

4.2 內核空間和用戶空間的交互

上面講了系統與硬件交互的幾種方式提到了,在具體的交互中,驅動程序驅動具體的硬件模塊工作時涉及到一個內核空間和用戶空間交互的概念。

現代的計算機體系結構中存儲管理通常都包含保護機制。提供保護的目的,是要避免系統中的一個任務訪問屬於另外的或屬於操作系統的存儲區域。如在IntelX86體系中,就提供了特權級這種保護機制,通過特權級別的區別來限制對存儲區域的訪問。

基於這種構架,Linux操作系統對自身進行了劃分:一部分核心軟件獨立於普通應用程序,運行在較高的特權級別上,(Linux使用Intel體系的特權級3來運行內核。)它們駐留在被保護的內存空間上,擁有訪問硬件設備的所有權限,Linux將此稱為內核空間

相對的,其它部分被作為應用程序在用戶空間 執行。它們只能看到允許它們使用的部分系統資源,並且不能使用某些特定的系統功能,不能直接訪問硬件,不能直接訪問內核空間,當然還有其他一些具體的使用限制。(Linux使用Intel體系的特權級0來運行用戶程序。)

通過下面的圖,看一下內核空間與用戶空間的交互關系:

技術分享圖片

版權聲明:本文為博主【limin13215】原創文章,歡迎轉載,轉載請註明鏈接地址! https://blog.csdn.net/limin13215/article/details/72676518

Android系統移植:驅動篇