Android System Structure:

Android 是一个开放的软件系统,为用户提供了丰富的移动设备开发功能,从下至上包括4
个层次,如图1 所示。其中第一层是Linux 内核层,包括Linux 操作系统及驱动,依赖于Linux2.
6 内核,不支持linux2.4 内核。如Android1.0(release 一1.0)使用inux2.6.25,Android1.
6(sdk 一1.6)使用Linux2.6.29。除了标准的Linux 内核外,Android 系统还增加了Binder IPC
驱动、WiFi 驱动、蓝牙驱动等驱动程序,为系统运行提供了基础性支持。
第二层是核心的扩展类库,如SQLite、WebKit、OpenGL 等,它们可以通过JAVA 本地调用
JNI(Java Native Interface)的接口函数实现和上层之间的通信。该层由Android 的Java 虚拟机
Dalvik 和基础的Java 库为Java 运行环境提供了Java 编程语言核心库的大多数功能。
第三层是包含所有开发所用的SDK 类库和某些未公开接口类库的框架层,是整个Android 平
台核心机制的体现。
第四层是应用层。系统部分应用和第三方开发的应用都是位于这个层次上,但两者不完全相
同,其中系统应用会用一些隐藏的类,而第三方的应用,是基于SDK 基础上开发的。一般Android
开发是在SDK 基础上用Java 编写应用程序,但本机开发程序包NDK 提供了应用层穿越Java 框架
层直接和底层包含了JNI 接口的C/C++库直接通信的方法。


其中第一层由C 语言实现,第二层由C 和c+十实现,第三、四层主要由Java 代码实现。从
Linux 操作系统的角度来看,第一、二层次之间是内核空间与用户空间的分界线,第一层运行于
内核空间,第二、三、四层运行于用户空间。第二、三层之间,是本地代码层和Java 代码层的接
口。第三、四层之间是系统API 接口。

Android 代码包括3 个部分:
① 核心工程(Core Project 文件夹)是建立Android 系统的基础,在根目录的各个文件
夹中;
② 扩展工程(External Project 文件夹中)是使用其他开源项目扩展功能;
③ 包(Package)提供Android 的应用程序和服务。其中既包含了原始Android 的目标机
代码,还包括了主机编译工具、仿真环境等。

Mydroid/
—— Makefile (全局的Makefile)
—— bionic (这里面是一些基础的库的源代码)
—— bootloader (引导加载器)
—— build (目录的内容不是目标所用的代码,而是编译和配置所需要的脚本和工具)
—— dalvik (JAVA 虚拟机)
—— development (程序开发所需要的模板和工具)
—— external (目标机器使用的一些库)
—— frameworks (应用程序的框架层)
—— hardware (与硬件相关的库)
—— kernel (Linux2.6 的源代码)
—— packages (Android 的各种应用程序)
—— prebuilt (Android 在各种平台下编译的预置脚本)
—— recovery (与目标的恢复功能相关)
—— system (Android 的底层的一些库)

编译完成后,将在根目录中生成一个out 文件夹,所有生成的Android 代码结构内容均放置
在这个文件夹中。out 文件夹如下所示:
Out/
—— CaseCheck.txt
—— casecheck.txt
—— host
—— common
—— linux—x86
—— taeget
—— common
—— product
主要的两个目录为host 和target,前者表示在主机(x86)生成的工具,后者表示目标机(默
认为ARMy5)运行的内容。

Binder: Android System IPC mechanism.

用户进程如何与系统进程通信,数据共享。

为用户层程序提供进程问通信(IPC)支持,Android 整个系统的运行依赖Binder 驱动。其设
备节点名称为:/dev/binder,主设备号为10,次设备号动态生成。Binder 驱动程序在内核中的
头文件和代码路径如下:
Kernel/include/linux/binder.h


Kernel/drivers/misc/binder.c

drivers/staging/android/binder.c

drivers/staging/android/binder.h

在用户空问libutil 工具库和Service Manager 守护进程中调用Binder 接口提供对整个系统
的支持。
Frameworks/base/cmds/servicemanager/ —— Server Manager 守护进程的实现;

Framewoks/base/include/utils/ —— Binder 驱动在用户空间的封装接1:7;
Frameworks/base/libs/utils/ —— Binder 驱动在用户空间的封装实现。
Binder 是Android 中主要使用的IPC 方式,使用时通常只需要按照模板定义相关的类即可,
不需要直接调用Binder 驱动程序的设备节点。

Eventually they are all Linux process that runs on the system.

A mechanism to send and requests and responses to other process is Binder. Binder is used other than Linux Inter Process Communicaiton (IPC), such as sockets and pipes provided by Linux.

All system functions are provided as server process, need optimized communication mechanism. Binder also provides Remote Procedure Call (RPC) for higher productivity.

More about binder:

ABinder Driveris implemented to use the kernel space. The role of the Binder driver is to convert the memory address that each process has mapped with the memory address of the kernel space for reference

Binder driver, convert memory address each process has with memory address of the kernel address to use the kernel space. It can be used by system function ioctl(), which (the mechanism) is called binder IPC.

LOG

位置在 /dev/log, liblog library used to wrote in by application systems. can access the log by 'adb logcat' command.

Ashmen

System V IPC

Three methods of communication: message queues, semaphores, and shared segments.

keys obtained via ftok(2), which takes a filename and a project argument to generate unique key to describe an instance of an IPC mechanism. System V shared memory only exists in memory, so the segment persist after the termination of the process. And it is programmer's responsibility to remove them to avoid memory leaks. system call is shmget(2).

http://fscked.org/writings/SHM/shm-5.html?wc=EA9qHQF/BBouAxJuDwodExUWVxA=

Message queues provide a memory based FIFO between two processes. The primary difference between a System V message queue and a socket or named pipe is that message queues may have multiple processes reading and writing from and to them, or no readers at all.

Android does not support System V IPCs, i.e. the facilities provided by the
following standard Posix headers:


<sys/sem.h> /* SysV semaphores */
<sys/shm.h> /* SysV shared memory segments */
<sys/msg.h> /* SysV message queues */
<sys/ipc.h> /* General IPC definitions */


The reason for this is due to the fact that, by design, they lead to global
kernel resource leakage.


For example, there is no way to automatically release a SysV semaphore
allocated in the kernel when:


- a buggy or malicious process exits
- a non-buggy and non-malicious process crashes or is explicitly killed.


Killing processes automatically to make room for new ones is an
important part of Android's application lifecycle implementation. This means
that, even assuming only non-buggy and non-malicious code, it is very likely
that over time, the kernel global tables used to implement SysV IPCs will fill
up.


At that point, strange failures are likely to occur and prevent programs that
use them to run properly until the next reboot of the system.


And we can't ignore potential malicious applications. As a proof of concept
here is a simple exploit that you can run on a standard Linux box today:


--------------- cut here ------------------------
#include <sys/sem.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>


#define NUM_SEMAPHORES 32
#define MAX_FAILS 10


int main(void)
{
int counter = 0;
int fails = 0;


if (counter == IPC_PRIVATE)
counter++;


printf( "%d (NUM_SEMAPHORES=%d)\n", counter, NUM_SEMAPHORES);


for (;;) {
int ret = fork();
int status;


if (ret < 0) {
perror("fork:");
break;
}
if (ret == 0) {
/* in the child */
ret = semget( (key_t)counter, NUM_SEMAPHORES, IPC_CREAT );
if (ret < 0) {
return errno;
}
return 0;
}
else {
/* in the parent */
ret = wait(&status);
if (ret < 0) {
perror("waitpid:");
break;
}
if (status != 0) {
status = WEXITSTATUS(status);
fprintf(stderr, "child %d FAIL at counter=%d: %d\n", ret,
counter, status);
if (++fails >= MAX_FAILS)
break;
}
}


counter++;
if ((counter % 1000) == 0) {
printf("%d\n", counter);
}
if (counter == IPC_PRIVATE)
counter++;
}
return 0;
}
--------------- cut here ------------------------


If you run it on a typical Linux distribution today, you'll discover that it
will quickly fill up the kernel's table of unique key_t values, and that
strange things will happen in some parts of the system, but not all.


(You can use the "ipcs -u" command to get a summary describing the kernel
tables and their allocations)


For example, in our experience, anything program launched after that that
calls strerror() will simply crash. The USB sub-system starts spoutting weird
errors to the system console, etc...


Low Memory Killer

Use different method/thresholds to kill applications, before which a process is used to notify them to save the state.

(1)Android是一个多任务系统,也就是说可以同时运行多个程序,这个大家应该很熟悉。一般来说,启动运行一个程序是有一定的时间开销的,因 此为了加快运行速度,当你退出一个程序时,Android并不会立即杀掉它,这样下次再运行该程序时,可以很快的启动。随着系统中保留的程序越来越多,内 存肯定会出现不足,这个时候Android系统开始挥舞屠刀杀程序。这里就有一个很明显的问题,杀谁?

(2)Android系统中杀程序 的这个刽子手被称作"LowMemory Killer",它是在Linux内核中实现的。这里它实现了一个机制,由程序的重要性来决定杀谁。通俗来说,谁不干活,先杀谁。Android将程序的 重要性分成以下几类,按照重要性依次降低的顺序:

名称 oom_adj 解释
FOREGROUD_APP 0 前台程序,可以理解为你正在使用的程序
VISIBLE_APP 1 用户可见的程序
SECONDARY_SERVER 2 后台服务,比如说QQ会在后台运行服务
HOME_APP 4 HOME,就是主界面
HIDDEN_APP 7 被隐藏的程序
CONTENT_PROVIDER 14 内容提供者,
EMPTY_APP
15
空程序,既不提供服务,也不提供内容


其中每个程序都会有一个oom_adj值,这个值越小,程序越重要,被杀的可能性越低。

(3)除了上述程序重要性分类之外,Android系统还维护着另外一张表,这张表是一个对应关系,以N1为例:

oom_adj 内存警戒值( 以4K为单位)
0 1536
1 2048
2 4096
7 5120
14 5632
15 6144

这个表是定义了一个对应关系,每一个警戒值对应了一个重要性值,当系统的可用内存低于某个警戒值时,就杀掉所有大于该警戒值对应的重要性值的程序。 比如说,当可用内存小于6144 * 4K = 24MB时,开始杀所有的EMPTY_APP,当可用内存小于5632 * 4K = 22MB时,开始杀所有
的CONTENT_PROVIDER和EMPTY_APP。


(4) alter minfree改的是什么呢,上面这张对应表是由两个文件组成的:
/sys/module/lowmemorykiller/parameters/adj和/sys/module/lowmemorykiller/parameters/minfree。

alter minfreee就是修改/sys/module/lowmemorykiller/parameters/minfree这个文件的,举例来说,如果把最后一项改为32 * 1024,那么当可用内存小于128MB是,就开始杀所有的EMPTY_APP。

Bootloader:

bootloader的定义:

相当于pc机的BIOS,在操作系统启动内核运行之前运行的一段小程序,通过这段小程序我们可以初始化cpu内部的硬件设备,建立内存空间映射范围,从而将系统的软硬件环境带到一个合适的状态,以便最终调用os内核准备好正确的环境。


可以得出bootloader主要有2个任务,1是初始化cpu内部的硬件设备,2是将os kernel带到内存中去。

在讲bootloader之前,我们先讲讲pc机的启动过程,

pc机中有bois,这个是固化在硬件的,当pc机一加电以后,bios就会自己启动,完成硬件检测和资源的分配,然后将硬盘中的引导程序调入内存,然后把控制权交给引导程序,引导程序主要的用途就是将操作系统的kernel调入内存,然后跳转到内核的开始地址,然后os就开始启动了。

就pc而言,启动的过程相对复杂,从bios--->引导程序(grub等)---->os

但是嵌入式系统来说,他没有bios这样硬件,所以它的启动过程全部都是交给bootloader去完成的。

bootloader是放在flash的最前面的位置,原因是:

系统在加电或复位的时候,所有的cpu通常都从cpu制造商预先安排地址开始执行的,(通常是0x00000000位置),所以bootloader通常是放在flash中的最前面的位置。

这是一个简易的flash分布图,bootloader在flash的最前端。

关于bootloader的启动过程还可以分为两种,1是单阶段,2是多阶段的

现在很多的bootloader是2个阶段的

stage 1 的步骤(用的是汇编)

1是初始化硬件设备(cpu内存的硬件设备)

2是初始化stage2 要使用的内存空间

3是把stage 2的代码copy到内存中去

4初始话堆栈

5是跳转到c的入口函数


stage 2(c语言)

1.初始化本阶段的硬件设备(板载硬件设备)

2.将os kernel导入到内存中去

3.调用内核


stage 1是用汇编写,主要是是为了配置能让c语言运行环境。

这个是一个具体的flash的结构图,bootloader 在执行第一个部分的时候,也就是stage1的时候,会把bootloader stage2这部分copy到ram中去运行,为什么呢,我觉得一个在内存中运行总是比在flash中执行要好,第二我觉得能执行code的flash必须是nor flash,这样的flash相对成本也就高了。所以就会产生这个部分。当stage2的时候,会将kernel也copy到内存中,然后在结束的阶段,让执行地址跳转到操作系统的入口地址,那样的话操作系统也就自己启动来了。


如果分析过2440的官方代码的话,里面有一个start.s 这个汇编代码,这可以看成一个小型的bootloader,因为他也完成了自启动的过程,不过他启动的是你的程序而不是操作系统,不过作用很相似。


在上面我们知道bootloader stage1这个阶段的代码是运行在flash中的,如果flash是nor flash的话也是可以的,不过如果你的开发板是不带nor flash的话则就不能了。nand flash是不能让代码运行在flash的,所以他的自启动过程是比较复杂的。他的cpu有一个4k ram 在加电的时候是被当作垫脚石使用的,当板子加电以后,硬件会自动把flash最前面的code copy到这个内存中的,也就是bootloader stage1这个部分,在这4kB的空间中的代码必须要完成讲代码copy的内存中去

对于bootloader的研究我觉得可以看一下start.s这个源代码,你会知道的更加清楚,不过是汇编的,理解起来会有点困难,要耐心看的.....


还有关于bootloader的移植,为什么要进行bootloader的移植呢,原因有2个

1是因为不同的板子之间的cpu体系结构不一样...

2是因为不同的板子之间的外围硬件设备不一样...

Devices Files


Android

Everything in the system is file, also the devices. Access the devices at /dev/

Proc Virtual Filesystem

Every Component in Android is called module defined by Android.mk



References: Android 底层驱动.

http://www.cubrid.org/blog/dev-platform/binder-communication-mechanism-of-android-processes/

更多相关文章

  1. Android(安卓)双击返回键退出应用
  2. Android实现整理PackageManager获取所有安装程序信息
  3. Android杂谈--内存泄露(1)--contentView缓存使用与ListView优化
  4. ubuntu12.04(64bit)编译android-3.4内核代码
  5. Android安装服务installd源码分析
  6. Cocos2d-x 3.2编译生成Android程序出错的解决方案:c++_static报
  7. 关于异步加载、缓存图片、软引用等
  8. 使用Fragment让程序界面一分为多
  9. android log 日志分析 来自 Google I/O 2011: Memory man...

随机推荐

  1. android怎样在布局文件监听事假
  2. Android(安卓)文件工具FileUtil
  3. Android(安卓)Media Scanner Mechanism A
  4. 【android】两个按钮的宽度各占屏幕的一
  5. 智能手机软件平台 Android(安卓)VS iPhon
  6. android 数据库
  7. Android(安卓)自定义对话框
  8. Android学习笔记(6)————Android的线
  9. android系统编译的网站
  10. android UI布局练习3