[置顶] 基于android2.3.5系统:开天辟地Android启动机制[四]

***************************************************************************************************************************
作者:EasyWave                                                                                 时间:2013.02.08

类别:Android系统源码分析                                                              声明:转载,请保留链接

注意:如有错误,欢迎指正。这些是我学习的日志文章......

***************************************************************************************************************************

在我的博文基于android2.3.5学习之:开天辟地Android启动机制[三]中,详细的介绍了ueventd的解析机制,在分析andriod2.3.5中的action_list、action_queue、service_list,之前,还是先来详细介绍在Andriod是如何调用内核中的一些函数,比如:chown以及chroot等等。Andriod中的三大链表如下图所示:

详细的介绍,将留在后面的文章中详细解释,因为,在这之前,需要先了解下linux中的syscall,就是系统调用。以chown命令为例,详细的解析Android中是如何执行chown这个命令的,在system/core/init/keywords.h中,我们可以看到如下的定义:

[置顶] 基于android2.3.5系统:开天辟地Android启动机制[四]_第1张图片

这里只分析红色圈中的部分,其他部分的代码,请自行分析,都是大同小异啦。进入do_chown函数中,可以看到如下的代码(在/system/core/init/Builtins.c):

[置顶] 基于android2.3.5系统:开天辟地Android启动机制[四]_第2张图片

进入深入进去发现chown是调用bionic\libc\arch-arm\syscalls下的chown.s文件,当然如果是其它的平台,那么路径是不一样的,这里只讨论ARM架构下的代码,如下图所示:

看到了吗,最终是调用__NR_chown32这个标号指定的函数地址,它是在哪里调用的呢,我们可以从上面的#include <sys/linux-syscalls.h>中找到答案。如下代码:

/* auto-generated by gensyscalls.py, do not touch */
#ifndef _BIONIC_LINUX_SYSCALLS_H_

#if !defined __ASM_ARM_UNISTD_H && !defined __ASM_I386_UNISTD_H
#if defined __arm__ && !defined __ARM_EABI__ && !defined __thumb__
  #  define __NR_SYSCALL_BASE  0x900000
  #else
  #  define  __NR_SYSCALL_BASE  0
  #endif

#define __NR_exit                         (__NR_SYSCALL_BASE + 1)
#define __NR_fork                         (__NR_SYSCALL_BASE + 2)
#define __NR_clone                        (__NR_SYSCALL_BASE + 120)
......
#define __NR_chown32                      (__NR_SYSCALL_BASE + 212)
#define __NR_lchown32                     (__NR_SYSCALL_BASE + 198)
......
#ifdef __arm__
#define __NR_exit_group                   (__NR_SYSCALL_BASE + 248)
#define __NR_waitid                       (__NR_SYSCALL_BASE + 280)
#define __NR_vfork                        (__NR_SYSCALL_BASE + 190)
#define __NR_openat                       (__NR_SYSCALL_BASE + 322)
......
#define __NR_ARM_set_tls                  (__NR_SYSCALL_BASE + 983045)
#define __NR_ARM_cacheflush               (__NR_SYSCALL_BASE + 983042)
#endif


#endif

#endif /* _BIONIC_LINUX_SYSCALLS_H_

从上面的代码中,我们看到#define __NR_chown32                      (__NR_SYSCALL_BASE + 212) 这行代码,不错,这个就是我们需要了解的。

在bionic\libc\kernel\arch-arm\asm中的Unistd.h文件中,我们也可以看到如下的代码,注意,这个是linux内核相关的。如下所示:

红色圈中的部分,看出来什么名堂没有呢,当然它们都是指向__NR_SYSCALL_BASE + 212 这个偏移地址,而在linux系统中定义如下(arch\arm\include\asm\Unistd.h):

[置顶] 基于android2.3.5系统:开天辟地Android启动机制[四]_第3张图片

[置顶] 基于android2.3.5系统:开天辟地Android启动机制[四]_第4张图片

看到了吗,上面红色圈中的部分的定义是跟Andriod中的定义是一样的,都是:#define __NR_chown32   (__NR_SYSCALL_BASE+212) 这个偏移地址。我们再来看看syscall调用的定义是在哪里的呢。最终调用的是:arch\arm\kernel\entry-common.S下的syscall函数,如下图所示:

[置顶] 基于android2.3.5系统:开天辟地Android启动机制[四]_第5张图片

同时syscall的函数代码如下所示:

[置顶] 基于android2.3.5系统:开天辟地Android启动机制[四]_第6张图片

最终会将#include "calls.S"文件加入进来,而calls.S文件主要是定义了一个sys_call_table表格而已,如下所示:

/*
 *  linux/arch/arm/kernel/calls.S
 *
 *  Copyright (C) 1995-2005 Russell King
 *
 * 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.
 *
 *  This file is included thrice in entry-common.S
 */
/* 0 */		CALL(sys_restart_syscall)
		CALL(sys_exit)
		CALL(sys_fork_wrapper)
		CALL(sys_read)
		CALL(sys_write)
/* 5 */		CALL(sys_open)
		CALL(sys_close)
		CALL(sys_ni_syscall)		/* was sys_waitpid */
		CALL(sys_creat)
		CALL(sys_link)
......
/* 210 */	CALL(sys_setresgid)
		CALL(sys_getresgid)
		CALL(sys_chown) //212 : 调用sys_chown函数
		CALL(sys_setuid)
		CALL(sys_setgid)
......
/* 300 */	CALL(sys_semctl)
		CALL(sys_msgsnd)
		CALL(sys_msgrcv)
		CALL(sys_msgget)
		CALL(sys_msgctl)
/* 305 */	CALL(sys_shmat)
		CALL(sys_shmdt)
		CALL(sys_shmget)
		CALL(sys_shmctl)
		CALL(sys_add_key)
/* 310 */	CALL(sys_request_key)
		CALL(sys_keyctl)
		CALL(ABI(sys_semtimedop, sys_oabi_semtimedop))
/* vserver */	CALL(sys_ni_syscall)
		CALL(sys_ioprio_set)
/* 315 */	CALL(sys_ioprio_get)
		CALL(sys_inotify_init)
		CALL(sys_inotify_add_watch)
		CALL(sys_inotify_rm_watch)
		CALL(sys_mbind)
/* 320 */	CALL(sys_get_mempolicy)
		CALL(sys_set_mempolicy)
		CALL(sys_openat)
		CALL(sys_mkdirat)
		CALL(sys_mknodat)
......
		CALL(sys_preadv)
		CALL(sys_pwritev)
		CALL(sys_rt_tgsigqueueinfo)
		CALL(sys_perf_event_open)
/* 365 */	CALL(sys_recvmmsg)
#ifndef syscalls_counted
.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
#define syscalls_counted
#endif
.rept syscalls_padding
		CALL(sys_ni_syscall)
.endr

 

       至此,我们了解了Anriod系统中的chown命令是通过syscall来调用linux内核中的系统函数chown函数,现在应该明白了吧,其他的命令基本一致,其实在busybox中也是采用内似的方法来做的。具体关于syscall的调用方法,可以到网络上去搜索,我这里就不详细的解释了。

 

你可能感兴趣的:([置顶] 基于android2.3.5系统:开天辟地Android启动机制[四])