Android系統架構

(一)Linux Kernel(/kernel,/bootable,/devices)
Android核心 對Linux核心進行了增強,增加了一些面向移動計算的特有功能。例如:
- 低記憶體管理器LMK(Low Memory Keller)。源代碼位于 drivers/staging/ android/lowmemorykiller.c
- 匿名共享記憶體(Ashmem),mm/ashmem.c。
- 輕量級的程序間通信Binder機制,源代碼位于drivers/staging/android/binder.c。等。
這些核心的增強使Android在繼承Linux核心安全機制的同時,進一步提升了記憶體管理,程序間通信等方面的安全性。
Android Linux Kernel 特征:
1.它沒有glibc支援
由于Android最初用于一些便攜的移動裝置上,是以,可能出于效率等方面的考慮,Android并沒有采用glibc作為
C庫,而是Google自己開發了一套Bionic Libc來代替glibc。
2.它并不包括一整套标準的Linux使用程式
Android并沒有完全照搬Liunx系統的核心,除了修正部分Liunx的Bug之外,還增加了不少内容,比如:它基于ARM
構架增加的Gold-Fish平台,以及yaffs2 FLASH檔案系統(如果學習了嵌入式的話就會知道yaffs2 FLASH檔案系
統已經在基于linux的很多嵌入式裝置上采用了,技術已經非常成熟)等。
3.它沒有本地基于X服務的視窗系統
什麼是本地視窗系統呢?本地視窗系統是指GNU/Linux上的X視窗系統,或者Mac OX X的Quartz等。不同的作業系統
的視窗系統可能不一樣,Android并沒有使用(也不需要使用)Linux的X視窗系統(對原作者的這個觀點不是很贊
同,原文章這一點放在第一條,并說“這是Android不是Linux的一個基本原因”,這個不敢苟同,由于作者 沒有
指明android用的什麼顯示系統,我也不好說)。
4.Android專有的驅動程式
除了上面這些不同點之外,Android還對Linux裝置驅動進行了增強,主要如下所示。
1)Android Binder 基于OpenBinder架構的一個驅動,用于提供 Android平台的程序間通信(InterProcess
Communication,IPC)功能。源代碼位于drivers/staging/android/binder.c。
2)Android電源管理(PM) 一個基于标準Linux電源管理系統的輕量級Android電源管理驅動,針對嵌入式裝置做
了很多優化。源代碼位于:
kernel/power/earlysuspend.c
kernel/power/consoleearlysuspend.c
kernel/power/fbearlysuspend.c
kernel/power/wakelock.c
kernel/power/userwakelock.c
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系統的各種日志。源代碼位于
drivers/staging/android/logger.c。
7)Android Alarm 提供了一個定時器,用于把裝置從睡眠狀态喚醒,同時它還提供了一個即使在裝置睡眠時也會
運作的時鐘基準。源代碼位于drivers/rtc/alarm.c。
8)USB Gadget驅動 一個基于标準 Linux USB gadget驅動架構的裝置驅動,Android的USB驅動是基于gaeget框
架的。源代碼位于drivers/usb/gadget/。
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存儲。
(二)硬體抽象層HAL(/hardware)
- 對下:對linux核心驅動程式封裝,這樣,對硬體的操作分成兩層,抽象層位于使用者空間,驅動程式位于核心。為了避免硬體資訊的公開,隻開源驅動層的代碼即可。
- 對上:對上層應用提供一個統一的簡單的查詢硬體裝置的接口。它所謂的抽象,基本上也就僅限于這一功能,它通常并不提供對硬體的實際操作,對硬體的操作,還是由應用程式來完成。
Linux核心源代碼版權遵循GNU License,而android源代碼版權遵循Apache License,前者在釋出産品時,必須公布源代碼,而後者無須釋出源代碼。如果把對硬體支援的所有代碼都放在Linux驅動層,那就意味着釋出時要公開驅動程式的源代碼,而公開源代碼就意味着把硬體的相關參數和實作都公開了,核心驅動層隻提供簡單的通路硬體邏輯,例如讀寫硬體寄存器的通道,至于從硬體中讀到了什麼值或者寫了什麼值到硬體中的邏輯,都放在硬體抽象層中去了,
(三)系統運作時庫(/libcore,/dalvik,/bionic,/system)
-
程式庫:C/C++庫,這些庫能被Android系統中不同的元件使用。
它們通過Android Framework為開發者提供服務。
-
運作庫:
Core Libraries 提供了JAVA程式設計語言核心庫的大多數功能,API,會調用native方法, android.os,android.NET,android.media
Dalvik虛拟機 每一個 Android應用程式都在它自己的程序中運作,都擁有一個獨立的Dalvik虛拟機執行個體。
(四)Android 應用程式架構(/framework)
應用程式架構層是我們從事Android開發的基礎,很多核心應用程式也是通過這一層來實作其核心功能的,該層簡化了元件的重用,開發人員可以直接使用其提供的元件來進行快速的應用程式開發,也可以通過繼承而實作個性化的拓展。
(五)Android 應用程式(/packages)
包括各類與使用者直接互動的應用程式,或由java語言編寫的運作于背景的服務程式,例如,智能手機上實作的常見基本功能 程式,諸如SMS短信,電話撥号,圖檔浏覽器,月曆,遊戲,地圖,web浏覽器等程式,以及開發人員開發的其他應用程式。
Android 層間調用
以Audio為例:(應用程式調用硬體裝置)
應用程式調用了應用架構層的Runtime Service(這裡是MediaPlayer),然後通過JNI調用與之綁定的Runtime Library (這裡是MediaPlayer)。這時MediaPlayer又分别調用MediaFramework,和通過Binder IPC 的方式調用AudioFlinger(原生服務),而後通過AudioFlinger調用指定的庫(libaudio.so),最後才調用Kernel Driver 。
JNI(Java Native Interface)
它提供了若幹的API實作了Java和其他語言的通信(主要是C&C++)
上層Java(Framework)要調用底層的C/C++函數庫(Libraries)必須通過Java的JNI來實作。
Java通過JNI機制和C/C++溝通的具體步驟
1、編寫包含native本地方法的java類(.java)
2、通過javah工具生成C/C++語言的頭檔案(.h)
3、使用C/C++語言實作頭檔案(.c)
4、使用交叉編譯工具對C/C++本地代碼進行編譯,最後通過連結生成*.so可執行的C/C++庫(.so)
5、實際執行Java代碼去和本地的C/C++代碼互相溝通
NDK
NDK是Google公司推出的幫助Android開發者通過C/C++本地語言編寫應用的開發包,包含了C/C++的頭檔案、庫檔案、說明文檔和示例代碼,我們可以了解為Windows Platform SDK一樣,是純C/C++編寫的,但是Android并不支援純C/C++編寫的應用,同時NDK提供的庫和函數功能很有限,僅僅處理些算法效率敏感的問題
簡單點說,用C語言生成一個庫檔案,在java中調用這個庫檔案的函數。JNI的過程比較複雜,生成.so需要大量操作,而NDK就是簡化了這個過程。