您的位置:首页 > 其它

浅析kernel启动的第1个用户进程init如何解读init.rc脚本

2010-05-26 19:14 645 查看
浅析kernel启动的第1个用户进程init如何解读init.
rc脚本

首先解读

1.
on init字段到来,
state-
>
context为新申请到的struct action结构体,
并将其挂接到action_list尾部,
然后初始化处理方法,

之后该section内的所有command都将挂接到act-
>
commands链表上,
这样也就有了立体层次[
luther.
gliethttp]
.

state-
>
parse_line =
parse_line_action;
这样以后的"行脚本"
将使用这个方法来做处理.

2.
loglevel 3因为为cmd,

所以会将动态malloc一个struct command缓冲区,

cmd =
malloc
(
sizeof
(
*
cmd)
+
sizeof
(
char
*
)
*
nargs)
;

cmd-
>
func =
kw_func(
kw)
;

cmd-
>
nargs =
nargs;

memcpy
(
cmd-
>
args,
args,
sizeof
(
char
*
)
*
nargs)
;

list_add_tail(
&
act-
>
commands,
&
cmd-
>
clist)
;
//先将cmd结构体放到list链表尾,后面会集中处理.

3.
之后就都是上面的重复工作了.

一个on和一个service都将创建一个新的struct action结构体,
之后作为当前state-
>
context来处理接下来的所有cmd,

所以接下来的所有cmd也就都将挂接到这个新的act-
>
commands链表上,
感觉这样一来脚本非常有层次感,
管理起来也很舒服.

4.
对于service服务段处理,
如果为service命令,
那么,
先检查service_list链表上是否已经有了同名的服务[
luther.
gliethttp]
.

svc =
service_find_by_name(
args[
1]
)
;

if
(
svc)
{

parse_error(
state,
"ignored duplicate definition of service '%s'/n"
,
args[
1]
)
;

return
0;

}

svc =
calloc
(
1,
sizeof
(
*
svc)
+
sizeof
(
char
*
)
*
nargs)
;

if
(
!
svc)
{

parse_error(
state,
"out of memory/n"
)
;

return
0;

}

svc-
>
name =
args[
1]
;

svc-
>
classname =
"default"
;

memcpy
(
svc-
>
args,
args +
2,
sizeof
(
char
*
)
*
nargs)
;

svc-
>
args[
nargs]
=
0;

svc-
>
nargs =
nargs;

list_add_tail(
&
service_list,
&
svc-
>
slist)
;
//将这个service控制结构体添加到service_list链表尾.

然后将paser的方法指向service方法

state-
>
parse_line =
parse_line_service;
//以下所有参数都将使用parse_line_service进行解析.

5.
service命令后边的参数都将用来改变该service控制结构体里的项,
不同的service命令,

对args有不同的解析方式,
都在parse_line_service中完成,
比如:

1 service dund /
system
/
bin/
dund /

2    -
-
listen
-
-
channel=
5 -
-
nodetach -
-
pppd=
/
system
/
bin/
pppd /

3    192.
168.
0.
100:
192.
168.
0.
101 nodefaultroute unit 1 linkname bluetooth

4    user bluetooth

5    group bluetooth net_bt_admin

6    disabled

那么1行开始将申请一个service结构体,
然后挂接到service_list链表上,

之后的5行都是用来控制这个service结构体里边的数据项,
直到在行首遇到下一个service关键字或者on才会停止[
luther.
gliethttp]
.

好了,
基本的命令字和立体的脚本解析结构,
已经说完了,
那么从init.
rc脚本解析出来的咚咚在啥时候用呢,

1.
对于on节提供的对外接口

void
action_for_each_trigger(
const
char
*
trigger,

void
(
*
func)
(
struct
action *
act)
)

void
queue_property_triggers(
const
char
*
name,
const
char
*
value)

void
queue_all_property_triggers(
)

举个例子

action_for_each_trigger(
"early-init"
,
action_add_queue_tail)
;

action_for_each_trigger(
"init"
,
action_add_queue_tail)
;

action_for_each_trigger(
"early-boot"
,
action_add_queue_tail)
;

action_for_each_trigger(
"boot"
,
action_add_queue_tail)
;

2.
对于service节提供的对外接口

struct
service *
service_find_by_name(
const
char
*
name)

struct
service *
service_find_by_pid(
pid_t
pid)

void
service_for_each_class(
const
char
*
classname,

void
(
*
func)
(
struct
service *
svc)
)

void
service_for_each_flags(
unsigned
matchflags,

void
(
*
func)
(
struct
service *
svc)
)

举个例子

int
do_start(
int
nargs,
char
*
*
args)

{

struct
service *
svc;

svc =
service_find_by_name(
args[
1]
)
;

if
(
svc)
{

service_start(
svc)
;

}

return
0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: