您的位置:首页 > 移动开发 > Android开发

[zz] 浅析android下propt怎么通过init进程传递和glibc库函数的添加

2009-10-22 16:48 453 查看
http://blog.chinaunix.net/u1/38994/showart_1170108.html


adb shell

#
printenv

#
getprop  获取所有java层propt

#
setprop wifi.
interface eth0 设置"wifi.interface"
对应的数值为eth0

环境变量ANDROID_PROPERTY_WORKSPACE=
9,
32768

所以fd=
9,
大小size=
32768

system
/
init/
init.
c=
>
main(
)
进程将调用

=
>
property_init

=
>
init_property_area

void
property_init(
void
)

{

//ashmem_area - android shared memory area是android共享内容存的一种方式

//打开ashmem设备,申请一段size大小的kernel空间内存,不去释放,以便供所有用户空间进程共享.

//内核驱动位于linux/mm/ashmem.c文件[luther.gliethttp].

init_property_area(
)
;

//#define PROP_PATH_RAMDISK_DEFAULT  "/default.prop"

//从ramdisk中读取default.prop文件,将文件中的所有java环境中使用到的propt释放到

//这个共享内存中.

load_properties_from_file(
PROP_PATH_RAMDISK_DEFAULT)
;

}

当然init程序在后边仍然可以调用property_set(
)
来设置新的propt,
比如:property_set(
"ro.hardware"
,
hardware)
;

ok,
这个公用户空间程序共享的内核空间内存区域ashmem已经申请成功,
并且填入了所有我们需要的数据,
不论是从ramdisk解压出来的

default
.
prop文件直接读出的propt,
还是手工调用property_set(
)
设置的propt,
都已经放入了内存中.

接下来init继续运行,
注册环境变量ANDROID_PROPERTY_WORKSPACE:

=
>
service_start

=
>

get_property_workspace(
&
fd,
&
sz)
;

//从init进程的空闲fdt中dup一个空闲的fd,比如空闲的fd=9

//执行一次dup,那么打开init的引用计数就会加1,这样保证不被无故释放[luther.gliethttp].

sprintf
(
tmp,
"%d,%d"
,
dup(
fd)
,
sz)
;
//比如ANDROID_PROPERTY_WORKSPACE=9,32768

add_environment(
"ANDROID_PROPERTY_WORKSPACE"
,
tmp)
;
//添加环境变量 "ANDROID_PROPERTY_WORKSPACE"

//其实是放到一个static const char *ENV[32];中,调用service_start()函数时ENV将作为参数传递给

//execve(svc->args[0], (char**) svc->args, (char**) ENV);传递给service系统服务进程.

bionic/
arch-
arm/
bionic/
crtbegin_dynamic.
S

bionic/
arch-
arm/
bionic/
crtbegin_static.
S

_start:

mov    r0,
sp

mov    r1,
#
0

adr r2,
0f

adr r3,
1f

b    __libc_init //glibc库初始化

0:
b   main

1:
.
long
__PREINIT_ARRAY__

.
long
__INIT_ARRAY__

.
long
__FINI_ARRAY__

.
long
__CTOR_LIST__

.
.
.

使用adb pull init .
从emulator模拟器导处init进程,
进行如下反汇编:

luther@gliethttp:
~
$
arm-
linux-
objdump -
DS init |
more

init:
file
format elf32-
littlearm

Disassembly of section .
text:

000080a0 <
.
text>
:

80a0:
e1a0000d     mov    r0,
sp

80a4:
e3a01000     mov    r1,
#
0    ;
0x0

80a8:
e28f2004     add    r2,
pc,
#
4    ;
0x4

80ac:
e28f3004     add    r3,
pc,
#
4    ;
0x4

80b0:
ea004ab3     b    0x1ab84 //可以看到这个就是b    __libc_init

80b4:
ea004ab5     b    0x1ab90 //可以看到这个就是b   main

80b8:
0001f000     andeq    pc,
r1,
r0

80bc:
0001f008     andeq    pc,
r1,
r8

80c0:
0001f014     andeq    pc,
r1,
r4,
lsl r0

80c4:
0001f01c     andeq    pc,
r1,
ip,
lsl r0

所以arm-
linux-
gcc就是按上面的方式对init进程进行link链接的.

bionic/
bionic/
libc_init_dynamic.
c

bionic/
bionic/
libc_init_static.
c

=
>
__libc_init

bionic/
bionic/
libc_init_common.
c

=
>
__libc_init_common

=
>
__system_properties_init

=
>
__system_property_area__

int
__system_properties_init(
void
)

{

.
.
.

env =
getenv
(
"ANDROID_PROPERTY_WORKSPACE"
)
;

.
.
.

pa  =
mmap(
0,
sz,
PROT_READ,
MAP_SHARED,
fd,
0)
;

.
.
.

__system_property_area__ =
pa;

.
.
.

return
0;

}

好了,
经过上面glibc库的初始化之后,
所有应用程序都可以通过编译到glibc库中自定义的property_get库函数

操作__system_property_area__了,
比如:wpa_supplicant用户应用应用程序调用wifi_connect_to_supplicant(
)

=
>
property_get(
"wifi.interface"
,
iface,
"sta"
)
;
来获得ashmem中与"wifi.interface"
匹配的propt.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐