***************************************************************************************************************************
作者: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中,我们可以看到如下的定义:
这里只分析红色圈中的部分,其他部分的代码,请自行分析,都是大同小异啦。进入do_chown函数中,可以看到如下的代码(在/system/core/init/Builtins.c):
进入深入进去发现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):
看到了吗,上面红色圈中的部分的定义是跟Andriod中的定义是一样的,都是:#define __NR_chown32 (__NR_SYSCALL_BASE+212) 这个偏移地址。我们再来看看syscall调用的定义是在哪里的呢。最终调用的是:arch\arm\kernel\entry-common.S下的syscall函数,如下图所示:
同时syscall的函数代码如下所示:
最终会将#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的调用方法,可以到网络上去搜索,我这里就不详细的解释了。