Android系统启动1————概述和Liunx内核的启动

Android系统启动1————概述和Linux内核的启动

一.概述

1.系统启动的整体流程

Android启动大致分为三个阶段

  • BootLoader引导即uBoot.bin
  • linux内核启动即zImage
  • Android系统启动即ramdisk.img与system.img

其中Android启动又可以分为下面的步骤

  • init进程的启动
  • zygote进程的启动
  • system Service进程的启动
  • 最后Launcher启动Home Activity

大致过程如下图所示:
在这里插入图片描述其中1,2,3是linux启动过程,4,5,6是android启动过程。

2.init进程简介

init进程是Android系统中用户空间的第一个进程,作为第一个进程,它被赋予了很多极其重要的工作职责,比如创建zygote(孵化器)和属性服务等。init进程是由多个源文件共同组成的,这些文件位于源码目录system/core/init。

也就是说,init进程负责两件事

  • 负责创建系统中比较关键的进程,比如说zygote进程
  • Andorid系统中有很多属性,于是init进程就提供了一个property Service(属性服务)来管理他们
3.Zygote进程简介

在Android中,虚拟机,应用程序进程以及运行系统的关键服务的SystemServer进程都是由Zygote进程来创建的,我们也将它称为孵化器。它通过fock(复制进程)的形式来创建应用程序进程和SystemServer进程,由于Zygote进程在启动时会创建DVM,因此通过fock而创建的应用程序进程和SystemServer进程可以在内部获取一个DVM的实例拷贝。

也就是说,Zygote进程主要负责下面三件事

  • 启动虚拟机
  • 创建SystemServer进程
  • 创建应用进程
4.SystemServer进程简介

SystemServer的进程名实际上叫做“system_server”,通常简称为SS。

系统中的服务驻留在其中,常见的比如WindowManagerServer(Wms)、ActivityManagerSystemService(AmS)、 PackageManagerServer(PmS)等,这些系统服务都是以一个线程的方式存在于SystemServer进程中。

也就是说,在SystemServer中,主要负责各种服务的创建。

二.BootLoader的启动

当按开机键的时候,引导芯片开始从固化在ROM的预设代码开始执行,然后加载引导程序到RAM。这个引导程序就是BootLoader()。因为笔者没有做过单片机的相关学习,所以下面的内容是我根据网上的资料整理而来。文末会附上链接。

BootLoaderd 分为两个阶段,一个阶段是汇编部分,一个阶段是C语言部分.

另外,关于BootLoader有很多的实现,下面以一个比较通用的BootLoader实现 uBoot为例

1.BootLoaderd的启动1-汇编阶段

目录:cpu/arm920t/start.S

a.设置CPU进入SVC模式(系统管理模式),cpsr[4:0]=0xd3

#include <common.h>
#include <config.h>

 //u-boot的主入口,跳入了后面的start_code
.globl _start   
//这些是跳转向量表,和芯片的体系结构有关
// ldr语句的意思是将第二个操作数(如:_undefined_instruction)指向的地址数据传给PC
_start:        b       start_code                      
         ldr     pc, _undefined_instruction          
         ldr     pc, _software_interrupt
         ldr     pc, _prefetch_abort
         ldr     pc, _data_abort
         ldr     pc, _not_used
         ldr     pc, _irq
         ldr     pc, _fiq

 //.word 为定义一个4字节的空间 undefined_instruction 为地址, 即后面标号所对的偏移地址数据
 //undefined_instruction 为地址, 即后面标号所对的偏移地址数据
_undefined_instruction:      .word undefined_instruction  
_software_interrupt:    .word software_interrupt
_prefetch_abort:          .word prefetch_abort
_data_abort:                .word data_abort
_not_used:                  .word not_used
_irq:                    .word irq
_fiq:                     .word fiq

//16字节对齐,并以0xdeadbeef填充,它是个Magic number 。
          .balignl 16,0xdeadbeef

b.接着进入Start_code中:设置CPU进入SVC模式。

 /*
  * the actual start code
  */
  
 start_code:
     /*
       * set the cpu to SVC32 mode
       */
      mrs    r0, cpsr
     bic    r0, r0, #0x1f
     orr    r0, r0, #0xd3
     msr    cpsr, r0
 
    bl    coloured_LED_init
    bl    red_LED_on

c.关看门狗,WTCON = 0x0,并设置寄存器地址

”watchdog”,俗称“看门狗”。“Watchdog” 在实现上可以是硬件电路也可以是软件定时器,能够在系统出现故障时自动重新启动系统。

复制代码

  /* turn off the watchdog */
  
  # if defined(CONFIG_S3C2400)
  
  #  define pWTCON    0x15300000    
  #  define INTMSK    0x14400008    /* Interupt-Controller base addresses */
  #  define CLKDIVN    0x14800014    /* clock divisor register */
  #else
  #  define pWTCON    0x53000000
  #  define INTMSK    0x4A000008    /* Interupt-Controller base addresses */
  #  define INTSUBMSK    0x4A00001C
  #  define CLKDIVN    0x4C000014    /* clock divisor register */
  # endif
     //关看门狗
     ldr    r0, =pWTCON
     mov    r1, #0x0
     str    r1, [r0]

d.关中断,INTMSK=0xFFFFFFFF, INTSUBMSK=0x3FF。

   /*
       * mask all IRQs by setting all bits in the INTMR - default
       */
      mov    r1, #0xffffffff
      ldr    r0, =INTMSK
      str    r1, [r0]
  # if defined(CONFIG_S3C2410)
      ldr    r1, =0x3ff
      ldr    r0, =INTSUBMSK
      str    r1, [r0]
  # endif

e.时钟设置CLKDIVN=0x3 , FCLK:HCLK:PCLK = 1:2:4

 /* FCLK:HCLK:PCLK = 1:2:4 */
     /* default FCLK is 120 MHz ! */
     ldr    r0, =CLKDIVN
     mov    r1, #3
     str    r1, [r0]
 #endif    /* CONFIG_S3C24X0 */

f.询问是否进行CPU初始化

 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
     bl    cpu_init_crit
 #endif

g.初始化堆栈,如果要在C语言环境下执行代码,就必须初始化堆栈

 /* Set up the stack                            */
  stack_setup:/* 设置栈指针 */
      ldr    r0, _TEXT_BASE        /* upper 128 KiB: relocated uboot   */
      sub    r0, r0, #CONFIG_SYS_MALLOC_LEN    /* malloc area              */
      sub    r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo                 */
  #ifdef CONFIG_USE_IRQ
      sub    r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
  #endif
      sub    sp, r0, #12        /* leave 3 words for abort-stack    */
 
  clear_bss:
     ldr    r0, _bss_start        /* find start of bss segment        */
     ldr    r1, _bss_end        /* stop here                        */
     mov    r2, #0x00000000        /* clear                            */
 
 clbss_l:str    r2, [r0]        /* clear loop...                    */
     add    r0, r0, #4
     cmp    r0, r1
     ble    clbss_l

只要将sp指针指向一段没有被使用的内存就完成栈的设置了。根据上面的代码可以知道U-Boot内存使用情况了,如下图所示:
在这里插入图片描述
h.CPU的初始化,即cpu_init_crit函数,完成以后回到主函数

 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
  cpu_init_crit:
      /*
       * flush v4 I/D caches
      */
      mov    r0, #0
      mcr    p15, 0, r0, c7, c7, 0    /* flush v3/v4 cache */
      mcr    p15, 0, r0, c8, c7, 0    /* flush v4 TLB */
  
     /*
      * disable MMU stuff and caches
      */
     mrc    p15, 0, r0, c1, c0, 0
     bic    r0, r0, #0x00002300    @ clear bits 13, 9:8 (--V- --RS)
     bic    r0, r0, #0x00000087    @ clear bits 7, 2:0 (B--- -CAM)
     orr    r0, r0, #0x00000002    @ set bit 2 (A) Align
     orr    r0, r0, #0x00001000    @ set bit 12 (I) I-Cache
     mcr    p15, 0, r0, c1, c0, 0
 
     /*
      * before relocating, we have to setup RAM timing
      * because memory timing is board-dependend, you will
      * find a lowlevel_init.S in your board directory.
      */
     mov    ip, lr
 
     bl    lowlevel_init
 
     mov    lr, ip
     mov    pc, lr
 #endif /* CONFIG_SKIP_LOWLEVEL_INIT */

i.清除bss段

clear_bss:  /* 清除bss段 */
	ldr	r0, _bss_start  /* r0 = bss段的起始位置 */
	ldr	r1, _bss_end		@ stop here                        /* r1 = bss段结束位置 */
	mov	r2, #0x0		@ clear value                           /* r2 = 0 */
clbss_l:
	str	r2, [r0]		@ clear BSS location                    /* 先将r2,即0x0,存到地址为r0的内存中去 */
	cmp	r0, r1			@ are we at the end yet                  /* 比较r0地址和r1地址,即比较当前地址是否到了bss段的结束位置 */
	add	r0, r0, #4		@ increment clear index pointer           /* 然后r0地址加上4 */
		bne	clbss_l			@ keep clearing till at end           /* 如果不等于,那么就跳到clbss_l,即接着这几个步骤,直到地址超过了bss的_end位置,即实现了将整个bss段,都清零。*/

j.从这里跳转到第二阶段C代码中去

 ldr    pc, _start_armboot
  _start_armboot:    .word start_armboot

汇编第一阶段的代码主要可以分为以下部分:

  • 设置异常向量表
  • 设置特权管理模式
  • 初始化PLL、DDR、MUX…
  • 关MMU,关CACHE
  • 判断代码在RAM还是FLASH,将FLASH代码复制至RAM中
  • 设置堆栈、清空bss段
  • 跳转至C语言处,进入第二阶段
2.BootLoaderd的启动2-c语言阶段

目录:u-boot-2010.06\arch\arm\lib\board.c

第二阶段主要用到了两个数据结构即 gd_t 和 bd_t,这两个类型变量记录了刚启动时的信息,还将记录作为引导内核和文件系统的参数,如 bootargs 等,并且将来还会在启动内核时,由 uboot 交由 kernel 时会有所用。其定义如下:
gd_t :

#### u-boot-2010.06\arch\arm\include\asm\global_data.h ####
/*  U-Boot使用了一个存储在寄存器中的指针gd来记录全局数据区的地址,这个指针存放在指定的寄存器r8中 */
typedef	struct	global_data {  /* 全局数据结构 */  
	bd_t		*bd;  /* 指向板级信息结构 */  
	unsigned long	flags;   /* 标记位 */  
	unsigned long	baudrate;  /* 串口波特率 */  
	unsigned long	have_console;  /* serial_init() was called */
	unsigned long	env_addr;  /* 环境参数地址 */ 
	unsigned long	env_valid;  /* 环境参数 CRC 校验有效标志 */
	unsigned long	fb_base;  /* fb 起始地址 */
#ifdef CONFIG_VFD
	unsigned char	vfd_type;  /* 显示器类型(VFD代指真空荧光屏) */
#endif
#ifdef CONFIG_FSL_ESDHC  /* 宏未定义 */
	unsigned long	sdhc_clk;  
#endif
#if 0  /* 未定义 */
	unsigned long	cpu_clk;  /* cpu 频率*/
	unsigned long	bus_clk;  /* bus 频率 */  
	phys_size_t	ram_size;  /* ram 大小 */
	unsigned long	reset_status;	/* reset status register at boot */
#endif
	void		**jt;  /* 跳转函数表 */
} gd_t;
 

bd_t

typedef struct bd_info {  /* 板级信息结构 */ 
    int			bi_baudrate;  /* 波特率 */
    unsigned long	bi_ip_addr;  /* IP地址 */
    struct environment_s	       *bi_env;  /* 板子的环境变量 */  
    ulong	        bi_arch_number;  /* 板子的 id */ 
    ulong	        bi_boot_params;  /* 板子的启动参数 */ 
    struct	  /* RAM 配置 */ 
    {
	ulong start;
	ulong size;
    }			bi_dram[CONFIG_NR_DRAM_BANKS];
} bd_t;

a.tart_armboot 首先为全局数据结构和板级信息结构分配内存

	gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));
	/* compiler optimization barrier needed for GCC >= 3.4 */
	__asm__ __volatile__("": : :"memory");  /* 内存屏障,防止编译器优化 */
	memset ((void*)gd, 0, sizeof (gd_t));  /* 将指定的内存地址清零( 将全局数据清零 ) */
	gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));  /* gd->bd指向一块地址( 取得板级信息数据结构的起始地址 )  */
	memset (gd->bd, 0, sizeof (bd_t));  /* gd->db指向地址中的内容清零( 将板级信息清零 ) */
	gd->flags |= GD_FLG_RELOC;  /* 标记为代码已经转移到 RAM */

b.调用 init_sequence数组中的函数指针完成各部分的初始化

init_fnc_t *init_sequence[] = {
#if defined(CONFIG_ARCH_CPU_INIT)
	arch_cpu_init,  /* 基本的处理器相关配置 -- basic arch cpu dependent setup */
#endif
	timer_init,	 /* 初始化定时器 -- initialize timer before usb init */
	board_init,  /* 板级特殊设备初始化(很重要) -- basic board dependent setup */
#if defined(CONFIG_USE_IRQ)
	interrupt_init,  /* 中断初始化 -- set up exceptions */
#endif
//	timer_init,	/* 初始化定时器 */
#ifdef CONFIG_FSL_ESDHC
	get_clocks,
#endif
	env_init,  /* 初始化环境变量(默认的环境变量) -- initialize environment */
	init_baudrate,  /* 初始化波特率设置 -- initialze baudrate settings */
	serial_init,  /* 初始化串口 */
	console_init_f,  /* 控制台初始化 -- stage 1 init of console */
	display_banner,	 /* 打印uboot版本信息 -- say that we are here */
#if defined(CONFIG_DISPLAY_CPUINFO)
	print_cpuinfo,  /* 显示cpu信息 -- display cpu info (and speed) */
#endif
#if defined(CONFIG_DISPLAY_BOARDINFO)
	checkboard,  /* 显示板级信息 -- display board info */
#endif
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
	init_func_i2c,  /* 初始化IIC,hard:真正iic,soft:gpio模拟iic */
#endif
	dram_init,	/* 配置可用RAM -- configure available RAM banks */
#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)
	arm_pci_init,  /* 初始化pci */
#endif
	NULL,
};
/* 函数指针,执行指针数组中的内容(实际内容为函数指针),初始化cpu、总线、设备等等*/
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) {
hang ();
}
}
void hang (void) {
	puts ("### ERROR ### Please RESET the board ###\n");
	for (;;);
}

c.start_armboot 在接下来的流程中还做了如下操作:

void start_armboot (void)
{nand_init();  /* 初始化 NAND */mmc_initialize(0);  /* 初始化MMC */
	mmc_flash_init(0);
	env_relocate ()  /* 重定位环境变量,将其从 NAND 拷贝到内存中 */  
    …
	gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");  /* 设置IP地址 */
	stdio_init ();  /* 初始化外设 */  
	jumptable_init ();  /* 初始化跳转函数表 */
    …
	console_init_r ();  /* 控制台初始化第二阶段 */
    …
	misc_init_r ();  /* 杂项设备初始化, eg:battery */  
    …
	enable_interrupts ();  /* 使能中断 */
#ifdef CONFIG_KEDACOM_E2PROM
	extern int kd_set_ethaddr();
	kd_set_ethaddr();
#endif/* 如果存在则从环境变量中读取装载地址,其默认为 ulong load_addr = CONFIG_SYS_LOAD_ADDR; */
	if ((s = getenv ("loadaddr")) != NULL) {
		load_addr = simple_strtoul (s, NULL, 16);
	}
#if defined(CONFIG_CMD_NET)
	if ((s = getenv ("bootfile")) != NULL) {
		copy_filename (BootFile, s, sizeof (BootFile));
	}
#endif#if defined(CONFIG_CMD_NET)eth_initialize(gd->bd);  /* 网络初始化 */#endif
#if defined(CONFIG_BOOTROM_SUPPORT)
	extern void download_boot(const int (*handle)(void));
	download_boot(NULL);
#endif
	product_control();#ifdef CONFIG_PARTTAB_ON_FLASH
	partition_check_update_flags();
#endif
	/* main_loop() can return to retry autoboot, if so just run it again. */
	for (;;) {
		main_loop ();  /* 进入主循环 common/main.c */ 
	}
}

d.main_loop 函数

#### u-boot-2010.06\arch\arm\lib\board.c ####
void main_loop (void)
{
    …
setenv ("ver", version_string);  /* 设置版本信息 */
    …
	update_tftp ();.
#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
	s = getenv ("bootdelay");    /* 获取bootdelay环境变量的值 */
	bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;    /* 将字符串转换为long类型变量 */
	debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay);
	debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");
    /* 倒数读秒,如果delay时间内没有操作,执行run_command命令 */
	if (bootdelay >= 0 && s && !abortboot (bootdelay)) {
		run_command (s, 0);
	}
#endif	/* CONFIG_BOOTDELAY */for (;;) {
        …
		len = readline (CONFIG_SYS_PROMPT); /* 读取输入 */
		flag = 0;	/* assume no special flags for now */
		if (len > 0)
			strcpy (lastcommand, console_buffer);  /* 将输入保存到历史记录中 */
		else if (len == 0)
			flag |= CMD_FLAG_REPEAT;  /* 如果没有输入则重复上次 */if (len == -1)
			puts ("<INTERRUPT>\n");
		else
			rc = run_command(lastcommand, flag);  /* 执行命令 */
			lastcommand[0] = 0;  /* 将命令置无效命令令其不可重复 */
	}
}

e.通过一个函数指针 thekernel()带三个参数跳转到内核( zImage )入口点开始执行

此时, u-boot 的任务已经完成,控制权完全交给内核( zImage )。在 uBoot 的文件lib_arm\bootm.c中定义了 thekernel, 并在 do_bootm_linux 的最后执行 thekernel。定义thekernel函数指针,获取bootargs参数给commandline指针。theKernel (0, machid, bd->bi_boot_params);第一个参数必须为0,第二个参数为机器类型ID,第三个参数为传递给内核参数的起始地址0x30000100

 int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
   {
       bd_t    *bd = gd->bd;
       char    *s;
       int    machid = bd->bi_arch_number;
       void    (*theKernel)(int zero, int arch, uint params);
       int    ret;
   
   #ifdef CONFIG_CMDLINE_TAG
       char *commandline = getenv ("bootargs");
   #endif
   
       if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
           return 1;
   
       theKernel = (void (*)(int, int, uint))images->ep;
   
       s = getenv ("machid");
       if (s) {
           machid = simple_strtoul (s, NULL, 16);
           printf ("Using machid 0x%x from environment\n", machid);
       }
       
       ret = boot_get_ramdisk(argc, argv, images, IH_ARCH_ARM, 
               &(images->rd_start), &(images->rd_end));
       if(ret)
           printf("[err] boot_get_ramdisk\n");
   
       show_boot_progress (15);
   
       debug ("## Transferring control to Linux (at address %0 lx) ...\n",
              (ulong) theKernel);
   
   #if defined (CONFIG_SETUP_MEMORY_TAGS) || \
       defined (CONFIG_CMDLINE_TAG) || \
       defined (CONFIG_INITRD_TAG) || \
       defined (CONFIG_SERIAL_TAG) || \
       defined (CONFIG_REVISION_TAG) || \
       defined (CONFIG_LCD) || \
       defined (CONFIG_VFD)
       setup_start_tag (bd);
   #ifdef CONFIG_SERIAL_TAG
       setup_serial_tag (&params);
   #endif
   #ifdef CONFIG_REVISION_TAG
       setup_revision_tag (&params);
   #endif
   #ifdef CONFIG_SETUP_MEMORY_TAGS
       setup_memory_tags (bd);
  #endif
   #ifdef CONFIG_CMDLINE_TAG
       setup_commandline_tag (bd, commandline);
   #endif
   #ifdef CONFIG_INITRD_TAG
       if (images->rd_start && images->rd_end)
           setup_initrd_tag (bd, images->rd_start, images->rd_end);
   #endif
   #if defined (CONFIG_VFD) || defined (CONFIG_LCD)
       setup_videolfb_tag ((gd_t *) gd);
   #endif
       setup_end_tag (bd);
   #endif
   
       /* we assume that the kernel is in place */
       printf ("\nStarting kernel ...\n\n");
   
   #ifdef CONFIG_USB_DEVICE
       {
           extern void udc_disconnect (void);
           udc_disconnect ();
       }
   #endif
   
       cleanup_before_linux ();
   
       theKernel (0, machid, bd->bi_boot_params);
       /* does not return */
   
       return 1;
   }

小结,第二阶段代码可以分为下面部分
为gd、bd数据结构分配地址,并清零

  • 执行 init_fnc_ptr 函数指针数组中的各个初始化函数:板级特殊设备初始化(board_init)、时钟初始化(timer_init)、初始化环境变量(env_init)、串口控制台初始化(init_baudrate、console_init_f)、打印U-Boot信息(display_banner、print_cpuinfo、checkboard)、配置可用RAM大小(dram_init)
  • 对gd, bd 数据结构赋值初始化
  • 各种设备初始化
  • NAND Flash初始化 (nand_init) 、MMC初始化 (mmc_initialize、mmc_flash_init) 、网络初始化 (eth_initialize)、初始化串口(serial_init、console_init_r) 、初始化其他外设(stdio_init)、杂项设备初始化(misc_init_r)
  • 环境变量代码重定位(env_relocate)
  • 使能中断(enable_interrupts)
  • 进入主循环(main_loop)
  • 调用 thekernel进入kernel,启动Linux系统

三.Linux的启动

关于Linux系统启动主要分为三个阶段,第一个阶段是自解压过程,第二个是设置ARM处理器的工作模式、设置一级页表等,第三个阶段主要是C代码,包括Android的初始化的全部工作。

  • 自解压过程,内核压缩和解压缩目录kernel/arch/boot/compressed,编译完成后将产生head.o、misc.o、piggy.gzip.o、vmlinux、decompress.o这几个文件。
  • 解压缩完成后就进入Kernel初始化阶段。也就是我着重介绍的部分。
  • 第三阶段主要是C代码,包括Android的初始化的全部工作
1.head.S
 * Non-board-specific low-level startup code
 *
 * Copyright (C) 2004-2006 Atmel Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#include <linux/linkage.h>

#include <asm/page.h>

    .section .init.text,"ax"
    .global kernel_entry
kernel_entry:
    /* Start the show */
    lddpc   pc, kernel_start_addr

    .align  2
kernel_start_addr:
    .long   start_kernel

从上面的代码我们看出,最终调用了start_kernel方法

2.start_kernel
asmlinkage __visible void __init start_kernel(void)
{
    char *command_line;
    char *after_dashes;

    /*
     * Need to run as early as possible, to initialize the lockdep hash:
     * 需要尽早运行,初始化lockdep散列:
     */
    lockdep_init();
    set_task_stack_end_magic(&init_task);
    smp_setup_processor_id();
    debug_objects_early_init();

    /*
     * Set up the the initial canary ASAP:
     * 尽快设置初始ASAP:
     */
    boot_init_stack_canary();

    cgroup_init_early();

    local_irq_disable();
    early_boot_irqs_disabled = true;

    /*
     * Interrupts are still disabled. Do necessary setups, then
     * enable them
     */
    boot_cpu_init();
    page_address_init();
    pr_notice("%s", linux_banner);
    setup_arch(&command_line);
    mm_init_cpumask(&init_mm);
    setup_command_line(command_line);
    setup_nr_cpu_ids();
    setup_per_cpu_areas();
    smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */
    build_all_zonelists(NULL, NULL);
    page_alloc_init();

    pr_notice("Kernel command line: %s\n", boot_command_line);
    parse_early_param();
    after_dashes = parse_args("Booting kernel",
                    static_command_line, __start___param,
                    __stop___param - __start___param,
                    -1, -1, NULL, &unknown_bootoption);
    if (!IS_ERR_OR_NULL(after_dashes))
        parse_args("Setting init args", after_dashes, NULL, 0, -1, -1, NULL, set_init_arg);

    jump_label_init();

    /*
     * These use large bootmem allocations and must precede kmem_cache_init()
     */
    setup_log_buf(0);
    pidhash_init();
    vfs_caches_init_early();
    sort_main_extable();
    trap_init();
    mm_init();

    /*
     * Set up the scheduler prior starting any interrupts (such as the
     * timer interrupt). Full topology setup happens at smp_init()
     * time - but meanwhile we still have a functioning scheduler.
     */
     //初始化每个处理器的可运行队列,设置系统初始化进程即0号进程
    sched_init();
    /*
     * Disable preemption - early bootup scheduling is extremely
     * fragile until we cpu_idle() for the first time.
     */
    preempt_disable();
    if (WARN(!irqs_disabled(), "Interrupts were enabled *very* early, fixing it\n"))
        local_irq_disable();
    idr_init_cache();
    rcu_init();

    /* trace_printk() and trace points may be used after this */
    trace_init();

    context_tracking_init();
    radix_tree_init();
    /* init some links before init_ISA_irqs() */
    early_irq_init();
    init_IRQ();
    tick_init();
    rcu_init_nohz();
    init_timers();
    hrtimers_init();
    softirq_init();
    timekeeping_init();
    time_init();
    sched_clock_postinit();
    perf_event_init();
    profile_init();
    call_function_init();
    WARN(!irqs_disabled(), "Interrupts were enabled early\n");
    early_boot_irqs_disabled = false;
    local_irq_enable();
    kmem_cache_init_late();

    /*
     * HACK ALERT! This is early. We're enabling the console before
     * we've done PCI setups etc, and console_init() must be aware of
     * this. But we do want output early, in case something goes wrong.
     */
    console_init();
    if (panic_later)
        panic("Too many boot %s vars at `%s'", panic_later, panic_param);

    lockdep_info();

    /*
     * Need to run this when irqs are enabled, because it wants
     * to self-test [hard/soft]-irqs on/off lock inversion bugs
     * too:
     */
    locking_selftest();

#ifdef CONFIG_BLK_DEV_INITRD
    if (initrd_start && !initrd_below_start_ok &&
        page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
        pr_crit("initrd overwritten (0x%08lx < 0x%08lx) - disabling it.\n",
        page_to_pfn(virt_to_page((void *)initrd_start)), min_low_pfn);
        initrd_start = 0;
    }
#endif
    page_ext_init();
    debug_objects_mem_init();
    kmemleak_init();
    setup_per_cpu_pageset();
    numa_policy_init();
    if (late_time_init)
    late_time_init();
    sched_clock_init();
    calibrate_delay();
    pidmap_init();
    anon_vma_init();
    acpi_early_init();
#ifdef CONFIG_X86
    if (efi_enabled(EFI_RUNTIME_SERVICES))
        efi_enter_virtual_mode();
#endif
#ifdef CONFIG_X86_ESPFIX64
    /* Should be run before the first non-init thread is created */
    init_espfix_bsp();
#endif
    thread_stack_cache_init();
    cred_init();
    fork_init();
    proc_caches_init();
    buffer_init();
    key_init();
    security_init();
    dbg_late_init();
    vfs_caches_init();
    signals_init();
    /* rootfs populating might need page-writeback */
    page_writeback_init();
    proc_root_init();
    nsfs_init();
    cpuset_init();
    cgroup_init();
    taskstats_init_early();
    delayacct_init();
    check_bugs();

    acpi_subsystem_init();
    sfi_init_late();

    if (efi_enabled(EFI_RUNTIME_SERVICES)) {
        efi_late_init();
        efi_free_boot_services();
    }

    ftrace_init();

    /* Do the rest non-__init'ed, we're now alive */
    //调用kernel_thread()创建1号内核线程
    rest_init();
}

start_kernel()函数中执行了大量的初始化操作:

  • setup_arch():主要做一些板级初始化,cpu初始化,tag参数解析,u-boot传递的cmdline解析,建立mmu工作页表,初始化内存布局,调用mmap_io建立GPIO、IRQ、MEMCTRL、UART,及其他外设的静态映射表,对时钟,定时器,uart进行初始化
  • sched_init():初始化每个处理器的可运行队列,设置系统初始化进程即0号进程
  • softirq_init():内核的软中断机制初始化函数
  • console_init():初始化系统的控制台结构
  • rest_init():调用kernel_thread()创建1号内核线程,调用schedule()函数切换当前进程,在调用该函数之前,Linux系统中只有两个进程,即0号进程init_task和1号进程kernel_init,其中kernel_init进程也是刚刚被创建的。调用该函数后,1号进程kernel_init将会运行
3.kernel进程

Linux下有三个特殊的进程,idle(swapper)进程(PID = 0),init进程(PID = 1)和看threadd(PID = 2)

  • idle(swapper)进程由系统自动创建,运行在内核态.idle进程其pid=0,其前身是系统创建的第一个进程,也是唯一一个没有通过fork或者kernel_thread产生的进程。
    • 完成加载系统后,演变为进程调度、交换,常常被称为交换进程。
  • init进程由idle通过kernel_thread创建,在内核空间完成初始化后,加载init进程,并最终转变为用户空间的init进程。
    • 由0进程创建,完成系统的初始化,是系统中所有其他用户进程的祖先进程。
    • linux中的所有进程都是由init进程创建并运行的,首先Linux内核启动,然后在用户空间中启动init进程,在启动其他系统进程
  • Kthreadd进程是idle通过kernel_thread创建,并始终运行在内核空间 ,负责所有内核线程的调度和管理
    • Kthreadd的任务是管理和调度其他内核线程Kernel_thread ,会循环执行一个kthreadd的函数,作用是运行kthreadd_create_list全局链表中维护的kthread
    • 当调用用kernel_thread创建的内核线程会被加入到此链表中,因此所有的内核线程都是直接或者间接的以kthreadd为父进程。

四.小结

在这里插入图片描述前面的文章主要分析了2,3过程。
即BootLoader和Linux内核的启动过程。
下一篇介绍Android初始化语言。
之后继续分析init ,zygote,SystemService进程

五.参考资料

《Android高级进阶》
《深入理解android 卷一》
U-Boot – uboot代码深度解析
Android启动流程简析

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
 本书内容   本书的各个章节及其组织方式如下所示。   第1章“Android系统概述”,概述Android系统方面的内容,包括智能手机平台的发展历程、Android系统的特点、Android的3种开发工作,以及Android的2种不同的开发方式。   第2章“Android系统开发综述”,介绍Android系统开发的综述性内容,包括工具使用、获得代码、编译系统、仿真器运行、SDK使用等。   第3章“Android的Linux内核与驱动程序”,介绍Android内核的特点、Android中使用的专用驱动程序、Android系统可能使用的标准设备驱动。   第4章“Android的底层库和程序”,介绍Android系统的基础程序,以本地程序为主。   第5章“Android的Java虚拟机和Java环境”,这是介于本地和Java层之间的相关内容,主要介绍Android的Java虚拟机Dalvik的基本概念、Android Java程序的环境、JNI的使用方法,以及Java框架的启动流程等。   第6章“Android的GUI系统”,包括Android GUI系统架构、底层的pixelflinger和libui库、Surface系统、Skia和2D图形系统、Android的OpenGL和3D图形系统等内容。   第7章“Android的Audio系统”,主要是音频的输入输出环节,音频系统从驱动程序、本地框架到Java框架都具有内容。   第8章“Android的Video输入输出系统”,介绍Android的Video输入输出系统,包括Overlay系统和Camera系统两个部分,前者只有本地的内容,后者各个层次均有内容。   第9章“Android的多媒体系统”,介绍Android的多媒体系统的核心部分,包括Android中多媒体系统的业务、结构、多媒体系统的核心框架、OpenCore系统结构和使用等内容。   第10章“Android的电话部分”,介绍Android系统在电话方面的功能,Android是智能手机系统,电话是其核心部分。   第11章“Android的连接部分”,主要包括WiFi、蓝牙及定位系统等,这些Android的连接部分也具有从驱动层到Java应用层的结构。   第12章“Android的传感器系统”,传感器系统涉及Android的各个层次,具有完整的结构,相比其他系统,传感器系统的各个层次都比较简单。   第6~12章分模块介绍Android的几个核心系统,主要是本地框架和Java框架方面的内容,兼顾应用程序和驱动层,这是本书的重点。   第13章“Android应用程序概述及框架”,介绍Android应用程序层的基本概念和应用程序框架,这部分内容是Android自下而上的第4个层次,可以基于源代码或者SDK开发,它们之间的差别非常小。   第14章“Android应用程序的主要方面”,介绍Android应用程序层开发的各个方面,基本上是横向内容,包括应用程序的基本控制、各种UI元素的使用、图形API使用3个方面的内容。   第15章“Android应用程序的设计思想”,本章的内容是基于通用的应用程序和GUI程序的通用设计思想,结合Android系统自身的特点,提出一些值得注意的问题和设计方法。   本书读者   本书适应广大的读者群,力求在Android的系统移植、应用程序开发、系统框架改进方面给读者全面的支持。不同的读者在学习本书时,应该使用不同的方法。   Android初级开发者:在本书指引下阅读代码,搭建系统开发环境,对于Android应用程序的开发者,重点关注后3章的内容。   Android中、高级开发者:通过本书的引导,学习系统架构,关注开发要点,并尽量使用手机系统的通用设计思想、软件工程思想、系统工程思想来指导Android系统学习。   嵌入式Linux系统学习者:将Android作为一个集Linux核心和应用层程序于一体的系统进行学习,并可以利用Android的仿真环境运行和调试程序。   读者在学习本书的过程中,应尽量对照本书的框图和手头的Android源代码,这样可以达到事半功倍的效果。本书在重点代码中加上大量的注释,帮助读者阅读,对于非重点的代码,不占用本书的篇幅,读者可以参考开放的源代码。可以采用顺序读和重点读相结合的方式学习本书,顺序读关注系统框架,重点读关注开发要点。   本书作者   本书在编写过程中提炼和综合Android早期开发者的经验、中国大陆Androidin社区的开发成果,以及各位专家的经验和技术,这是本书出版的知识源泉。本书主要由Androidin社区的两名核心技术专家韩超和梁泉领衔规划和编著,韩超统稿。总部设在南加州、专注于Android平台并提供其移动应用开发及解决方案的迈奔无线(mAPPn Inc.)也投入技术和人力参与了本书的工作。   参与本书编写的还有于仕林、张宇、张超等人,赵家维、黄亮、沈桢、徐威特、杨钰等参与了审校工作。   由于时间仓促,可能依然存在一些错误和问题,请读者见谅,欢迎读者讨论和指点。 编辑本段 目 录   第1章 Android系统概述 1   1.1 基础知识 1   1.1.1 Android开发系统的由来 1   1.1.2 移动电话系统开发模式 2   1.1.3 未来移动电话的功能及Android的优势 4   1.2 Android的开发工作 6   1.2.1 Android移植开发 6   1.2.2 Android应用开发 8   1.2.3 Android系统开发 9   1.3 Android的SDK与源代码 10   1.3.1 基于SDK的Android开发 10   1.3.2 基于源代码SDK Android开发 11   第2章 Android系统开发综述 13   2.1 Android的系统架构 13   2.1.1 软件结构 13   2.1.2 Android的工具 16   2.2 Android源代码的开发环境 18   2.2.1 Android源代码的获取和提交 18   2.2.2 Android源代码结构 21   2.2.3 编译 24   2.2.4 系统的运行 25   2.3 Android SDK的开发环境 32   2.3.1 SDK的结构 32   2.3.2 Windows环境SDK开发 33   2.3.3 Linux环境SDK开发 42   第3章 Android的Linux内核与驱动程序 44   3.1 Linux核心与驱动 44   3.2 Android专用驱动 45   3.2.1 Ashmem 45   3.2.2 Binder 45   3.2.3 Logger 46   3.3 Android使用的设备驱动 46   3.3.1 Framebuffer显示驱动 46   3.3.2 Event输入设备驱动 48   3.3.3 v4l2摄像头——视频驱动 50   3.3.4 OSS音频驱动 53   3.3.5 ALSA音频驱动 54   3.3.6 MTD驱动 56   3.3.7 蓝牙驱动 57   3.3.8 Wlan驱动 58   第4章 Android的底层库和程序 60   4.1 底层库和程序的结构 60   4.1.1 本地实现的基本结构 60   4.1.2 增加本地程序和库的方法 61   4.2 标准C/C++库bionic 64   4.3 C语言工具库libcutils 65   4.4 init可执行程序 66   4.5 Shell工具 72   4.6 C++工具库libutils 75   4.6.1 libutils的基本内容 75   4.6.2 Binder 76   4.6.3 libutils中的其他内容 82   4.7 Android的系统进程 85   4.7.1 servicemanager 85   4.7.2 zygote 87   第5章 Android的Java虚拟机和Java环境 88   5.1 Dalvik虚拟机和核心库 88   5.1.1 dex工具库和虚拟机的实现 89   5.1.2 核心库 90   5.1.3 nativehelper库 91   5.2 Android的Java程序环境 91   5.2.1 Java类的层次结构 91   5.2.2 Android Java类的代码 92   5.2.3 Android系统API 92   5.3 JNI的使用 96   5.3.1 JNI的架构和实现方式 97   5.3.2 JNI的实现方式 97   5.3.3 在应用程序中使用JNI 99   5.4 系统服务的Java部分 101   5.4.1 Binder 102   5.4.2 ServiceManager 103   5.4.3 系统进程 103   第6章 Android的GUI系统 106   6.1 Android GUI系统综述 106   6.2 pixelflinger和libui库 108   6.2.1 pixelflinger 108   6.2.2 libui 108   6.2.3 输出/输入与硬件的接口 109   6.3 Surface系统 113   6.3.1 Surface系统本地接口 113   6.3.2 SurfaceFlinger本地代码 115   6.3.3 Surface的Java和JNI代码 119   6.4 Skia和2D图形系统 121   6.4.1 Skia底层库 121   6.4.2 Android图形系统的JNI接口 124   6.4.3 Android的图形包(graphics) 125   6.5 Android的OpenGL系统与3D图形系统 125   6.5.1 OpenGL的本地代码 125   6.5.2 OpenGL的JNI代码 130   6.5.3 OpenGL的Java类 130   第7章 Android的Audio系统 132   7.1 Audio系统综述 132   7.2 Audio系统和上层接口 134   7.2.1 Audio系统的各个层次 134   7.2.2 media库中的Audio框架部分 135   7.2.3 AudioFlinger本地代码 138   7.2.4 Audio系统的JNI代码 140   7.2.5 Audio系统的Java代码 142   7.3 Audio的硬件抽象层 142   7.3.1 Audio硬件抽象层的接口定义 142   7.3.2 AudioFlinger中自带Audio硬件抽象层实现 144   7.3.3 Audio硬件抽象层的真正实现 150   第8章 Android的Video输入输出系统 151   8.1 Video输入输出系统综述 151   8.1.1 Android的Overlay系统结构 152   8.1.2 Android的Camera系统结构 153   8.2 Overlay系统 155   8.2.1 Overlay系统的框架部分定义 156   8.2.2 SurfaceFlinger系统的Overlay部分 158   8.3 Overlay的硬件抽象层 161   8.3.1 Overlay系统硬件抽象层的接口 161   8.3.2 Overlay系统硬件实现框架 164   8.3.3 Overlay系统硬件实现的注意事项 166   8.4 Camera系统与上层接口 169   8.4.1 Camera本地代码框架 169   8.4.2 CameraService 176   8.4.3 Camera的JNI代码 179   8.4.4 Camera的Java代码 182   8.5 Camera的硬件抽象层 182   8.5.1 Camera硬件抽象层的接口定义 182   8.5.2 Camera硬件抽象层的桩实现 184   8.5.3 Camera硬件抽象层的硬件实现 188   第9章 Android的多媒体系统 190   9.1 Android多媒体系统的结构和业务 190   9.1.1 多媒体系统的宏观结构 190   9.1.2 多媒体的各种业务 192   9.2 多媒体系统的各个层次 199   9.2.1 libmedia的框架部分 199   9.2.2 多媒体服务 208   9.2.3 多媒体部分的JNI代码 213   9.2.4 多媒体部分的Java框架代码 215   9.2.5 android.widget.VideoView类 216   9.3 多媒体实现的核心部分OpenCore 216   9.3.1 OpenCore概述 216   9.3.2 OpenCore的层次结构 217   9.3.3 OpenCore的OSCL部分 219   9.3.4 OpenCore的文件格式和编解码部分 221   9.3.5 OpenCore 的Node 222   9.3.6 OpenCore 的功能扩展 223   9.3.7 OpenCore的 Player 226   9.3.8 OpenCore 的Author 236   第10章 Android的电话部分 243   10.1 Android电话部分综述 243   10.2 Modem驱动 243   10.3 本地的RIL代码 245   10.3.1 简介 245   10.3.2 RILD守护进程 246   10.3.3 libril库 247   10.3.4 RIL的实现库Reference RIL 247   10.3.5 Request(请求)流程 248   10.3.6 Response(响应)流程 249   10.3.7 RIL的移植工作 251   10.4 Java框架及应用 251   10.4.1 基本架构 252   10.4.2 呼叫 255   10.4.3 短信 256   10.4.4 数据连接 257   10.4.5 其他框架部分及其他应用 258   第11章 Android的连接部分 259   11.1 WiFi部分 259   11.1.1 WiFi基本架构 259   11.1.2 WiFi本地实现 260   11.1.3 WiFi的Java和JNI 263   11.1.4 Settings中的WiFi设置 265   11.1.5 WiFi工作流程实例 265   11.2 蓝牙部分 267   11.2.1 蓝牙基本架构 268   11.2.2 蓝牙用户空间库bluez 269   11.2.3 bluez适配层 272   11.2.4 蓝牙的JNI和Java部分 272   11.3 GPS和定位部分 280   11.3.1 定位系统基本架构 281   11.3.2 定位系统驱动层 281   11.3.3 GPS本地实现 282   11.3.4 GPS JNI实现 283   11.3.5 定位系统Java实现 284   第12章 Android的传感器系统 286   12.1 传感器系统综述 286   12.2 传感器系统层次结构 288   12.2.1 传感器系统的各个层次 288   12.2.2 传感器系统的JNI 288   12.2.3 传感器系统的Java代码 290   12.3 传感器系统的硬件抽象层 291   12.3.1 传感器系统硬件抽象层的接口定义 291   12.3.2 传感器系统硬件抽象层的示例实现 293   12.3.3 传感器系统硬件抽象层的实现要点 296   12.4 Sensor的使用 296
android技术内幕:系统卷》 前言 第1章 准备工作 /1 1.1 深入认识android /2 1.1.1 android的系统构架 /2 1.1.2 android的初始化流程 /5 1.1.3 各个层次之间的相互关系 /8 1.1.4 android系统开发(移植)和应用开发 /11 1.2 获取和编译android的源码 /13 1.2.1 环境配置 /13 1.2.2 获取android源码 /14 1.2.3 编译android的源码及其工具包 /16 1.2.4 运行android系统 /21 1.3 开发环境搭建 /23 1.3.1 应用开发环境搭建 /23 1.3.2 源码开发环境搭建 /26 1.4 android源码结构 /32 1.5 小结 /33 第2章 android内核机制和结构剖析 /34 2.1 linux与android的关系 /35 .2.1.1 为什么会选择linux /35 2.1.2 android不是linux /35 2.2 android对linux内核的改动 /37 2.2.1 goldfish /37 2.2.2 yaffs2 /38 2.2.3 蓝牙 /39 2.2.4 调度器(scheduler)/39 2.2.5 android新增的驱动 /40 2.2.6 电源管理 /41 2.2.7 杂项 /41 2.3 android对linux内核的增强 /42 2.3.1 alarm(硬件时钟)/43 2.3.2 ashmem(匿名内存共享)/46 2.3.3 low memory killer(低内存管理)/52 2.3.4 logger(日志设备)/56 2.3.5 android pmem /65 2.3.6 switch /79 2.3.7 timed gpio /88 2.3.8 android ram console /94 2.4 小结 /99 第3章 android的ipc机制--binder /100 3.1 binder概述 /101 3.1.1 为什么选择binder /101 3.1.2 初识binder /102 3.2 binder驱动的原理和实现 /102 3.2.1 binder驱动的原理 /102 3.2.2 binder驱动的实现 /103 3.3 binder的构架与实现 /132 3.3.1 binder的系统构架 /132 3.3.2 binder的机制和原理 /133 3.4 小结 /150 第4章 电源管理 /151 4.1 电源管理概述 /152 4.2 电源管理结构 /152 4.3 android的电源管理机制 /153 4.4 android电源管理机制的实现 /154 4.5 小结 /187 第5章 驱动的工作原理及实现机制 /188 5.1 显示驱动(framebuffer)/189 5.1.1 framebuffer的工作原理 /189 5.1.2 framebuffer的构架 /190 5.1.3 framebuffer驱动的实现机制 /190 5.2 视频驱动(v4l和v4l2)/201 5.2.1 v4l2介绍 /201 5.2.2 v4l2的原理和构架 /201 5.2.3 v4l2的实现 /202 5.3 音频驱动(oss和alsa)/208 5.3.1 oss与alsa介绍 /208 5.3.2 oss的构架与实现 /209 5.3.3 alsa的构架与实现 /213 5.4 mtd驱动 /214 5.4.1 mtd驱动的功能 /214 5.4.2 mtd驱动的构架 /215 5.4.3 mtd驱动的原理及实现 /215 5.5 event输入设备驱动 /223 5.5.1 input的系统构架 /223 5.5.2 event输入驱动的构架 /224 5.5.3 event输入驱动的原理 /224 5.5.4 event输入驱动的实现 /225 5.6 蓝牙驱动(bluetooth)/235 5.6.1 bluetooth驱动的构架 /235 5.6.2 bluez的原理及实现 /237 5.7 wlan驱动(wi-fi)/244 5.7.1 wlan构架 /244 5.7.2 wi-fi驱动的实现原理 /245 5.8 小结 /245 第6章 原生库的原理及实现 /246 6.1 系统c库(bionic libc)/247 6.1.1 bionic libc功能概述 /247 6.1.2 bionic libc实现原理 /248 6.2 功能库 /258 6.2.1 webkit构架与实现 /258 6.2.2 多媒体框架与实现 /275 6.2.3 android sqlite框架及原理
书名:《Android底层开发技术实战详解——内核、移植和驱动》(电子工业出版社.王振丽)。本书从底层原理开始讲起,结合真实的案例向读者详细介绍了android内核、移植和驱动开发的整个流程。全书分为19章,依次讲解驱动移植的必要性,何为hal层深入分析,goldfish、msm、map内核和驱动解析,显示系统、输入系统、振动器系统、音频系统、视频输出系统的驱动,openmax多媒体、多媒体插件框架,传感器、照相机、wi-fi、蓝牙、gps和电话系统等。在每一章中,重点介绍了与Android驱动开发相关的底层知识,并对Android源码进行了剖析。 本书适合Android研发人员及Android爱好者学习,也可以作为相关培训学校和大专院校相关专业的教学用书。 全书压缩打包成3部分,这是第3部分。 目录: 第1章 Android底层开发基础 1 1.1 什么是驱动 1 1.1.1 驱动程序的魅力 1 1.1.2 电脑中的驱动 2 1.1.3 手机中的驱动程序 2 1.2 开源还是不开源的问题 3 1.2.1 雾里看花的开源 3 1.2.2 从为什么选择java谈为什么不开源驱动程序 3 1.2.3 对驱动开发者来说是一把双刃剑 4 1.3 Android和Linux 4 1.3.1 Linux简介 5 1.3.2 Android和Linux的关系 5 1.4 简析Linux内核 8 1.4.1 内核的体系结构 8 1.4.2 和Android密切相关的Linux内核知识 10 1.5 分析Linux内核源代码很有必要 14 1.5.1 源代码目录结构 14 1.5.2 浏览源代码的工具 16 1.5.3 为什么用汇编语言编写内核代码 17 1.5.4 Linux内核的显著特性 18 1.5.5 学习Linux内核的方法 26 第2章 分析Android源代码 31 2.1 搭建Linux开发环境和工具 31 2.1.1 搭建Linux开发环境 31 2.1.2 设置环境变量 32 2.1.3 安装编译工具 32 2.2 获取Android源代码 33 2.3 分析并编译Android源代码 35 2.3.1 Android源代码的结构 35 2.3.2 编译Android源代码 40 2.3.3 运行Android源代码 42 2.3.4 实践演练——演示编译Android程序的两种方法 43 2.4 编译Android kernel 47 2.4.1 获取goldfish内核代码 47 2.4.2 获取msm内核代码 50 2.4.3 获取omap内核代码 50 2.4.4 编译Android的Linux内核 50 2.5 运行模拟器 52 2.5.1 Linux环境下运行模拟器的方法 53 2.5.2 模拟器辅助工具——adb 54 第3章 驱动需要移植 57 3.1 驱动开发需要做的工作 57 3.2 Android移植 59 3.2.1 移植的任务 60 3.2.2 移植的内容 60 3.2.3 驱动开发的任务 61 3.3 Android对Linux的改造 61 3.3.1 Android对Linux内核文件的改动 62 3.3.2 为Android构建 Linux的操作系统 63 3.4 内核空间和用户空间接口是一个媒介 64 3.4.1 内核空间和用户空间的相互作用 64 3.4.2 系统和硬件之间的交互 64 3.4.3 使用relay实现内核到用户空间的数据传输 66 3.5 三类驱动程序 70 3.5.1 字符设备驱动程序 70 3.5.2 块设备驱动程序 79 3.5.3 网络设备驱动程序 82 第4章 hal层深入分析 84 4.1 认识hal层 84 4.1.1 hal层的发展 84 4.1.2 过去和现在的区别 86 4.2 分析hal层源代码 86 4.2.1 分析hal moudle 86 4.2.2 分析mokoid工程 89 4.3 总结hal层的使用方法 98 4.4 传感器在hal层的表现 101 4.4.1 hal层的sensor代码 102 4.4.2 总结sensor编程的流程 104 4.4.3 分析sensor源代码看Android api 与硬件平台的衔接 104 4.5 移植总结 116 4.5.1 移植各个Android部件的方式 116 4.5.2 移植技巧之一——不得不说的辅助工作 117 第5章 goldfish下的驱动解析 125 5.1 staging驱动 125 5.1.1 staging驱动概述 125 5.1.2 binder驱动程序 126 5.1.3 logger驱动程序 135 5.1.4 lowmemorykiller组件 136 5.1.5 timed output驱动程序 137 5.1.6 timed gpio驱动程序 139 5.1.7 ram console驱动程序 139 5.2 wakelock和early_suspend 140 5.2.1 wakelock和early_suspend的原理 140 5.2.2 Android休眠 141 5.2.3 Android唤醒 144 5.3 ashmem驱动程序 145 5.4 pmem驱动程序 148 5.5 alarm驱动程序 149 5.5.1 alarm简析 149 5.5.2 alarm驱动程序的实现 150 5.6 usb gadget驱动程序151 5.7 Android paranoid驱动程序153 5.8 goldfish设备驱动154 5.8.1 framebuffer驱动155 5.8.2 键盘驱动159 5.8.3 实时时钟驱动程序160 5.8.4 tty终端驱动程序161 5.8.5 nandflash驱动程序162 5.8.6 mmc驱动程序162 5.8.7 电池驱动程序162 第6章 msm内核和驱动解析164 6.1 msm基础164 6.1.1 常见msm处理器产品164 6.1.2 snapdragon内核介绍165 6.2 移植msm内核简介166 6.3 移植msm168 6.3.1 makefile文件168 6.3.2 驱动和组件170 6.3.3 设备驱动172 6.3.4 高通特有的组件174 第7章 omap内核和驱动解析177 7.1 omap基础177 7.1.1 omap简析177 7.1.2 常见omap处理器产品177 7.1.3 开发平台178 7.2 omap内核178 7.3 移植omap体系结构180 7.3.1 移植omap平台180 7.3.2 移植omap处理器183 7.4 移植Android专用驱动和组件188 7.5 omap的设备驱动190 第8章 显示系统驱动应用195 8.1 显示系统介绍195 8.1.1 Android的版本195 8.1.2 不同版本的显示系统195 8.2 移植和调试前的准备196 8.2.1 framebuffer驱动程序196 8.2.2 硬件抽象层198 8.3 实现显示系统的驱动程序210 8.3.1 goldfish中的framebuffer驱动程序210 8.3.2 使用gralloc模块的驱动程序214 8.4 msm高通处理器中的显示驱动实现224 8.4.1 msm中的framebuffer驱动程序225 8.4.2 msm中的gralloc驱动程序227 8.5 omap处理器中的显示驱动实现235 第9章 输入系统驱动应用239 9.1 输入系统介绍239 9.1.1 Android输入系统结构元素介绍239 9.1.2 移植Android输入系统时的工作240 9.2 input(输入)驱动241 9.3 模拟器的输入驱动256 9.4 msm高通处理器中的输入驱动实现257 9.4.1 触摸屏驱动257 9.4.2 按键和轨迹球驱动264 9.5 omap处理器平台中的输入驱动实现266 9.5.1 触摸屏驱动267 9.5.2 键盘驱动267 第10章 振动器系统驱动269 10.1 振动器系统结构269 10.1.1 硬件抽象层271 10.1.2 jni框架部分272 10.2 开始移植273 10.2.1 移植振动器驱动程序273 10.2.2 实现硬件抽象层274 10.3 在msm平台实现振动器驱动275 第11章 音频系统驱动279 11.1 音频系统结构279 11.2 分析音频系统的层次280 11.2.1 层次说明280 11.2.2 media库中的audio框架281 11.2.3 本地代码284 11.2.4 jni代码288 11.2.5 java代码289 11.3 移植audio系统的必备技术289 11.3.1 移植audio系统所要做的工作289 11.3.2 分析硬件抽象层290 11.3.3 分析audioflinger中的audio硬件抽象层的实现291 11.4 真正实现audio硬件抽象层298 11.5 msm平台实现audio驱动系统298 11.5.1 实现audio驱动程序298 11.5.2 实现硬件抽象层299 11.6 oss平台实现audio驱动系统304 11.6.1 oss驱动程序介绍304 11.6.2 mixer305 11.7 alsa平台实现audio系统312 11.7.1 注册音频设备和音频驱动312 11.7.2 在Android中使用alsa声卡313 11.7.3 在omap平台移植Android的alsa声卡驱动322 第12章 视频输出系统驱动326 12.1 视频输出系统结构326 12.2 需要移植的部分328 12.3 分析硬件抽象层328 12.3.1 overlay系统硬件抽象层的接口328 12.3.2 实现overlay系统的硬件抽象层331 12.3.3 实现接口332 12.4 实现overlay硬件抽象层333 12.5 在omap平台实现overlay系统335 12.5.1 实现输出视频驱动程序335 12.5.2 实现overlay硬件抽象层337 12.6 系统层调用overlay hal的架构342 12.6.1 调用overlay hal的架构的流程342 12.6.2 s3c6410 Android overlay的测试代码346 第13章 openmax多媒体框架349 13.1 openmax基本层次结构349 13.2 分析openmax框架构成350 13.2.1 openmax总体层次结构350 13.2.2 openmax il层的结构351 13.2.3 Android中的openmax354 13.3 实现openmax il层接口354 13.3.1 openmax il层的接口354 13.3.2 在openmax il层中需要做什么361 13.3.3 研究Android中的openmax适配层361 13.4 在omap平台实现openmax il363 13.4.1 实现文件364 13.4.2 分析ti openmax il的核心365 13.4.3 实现ti openmax il组件实例368 第14章 多媒体插件框架373 14.1 Android多媒体插件373 14.2 需要移植的内容374 14.3 opencore引擎375 14.3.1 opencore层次结构375 14.3.2 opencore代码结构376 14.3.3 opencore编译结构377 14.3.4 opencore oscl381 14.3.5 实现opencore中的openmax部分383 14.3.6 opencore的扩展398 14.4 stagefright引擎404 14.4.1 stagefright代码结构404 14.4.2 stagefright实现openmax接口405 14.4.3 video buffer传输流程409 第15章 传感器系统415 15.1 传感器系统的结构415 15.2 需要移植的内容417 15.2.1 移植驱动程序417 15.2.2 移植硬件抽象层418 15.2.3 实现上层部分419 15.3 在模拟器中实现传感器424 第16章 照相机系统430 16.1 camera系统的结构430 16.2 需要移植的内容433 16.3 移植和调试433 16.3.1 v4l2驱动程序433 16.3.2 硬件抽象层441 16.4 实现camera系统的硬件抽象层446 16.4.1 java程序部分446 16.4.2 camera的java本地调用部分447 16.4.3 camera的本地库libui.so448 16.4.4 camera服务libcameraservice.so449 16.5 msm平台实现camera系统454 16.6 omap平台实现camera系统457 第17章 wi-fi系统、蓝牙系统和gps系统459 17.1 wi-fi系统459 17.1.1 wi-fi系统的结构459 17.1.2 需要移植的内容461 17.1.3 移植和调试461 17.1.4 omap平台实现wi-fi469 17.1.5 配置wi-fi的流程471 17.1.6 具体演练——在Android下实现ethernet473 17.2 蓝牙系统475 17.2.1 蓝牙系统的结构475 17.2.2 需要移植的内容477 17.2.3 具体移植478 17.2.4 msm平台的蓝牙驱动480 17.3 定位系统482 17.3.1 定位系统的结构483 17.3.2 需要移植的内容484 17.3.3 移植和调试484 第18章 电话系统498 18.1 电话系统基础498 18.1.1 电话系统简介498 18.1.2 电话系统结构500 18.2 需要移植的内容501 18.3 移植和调试502 18.3.1 驱动程序502 18.3.2 ril接口504 18.4 电话系统实现流程分析507 18.4.1 初始启动流程507 18.4.2 request流程509 18.4.3 response流程512 第19章 其他系统514 19.1 alarm警报器系统514 19.1.1 alarm系统的结构514 19.1.2 需要移植的内容515 19.1.3 移植和调试516 19.1.4 模拟器环境的具体实现518 19.1.5 msm平台实现alarm518 19.2 lights光系统519 19.2.1 lights光系统的结构520 19.2.2 需要移植的内容521 19.2.3 移植和调试521 19.2.4 msm平台实现光系统523 19.3 battery电池系统524 19.3.1 battery系统的结构524 19.3.2 需要移植的内容526 19.3.3 移植和调试526 19.3.4 在模拟器中实现电池系统529
书名:《Android底层开发技术实战详解——内核、移植和驱动》(电子工业出版社.王振丽)。本书从底层原理开始讲起,结合真实的案例向读者详细介绍了android内核、移植和驱动开发的整个流程。全书分为19章,依次讲解驱动移植的必要性,何为hal层深入分析,goldfish、msm、map内核和驱动解析,显示系统、输入系统、振动器系统、音频系统、视频输出系统的驱动,openmax多媒体、多媒体插件框架,传感器、照相机、wi-fi、蓝牙、gps和电话系统等。在每一章中,重点介绍了与Android驱动开发相关的底层知识,并对Android源码进行了剖析。 本书适合Android研发人员及Android爱好者学习,也可以作为相关培训学校和大专院校相关专业的教学用书。 全书压缩打包成3部分,这是第1部分。 目录: 第1章 Android底层开发基础 1 1.1 什么是驱动 1 1.1.1 驱动程序的魅力 1 1.1.2 电脑中的驱动 2 1.1.3 手机中的驱动程序 2 1.2 开源还是不开源的问题 3 1.2.1 雾里看花的开源 3 1.2.2 从为什么选择java谈为什么不开源驱动程序 3 1.2.3 对驱动开发者来说是一把双刃剑 4 1.3 Android和Linux 4 1.3.1 Linux简介 5 1.3.2 Android和Linux的关系 5 1.4 简析Linux内核 8 1.4.1 内核的体系结构 8 1.4.2 和Android密切相关的Linux内核知识 10 1.5 分析Linux内核源代码很有必要 14 1.5.1 源代码目录结构 14 1.5.2 浏览源代码的工具 16 1.5.3 为什么用汇编语言编写内核代码 17 1.5.4 Linux内核的显著特性 18 1.5.5 学习Linux内核的方法 26 第2章 分析Android源代码 31 2.1 搭建Linux开发环境和工具 31 2.1.1 搭建Linux开发环境 31 2.1.2 设置环境变量 32 2.1.3 安装编译工具 32 2.2 获取Android源代码 33 2.3 分析并编译Android源代码 35 2.3.1 Android源代码的结构 35 2.3.2 编译Android源代码 40 2.3.3 运行Android源代码 42 2.3.4 实践演练——演示编译Android程序的两种方法 43 2.4 编译Android kernel 47 2.4.1 获取goldfish内核代码 47 2.4.2 获取msm内核代码 50 2.4.3 获取omap内核代码 50 2.4.4 编译Android的Linux内核 50 2.5 运行模拟器 52 2.5.1 Linux环境下运行模拟器的方法 53 2.5.2 模拟器辅助工具——adb 54 第3章 驱动需要移植 57 3.1 驱动开发需要做的工作 57 3.2 Android移植 59 3.2.1 移植的任务 60 3.2.2 移植的内容 60 3.2.3 驱动开发的任务 61 3.3 Android对Linux的改造 61 3.3.1 Android对Linux内核文件的改动 62 3.3.2 为Android构建 Linux的操作系统 63 3.4 内核空间和用户空间接口是一个媒介 64 3.4.1 内核空间和用户空间的相互作用 64 3.4.2 系统和硬件之间的交互 64 3.4.3 使用relay实现内核到用户空间的数据传输 66 3.5 三类驱动程序 70 3.5.1 字符设备驱动程序 70 3.5.2 块设备驱动程序 79 3.5.3 网络设备驱动程序 82 第4章 hal层深入分析 84 4.1 认识hal层 84 4.1.1 hal层的发展 84 4.1.2 过去和现在的区别 86 4.2 分析hal层源代码 86 4.2.1 分析hal moudle 86 4.2.2 分析mokoid工程 89 4.3 总结hal层的使用方法 98 4.4 传感器在hal层的表现 101 4.4.1 hal层的sensor代码 102 4.4.2 总结sensor编程的流程 104 4.4.3 分析sensor源代码看Android api 与硬件平台的衔接 104 4.5 移植总结 116 4.5.1 移植各个Android部件的方式 116 4.5.2 移植技巧之一——不得不说的辅助工作 117 第5章 goldfish下的驱动解析 125 5.1 staging驱动 125 5.1.1 staging驱动概述 125 5.1.2 binder驱动程序 126 5.1.3 logger驱动程序 135 5.1.4 lowmemorykiller组件 136 5.1.5 timed output驱动程序 137 5.1.6 timed gpio驱动程序 139 5.1.7 ram console驱动程序 139 5.2 wakelock和early_suspend 140 5.2.1 wakelock和early_suspend的原理 140 5.2.2 Android休眠 141 5.2.3 Android唤醒 144 5.3 ashmem驱动程序 145 5.4 pmem驱动程序 148 5.5 alarm驱动程序 149 5.5.1 alarm简析 149 5.5.2 alarm驱动程序的实现 150 5.6 usb gadget驱动程序151 5.7 Android paranoid驱动程序153 5.8 goldfish设备驱动154 5.8.1 framebuffer驱动155 5.8.2 键盘驱动159 5.8.3 实时时钟驱动程序160 5.8.4 tty终端驱动程序161 5.8.5 nandflash驱动程序162 5.8.6 mmc驱动程序162 5.8.7 电池驱动程序162 第6章 msm内核和驱动解析164 6.1 msm基础164 6.1.1 常见msm处理器产品164 6.1.2 snapdragon内核介绍165 6.2 移植msm内核简介166 6.3 移植msm168 6.3.1 makefile文件168 6.3.2 驱动和组件170 6.3.3 设备驱动172 6.3.4 高通特有的组件174 第7章 omap内核和驱动解析177 7.1 omap基础177 7.1.1 omap简析177 7.1.2 常见omap处理器产品177 7.1.3 开发平台178 7.2 omap内核178 7.3 移植omap体系结构180 7.3.1 移植omap平台180 7.3.2 移植omap处理器183 7.4 移植Android专用驱动和组件188 7.5 omap的设备驱动190 第8章 显示系统驱动应用195 8.1 显示系统介绍195 8.1.1 Android的版本195 8.1.2 不同版本的显示系统195 8.2 移植和调试前的准备196 8.2.1 framebuffer驱动程序196 8.2.2 硬件抽象层198 8.3 实现显示系统的驱动程序210 8.3.1 goldfish中的framebuffer驱动程序210 8.3.2 使用gralloc模块的驱动程序214 8.4 msm高通处理器中的显示驱动实现224 8.4.1 msm中的framebuffer驱动程序225 8.4.2 msm中的gralloc驱动程序227 8.5 omap处理器中的显示驱动实现235 第9章 输入系统驱动应用239 9.1 输入系统介绍239 9.1.1 Android输入系统结构元素介绍239 9.1.2 移植Android输入系统时的工作240 9.2 input(输入)驱动241 9.3 模拟器的输入驱动256 9.4 msm高通处理器中的输入驱动实现257 9.4.1 触摸屏驱动257 9.4.2 按键和轨迹球驱动264 9.5 omap处理器平台中的输入驱动实现266 9.5.1 触摸屏驱动267 9.5.2 键盘驱动267 第10章 振动器系统驱动269 10.1 振动器系统结构269 10.1.1 硬件抽象层271 10.1.2 jni框架部分272 10.2 开始移植273 10.2.1 移植振动器驱动程序273 10.2.2 实现硬件抽象层274 10.3 在msm平台实现振动器驱动275 第11章 音频系统驱动279 11.1 音频系统结构279 11.2 分析音频系统的层次280 11.2.1 层次说明280 11.2.2 media库中的audio框架281 11.2.3 本地代码284 11.2.4 jni代码288 11.2.5 java代码289 11.3 移植audio系统的必备技术289 11.3.1 移植audio系统所要做的工作289 11.3.2 分析硬件抽象层290 11.3.3 分析audioflinger中的audio硬件抽象层的实现291 11.4 真正实现audio硬件抽象层298 11.5 msm平台实现audio驱动系统298 11.5.1 实现audio驱动程序298 11.5.2 实现硬件抽象层299 11.6 oss平台实现audio驱动系统304 11.6.1 oss驱动程序介绍304 11.6.2 mixer305 11.7 alsa平台实现audio系统312 11.7.1 注册音频设备和音频驱动312 11.7.2 在Android中使用alsa声卡313 11.7.3 在omap平台移植Android的alsa声卡驱动322 第12章 视频输出系统驱动326 12.1 视频输出系统结构326 12.2 需要移植的部分328 12.3 分析硬件抽象层328 12.3.1 overlay系统硬件抽象层的接口328 12.3.2 实现overlay系统的硬件抽象层331 12.3.3 实现接口332 12.4 实现overlay硬件抽象层333 12.5 在omap平台实现overlay系统335 12.5.1 实现输出视频驱动程序335 12.5.2 实现overlay硬件抽象层337 12.6 系统层调用overlay hal的架构342 12.6.1 调用overlay hal的架构的流程342 12.6.2 s3c6410 Android overlay的测试代码346 第13章 openmax多媒体框架349 13.1 openmax基本层次结构349 13.2 分析openmax框架构成350 13.2.1 openmax总体层次结构350 13.2.2 openmax il层的结构351 13.2.3 Android中的openmax354 13.3 实现openmax il层接口354 13.3.1 openmax il层的接口354 13.3.2 在openmax il层中需要做什么361 13.3.3 研究Android中的openmax适配层361 13.4 在omap平台实现openmax il363 13.4.1 实现文件364 13.4.2 分析ti openmax il的核心365 13.4.3 实现ti openmax il组件实例368 第14章 多媒体插件框架373 14.1 Android多媒体插件373 14.2 需要移植的内容374 14.3 opencore引擎375 14.3.1 opencore层次结构375 14.3.2 opencore代码结构376 14.3.3 opencore编译结构377 14.3.4 opencore oscl381 14.3.5 实现opencore中的openmax部分383 14.3.6 opencore的扩展398 14.4 stagefright引擎404 14.4.1 stagefright代码结构404 14.4.2 stagefright实现openmax接口405 14.4.3 video buffer传输流程409 第15章 传感器系统415 15.1 传感器系统的结构415 15.2 需要移植的内容417 15.2.1 移植驱动程序417 15.2.2 移植硬件抽象层418 15.2.3 实现上层部分419 15.3 在模拟器中实现传感器424 第16章 照相机系统430 16.1 camera系统的结构430 16.2 需要移植的内容433 16.3 移植和调试433 16.3.1 v4l2驱动程序433 16.3.2 硬件抽象层441 16.4 实现camera系统的硬件抽象层446 16.4.1 java程序部分446 16.4.2 camera的java本地调用部分447 16.4.3 camera的本地库libui.so448 16.4.4 camera服务libcameraservice.so449 16.5 msm平台实现camera系统454 16.6 omap平台实现camera系统457 第17章 wi-fi系统、蓝牙系统和gps系统459 17.1 wi-fi系统459 17.1.1 wi-fi系统的结构459 17.1.2 需要移植的内容461 17.1.3 移植和调试461 17.1.4 omap平台实现wi-fi469 17.1.5 配置wi-fi的流程471 17.1.6 具体演练——在Android下实现ethernet473 17.2 蓝牙系统475 17.2.1 蓝牙系统的结构475 17.2.2 需要移植的内容477 17.2.3 具体移植478 17.2.4 msm平台的蓝牙驱动480 17.3 定位系统482 17.3.1 定位系统的结构483 17.3.2 需要移植的内容484 17.3.3 移植和调试484 第18章 电话系统498 18.1 电话系统基础498 18.1.1 电话系统简介498 18.1.2 电话系统结构500 18.2 需要移植的内容501 18.3 移植和调试502 18.3.1 驱动程序502 18.3.2 ril接口504 18.4 电话系统实现流程分析507 18.4.1 初始启动流程507 18.4.2 request流程509 18.4.3 response流程512 第19章 其他系统514 19.1 alarm警报器系统514 19.1.1 alarm系统的结构514 19.1.2 需要移植的内容515 19.1.3 移植和调试516 19.1.4 模拟器环境的具体实现518 19.1.5 msm平台实现alarm518 19.2 lights光系统519 19.2.1 lights光系统的结构520 19.2.2 需要移植的内容521 19.2.3 移植和调试521 19.2.4 msm平台实现光系统523 19.3 battery电池系统524 19.3.1 battery系统的结构524 19.3.2 需要移植的内容526 19.3.3 移植和调试526 19.3.4 在模拟器中实现电池系统529

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值