Android Linux 内核介绍
扫描二维码
随时随地手机看文章
已经有一些的文章介绍Android内核了,本系列篇将从Linux内核的角度来分析Android的内核,希望给初学者提够有用的信息。本章将简单的介绍 Android内核的全貌,起到一个抛砖引玉的作用。从下一篇开始将详细介绍每一个Android内核驱动程序及其作用。
Android内核是基于Linux 2.6内核的(目前最新开发版本是2.6.31),它是一个增强内核版本,除了修改部分Bug外,它提供了用于支持Android平台的设备驱动,其核心驱动主要包括:
Android Binder ,基于OpenBinder框架的一个驱动,用于提供Android平台的进程间通讯(IPC,inter-process communication)。
源代码位于drivers/staging/android/binder.c
Android电源管理(PM) ,一个基于标准Linux电源管理系统的轻量级的Android电源管理驱动,针对嵌入式设备做了很多优化。
源代码位于kernel/power/earlysuspend.c
kernel/power/consoleearlysuspend.c
kernel/power/fbearlysuspend.c
kernel/power/wakelock.c
kernel/power/userwakelock.c
低内存管理器(Low Memory Killer) ,相对于Linux标准OOM(Out Of Memory)机制更加灵活,它可以根据需要杀死进程来释放需要的内存。
源代码位于drivers/staging/android/lowmemorykiller.c
匿名共享内存(ashmem) ,为进程间提供大块共享内存,同时为内核提供回收和管理这个内存的机制。
源代码位于mm/ashmem.c
Android PMEM(Physical) ,PMEM用于向用户空间提供连续的物理内存区域,DSP和某些设备只能工作在连续的物理内存上。
源代码位于drivers/misc/pmem.c
Android Logger ,一个轻量级的日志设备,用于抓取Android系统的各种日志。
源代码位于drivers/staging/android/logger.c
Android Alarm ,提供了一个定时器用于把设备从睡眠状态唤醒,同时它也提供了一个即使在设备睡眠时也会运行的时钟基准,
源代码位于drivers/rtc/alarm.c
USB Gadget驱动 ,一个基于标准Linux USB gadget驱动框架的设备驱动,Android的USB驱动是基于gaeget框架的,
源代码位于drivers/usb/gadget/
Android Ram Console ,为了提供调试功能,Android允许将调试日志信息写入一个被称为RAM Console的设备里,它是一个基于RAM的Buffer。
源代码位于drivers/staging/android/ram_console.c。
Android timed device ,提供了对设备进行定时控制功能,目前支持vibrator和LED设备。
源代码位于drivers/staging/android/timed_output.c(timed_gpio.c)。
Yaffs2文件系统 ,Android 采用Yaffs2作为MTD nand flash文件系统,源代码位于fs/yaffs2/目录下。Yaffs2是一个快速稳定的应用于NAND和NOR Flash的跨平台的嵌入式设备文件系统,同其他Flash文件系统相比,Yaffs2使用更小的内存来保存他的运行状态,因此它占用内存小;Yaffs2的垃圾回收非常简单而且快速,因此能达到更好的性能;Yaffs2在大容量的NAND Flash上性能表现尤为明显,非常适合大容量的Flash存储。
Android内核添加或修改的文件很多,下面的列表描述了Android Emulator内核的文件:
drivers/misc/kernel_debugger.c
drivers/misc/pmem.c
drivers/misc/qemutrace/qemu_trace_sysfs.c
drivers/misc/qemutrace/qemu_trace.c
drivers/misc/qemutrace/qemu_trace.h
drivers/misc/uid_stat.c
drivers/staging/android/lowmemorykiller.c
drivers/staging/android/logger.c
drivers/staging/android/timed_output.h
drivers/staging/android/ram_console.c
drivers/staging/android/timed_gpio.c
drivers/staging/android/logger.h
drivers/staging/android/binder.h
drivers/staging/android/binder.c
drivers/staging/android/timed_output.c
drivers/staging/android/timed_gpio.h
drivers/rtc/alarm.c
drivers/rtc/rtc-goldfish.c
drivers/net/pppolac.c
drivers/net/ppp_mppe.c
drivers/net/pppopns.c
drivers/video/goldfishfb.c
drivers/switch/switch_class.c
drivers/switch/switch_gpio.c
drivers/char/dcc_tty.c
drivers/char/goldfish_tty.c
drivers/watchdog/i6300esb.c
drivers/input/misc/gpio_event.c
drivers/input/misc/gpio_input.c
drivers/input/misc/gpio_output.c
drivers/input/misc/keychord.c
drivers/input/misc/gpio_axis.c
drivers/input/misc/gpio_matrix.c
drivers/input/keyreset.c
drivers/input/keyboard/goldfish_events.c
drivers/input/touchscreen/synaptics_i2c_rmi.c
drivers/usb/gadget/android.c
drivers/usb/gadget/f_adb.h
drivers/usb/gadget/f_mass_storage.h
drivers/usb/gadget/f_adb.c
drivers/usb/gadget/f_mass_storage.c
drivers/mmc/host/goldfish.c
drivers/power/goldfish_battery.c
drivers/leds/ledtrig-sleep.c
drivers/mtd/devices/goldfish_nand_reg.h
drivers/mtd/devices/goldfish_nand.c
kernel/power/earlysuspend.c
kernel/power/consoleearlysuspend.c
kernel/power/fbearlysuspend.c
kernel/power/wakelock.c
kernel/power/userwakelock.c
kernel/cpuset.c
kernel/cgroup_debug.c
kernel/cgroup.c
mm/ashmem.c
include/linux/ashmem.h
include/linux/switch.h
include/linux/keychord.h
include/linux/earlysuspend.h
include/linux/android_aid.h
include/linux/uid_stat.h
include/linux/if_pppolac.h
include/linux/usb/android.h[!--empirenews.page--]
include/linux/wifi_tiwlan.h
include/linux/android_alarm.h
include/linux/keyreset.h
include/linux/synaptics_i2c_rmi.h
include/linux/android_pmem.h
include/linux/kernel_debugger.h
include/linux/gpio_event.h
include/linux/wakelock.h
include/linux/if_pppopns.h
net/ipv4/sysfs_net_ipv4.c
net/ipv4/af_inet.c
net/ipv6/af_inet6.c
net/bluetooth/af_bluetooth.c
security/commoncap.c
fs/proc/base.c
Android内核配置
Android 是基于 Linux 的 , 对于一个新的设备,我们 首先要 编译一个支持 Android 的 Kernel ,那么如何 使 你的 Kernel Android 化呢?除了要移植前面提到的驱动之外,就是如何配置你的 Kernel 来支持 Android 平台,这可以参考 Goldfish 的内核配置文件 - arch/arm/configs/goldfish_defconfig 。
一般来说,我们会基于一个平台标准内核配置选项来配置 Android 内核,你可以根据具体的硬件平台来选择 Android 内核的配置选项,可以参考下面的 Android 内核配置列表:
一般需要支持的内核选项
ANDROID_PARANOID_NETWORK
ASHMEM
CONFIG_FB_MODE_HELPERS
CONFIG_FONT_8x16
CONFIG_FONT_8x8
CONFIG_YAFFS_SHORT_NAMES_IN_RAM
DAB
EARLYSUSPEND
FB
FB_CFB_COPYAREA
FB_CFB_FILLRECT
FB_CFB_IMAGEBLIT
FB_DEFERRED_IO
FB_TILEBLITTING
HIGH_RES_TIMERS
INOTIFY
INOTIFY_USER
INPUT_EVDEV
INPUT_GPIO
INPUT_MISC
LEDS_CLASS
LEDS_GPIO
LOCK_KERNEL
LkOGGER
LOW_MEMORY_KILLER
MISC_DEVICES
NEW_LEDS
NO_HZ
POWER_SUPPLY
PREEMPT
RAMFS
RTC_CLASS
RTC_LIB
SWITCH
SWITCH_GPIO
TMPFS
UID_STAT
UID16
USB_FUNCTION
USB_FUNCTION_ADB
USER_WAKELOCK
VIDEO_OUTPUT_CONTROL
WAKELOCK
YAFFS_AUTO_YAFFS2
YAFFS_FS
YAFFS_YAFFS1
YAFFS_YAFFS2
但是Android推荐不要支持下面两个功能:
CONFIG_YAFFS_DISABLE_LAZY_LOAD
DNOTIFY
配置好后,就可以用Toolchain来编译内核了。编译内核比较简单,以Emulator的kernel为例:
- git clone git://android.kernel.org/kernel/common.git kernel-emulator
- cd kernel-emulator
- export ARCH=arm
- export CROSS_COMPILE=arm-eabi-
- export PATH=
- make goldfish_defconfig
- make
Google对 2.6.25 内核里做了什么改动呢?
有家公司专门比较了标准内核和android 内核,发现 google 修改了 75 个文件,增加了 88 个文件。改公司还对这些被修改的和新增的文件做了注解。
Goldfish -- 44 Files
Android模拟器运行了一个被 google 叫做 “ 金鱼 " 的虚拟 CPU. 金鱼运行 arm926t 指令集( arm926t 是属于 armv5 架构);并且仿真了输入输出:比如键盘输入和 LCD 输出。这个模拟器其实是在 qemu 之上开发的,输入输出基于 libSDL.
内核里这个Goldfish 接口实现了这个虚拟 “ 金鱼 ”CPU 的一些接口,如果想在真实设备上运行 android, 这些接口肯定要去掉的。
arm926ej的介绍见 http://www.arm.com/products/CPUs/ARM926EJ-S.html
YAFFS2 -- 35 Files
不同于PC 机,文件是存储在硬盘上的;手机使用 FLASH 作为存储介质。 HTC 的 G1 使用 NANDFLASH—— 这中存储目前已经相当普及了 , 而且种类也颇多, (SLC,MLC 等等),存储密度也越来越高(已经出现几十 G 大小的 NANDFLASH) ,价格也越来越低。
YAFFS2是专门用在 FLASH 上的文件系统, “YAFFS2” 是 "Yet Another Flash File System, 2nd edition" 的缩写。 YAFFS2 为 Linux 内核提供了一个高效访问 NANDFLASH 的接口。但是 NANDFLASH 的支持并不包含在标准的 2.6.25 内核中,所以 Google 在其中添加了对 NANDFLASH 的支持。
蓝牙 -- 10 files
在蓝牙通讯协议栈里Google 修改了 10 个文件。这些改动解决了一些跟蓝牙耳机相关的明显的 bug ,以及一些蓝牙调试和访问控制相关的函数。
调度器 -- 5 files
Android内核还修改了进程调度和时钟相关策略,这个改动就比较深入了。其目的和效果估计在一段时间后才能找到。
为android 新增的功能 -- 28 files
除了修正一些bug 以及其他的改动, android 还增加了一些新的 “ 子系统 ” ,这些系统都比较重要。
IPC Binder
IPC Binder是一种 IPC( 进程间通信)机制。它是的进程能够为其他进程提供服务 —— 还是通过标准的 linux 系统调用 api 。 IPC Binder 的概念起源于一家叫做 “Be.Inc" 的公司,在 Google 之前就已经被然后被用到 Palm 软件里去了。
Low Memory Killer
其实内核里已经有一个类似的功能, 叫做"oom killer", 就是 out of memory killer, 当内存不够的时候,改策略会试图结束一个进程。不知道为什么 Google 重新实现了这个策略。
Ashmem
Ashmem,全程 Anonymous SHared MEMory, 翻译成中文就是匿名共享内存。这个功能使得进程间能够共享大块的内存。比如说,系统可以使用 Ashmem 保存一些图标,多个应用程序可以访问这个共享内存来获取图标。 Ashmem 为内核提供了一种回收这些使用完的共享内存块的办法 , 如果一个进程试图访问这些已经被回收的内存块,它将会得到错误的返回值,以便它重新进行内存块分配和数据初始化。[!--empirenews.page--]
RAM Console and Log Device
为了调试方便,Android 添加了一个功能,使得调试信息可以输入到一个内存块中。此外, Android 添加了一个独立的日志模块,这样用户空间的进程能够读写日志消息,调试打印信息等。
Android Debug Bridge
嵌入式设备的调试的确比较麻烦。为了便于调试,google 设计了这个调试工具,可以叫做 "ADB" ,使用 USB 作为连接方式 ,ADB 可以看作是链接 android 的设备和 PC 机的一套协议。
Android 还添加了其他的东西,比如 real-time clock, switch , timed GPIO 。
Power Management -- 5 files
电源管理对于移动设备来说相当重要,也是最复杂,开发难度最高的一个功能。Google 添加了一个新的电源管理系统,并没有原先 apm,dpm 等。
其他修改 -- 36 files
除了上述改动之外,还有一些小改动,比如新增的额外的调试功能, 键盘背光控制,TCP 网络管理等等,共涉及 36 个文件。
根据上述,google 对标准的内核做了很大的改动。相比其他的项目,比如 Nokia N810,Openmoko 等项目中,内核的改动仅仅是增加了某个平台的支持。所以移植最快也是最可能的办法是在 google 使用的 kernel 上增加平台支持。
也有一些开发人员将google 对 2.6.25 内核的改动做成补丁,直接打在自己开发的内核上 —— 当然,自己的内核也应该是 2.6.25 ,否则会出问题。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/guoshaobei/archive/2010/08/21/5827399.aspx
Android是基于Linux,而Linux Kernel的目录结果如下:
浏览内核代码之前,有必要知道内核源码的整体分布情况,按照惯例,内核代码安装在/usr/src/linux目录下,该目录下的每一个子目录都代表了一个特定的内核功能性子集,下面针对2.6.23版本进行简单描述。
(1)Documentation。
这个目录下面没有内核代码,只有很多质量参差不齐的文档,但往往能够给我们提供很多的帮助。
(2)arch。
所有与体系结构相关的代码都在这个目录以及include/asm-*/目录中,Linux支持的每种体系结构在arch目录下都有对应的子目录,而在每个体系结构特有的子目录下又至少包含3个子目录。
kernel:存放支持体系结构特有的诸如信号量处理和SMP之类特征的实现。
lib:存放体系结构特有的对诸如strlen和memcpy之类的通用函数的实现。
mm:存放体系结构特有的内存管理程序的实现。
除了这3个子目录之外,大多数体系结构在必要的情况下还有一个boot子目录,包含了在这种硬件平台上启动内核所使用的部分或全部平台特有代码。
此外,大部分体系结构所特有的子目录还根据需要包含了供附加特性使用的其他子目录。比如,i386目录包含一个math-emu子目录,其中包括了在缺少数学协处理器(FPU)的CPU上运行模拟FPU的代码。
(3)drivers。
这个目录是内核中最庞大的一个目录,显卡、网卡、SCSI适配器、PCI总线、USB总线和其他任何Linux支持的外围设备或总线的驱动程序都可以在这里找到。
(4)fs。
虚拟文件系统(VFS,Virtual File System)的代码,和各个不同文件系统的代码都在这个目录中。Linux支持的所有文件系统在fs目录下面都有一个对应的子目录。比如ext2文件系统对应的是fs/ext2目录。
一个文件系统是存储设备和需要访问存储设备的进程之间的媒介。存储设备可能是本地的物理上可访问的,比如硬盘或CD-ROM驱动器,它们分别使用ext2/ext3和isofs文件系统;也可能是通过网络访问的,使用NFS文件系统。
还有一些虚拟文件系统,比如proc,它以一个标准文件系统出现,然而,它其中的文件只存在于内存中,并不占用磁盘空间。
(5)include。
这个目录包含了内核中大部分的头文件,它们按照下面的子目录进行分组。
include/asm-*/,这样的子目录有多个,每一个都对应着一个arch的子目录,比如include/asm-alpha、include/asm-arm、include/asm-i386等。每个子目录中的文件都定义了支持给定体系结构所必须的预处理器宏和内联函数,这些内联函数多数都是全部或部分使用汇编语言实现的。
编译内核时,系统会建立一个从include/asm目录到目标体系结构特有的目录的符号链接。比如对于arm平台,就是include/asm-arm到include/asm的符号链接。因此,体系结构无关部分的内核代码可以使用如下形式包含体系相关部分的头文件。
#include
include/linux/,与平台无关的头文件都在这个目录下面,它通常会被链接到目录/usr/include/linux(或者它里面的所有文件会被复制到/usr/include/linux目录下面)。因此用户应用程序里和内核代码里的语句:
#include
包含的头文件的内容是一致的。
include目录下的其他子目录,在此不做赘述。
(6)init。
内核的初始化代码。包括main.c、创建早期用户空间的代码以及其他初始化代码。
(7)ipc。
IPC,即进程间通信(interprocess communication)。它包含了共享内存、信号量以及其他形式IPC的代码。
(8)kernel。
内核中最核心的部分,包括进程的调度(kernel/sched.c),以及进程的创建和撤销(kernel/fork.c和kernel/exit.c)等,和平台相关的另外一部分核心的代码在arch/*/kernel目录。
(9)lib。
库代码,实现了一个标准C库的通用子集,包括字符串和内存操作的函数(strlen、mmcpy和其他类似的函数)以及有关sprintf和atoi的系列函数。与arch/lib下的代码不同,这里的库代码都是使用C编写的,在内核新的移植版本中可以直接使用。
(10)mm。
包含了体系结构无关部分的内存管理代码,体系相关的部分位于arch/*/mm目录下。
(11)net。
网络相关代码,实现了各种常见的网络协议,如TCP/IP、IPX等。
(12)scripts。
该目录下没有内核代码,只包含了用来配置内核的脚本文件。当运行make menuconfig或者make xconfig之类的命令配置内核时,用户就是和位于这个目录下的脚本进行交互的。[!--empirenews.page--]
(13)block。
block层的实现。最初block层的代码一部分位于drivers目录,一部分位于fs目录,从2.6.15开始,block层的核心代码被提取出来放在了顶层的block目录。
(14)crypto。
内核本身所用的加密API,实现了常用的加密和散列算法,还有一些压缩和CRC校验算法。
(15)security。
这个目录包括了不同的Linux安全模型的代码,比如NSA Security-Enhanced Linux。
(16)sound。
声卡驱动以及其他声音相关的代码。
(17)usr。
实现了用于打包和压缩的的cpio等。