Init.rc 정리
/system/core/rootdir/init.rc
Android Init Language로 기술 되어 있음 ( /system/core/init/readme.txt )
- action
on <trigger>
<command>
<command>
…
- service & option
service <name> <pathname> [ <argument> ]*
<option>
<option>
...
모든 서비스는 parse_line_service 에서 파싱 되어 동작 한다. ( /system/core/init/parser.c )
example)
- Socket
socket <name> <type> <perm> [ <user> [ <group> ] ]
Create a unix domain socket named /dev/socket/<name> and pass
its fd to the launched process. <type> must be "dgram" or "stream".
User and group default to 0.
-> /dev/socket/ 에 <name> 이름을 가진 Unix Domain Socket 을 만들고 실행한 프로세스에게 fd 를 넘긴다
<type> 은 반드시 dgram 이나 stream 이어야 한다. User 와 group (의 권한)은 기본적으로 0
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
socket zygote stream 666
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
// 추후 내용 보충
dgram - UDP, 비 연결형 ( 보장 x )
stream - TCP, 오버헤드, 신뢰
- 소켓 정보 설정 - parse_line_service ( /system/core/init/parser.c )
args[0] - socket / args[1] - xxx / ….
// 소켓 정보 셋팅
si->name = args[1];
si->type = args[2];
si->perm = strtoul(args[3], 0, 8);
si->next = svc->sockets;
svc->sockets = si;
- 소켓 생성 및 fd 값 저장 - service_start ( /system/core/init/init.c )
for (si = svc->sockets; si; si = si->next) {
/*
/dev/socket/'si->name' 의 파일로 바인딩 된 unix domain socket 생성 후 fd 리턴
*/
int s = create_socket(si->name,
!strcmp(si->type, "dgram") ?
SOCK_DGRAM : SOCK_STREAM,
si->perm, si->uid, si->gid);
/*
publish_socket - ( key, value ) 환경 변수 생성
key - ANDROID_SOCKET_ + si->name
key 와 생성 된 fd 매핑
*/
if (s >= 0) {
publish_socket(si->name, s);
}
}
- command
exmple)
- mount
mount <type> <device> <dir> [ <mountoption> ]*
Attempt to mount the named device at the directory <dir>
<device> may be of the form mtd@name to specify a mtd block
device by name.
<mountoption>s include "ro", "rw", "remount", "noatime", ...
mount /mnt 0775 root system
( /system/core/init/parser.c )
- 커맨드 맵핑
static void parse_line_action(struct parse_state* state, int nargs, char **args)
{
…
/*
( /system/core/init/keywords.h )
keyword 와 func 정의 되어 있음
*/
kw = lookup_keyword(args[0]);
…
/*
필요한 정보 저장
*/
cmd->func = kw_func(kw);
cmd->nargs = nargs;
memcpy(cmd->args, args, sizeof(char*) * nargs);
list_add_tail(&act->commands, &cmd->clist);
}
- 맵핑 된 커멘드 호출
void action_for_each_trigger(const char *trigger,
void (*func)(struct action *act))
{
struct listnode *node;
struct action *act;
list_for_each(node, &action_list) {
act = node_to_item(node, struct action, alist);
if (!strcmp(act->name, trigger)) {
func(act); // call do_mount() - ( /system/core/init/builtns.c );
}
}
}
- trigger
<name>=<value>
Triggers of this form occur when the property <name> is set
to the specific value <value>.
example)
- on Property
on property:ro.kernel.qemu=1
start adbd
ro.kernel.qemu 가 1로 셋팅 되면 'start adbd' 실행
- property 변경 시 property_set_fd 의 events POLLIN에 의해
handle_property_set_fd(property_set_fd) 호출
참고 - init.c 18, 19
- handle_property_set_fd() -> property_set() -> property_changed()
( /system/core/init/property_service.c )