如何手动运行init.rc service 启动里面的service-CSDN论坛

Android启动流程分析(九) 解析init.rc的service - CSDN博客
Android启动流程分析(九) 解析init.rc的service
#############################################
本文为极度寒冰原创,转载请注明出处
#############################################
在分析完解析init.rc的action之后,剩下的一部分就是解析service了。
而解析service还是需要回到parse_config里面来。根据前面的知识,我们也可以很容易的知道在关键字为section的时候,会进入到parse_new_section。
这里会先执行parse_service,然后将service以及后面跟的option设置为执行parse_line:parse_line_service。
要理解service的解析流程的话,首先要关注的就是service的结构体。
struct service {
/* list of all services */
// listnode slist
const char *
const char *
// 默认值为defult
// Service所在进程的PID
time_t time_
/* time of last start */
time_t time_
/* first crash within inspection window */
/* number of times crashed within window */
// effective user ID
// effective group ID
gid_t supp_gids[NR_SVC_SUPP_GIDS];
// supplementary ids
size_t nr_supp_
// supp_gids的大小
struct socketinfo *
// 为service创建的Sockets
struct svcenvinfo *
// 为service设置的环境变量
/* Actions to execute on restart. */
/* keycodes for triggering this service via /dev/keychord */
int keychord_
int ioprio_
int ioprio_
/* &MUST BE AT THE END OF THE STRUCT& */
char *args[1];
^-------'args' MUST be at the end of this struct! */
这个结构体相比较而言就比较简单了,除了service的本身属性以外,对于数据结构方面就只有一个listnode。
s 这也就是说,在service的结构体中,这个结构体只会被加入一条链表而不是像action的两条链表。
另外需要注意的是,在service的结构体中,也维护了一个action的结构体,这就是说,在service中,也存在着一个action的commands的链表?
然后我们就来看看parse_service的函数
static void *parse_service(struct parse_state *state, int nargs, char **args)
struct service *
// 声明结构体
if (nargs & 3) { // 如果service的参数小于三个的话,我们会认为service是个不正常的service。service最少的nargs也是3,分别为service关键字,service的名字,service启动的时候要执行的命令
parse_error(state, &services must have a name and a program\n&);
if (!valid_name(args[1])) {
//如果service的name为不标准的名字的话,含有其它的符号的话,我们会认为这个service是不规范的service。
parse_error(state, &invalid service name '%s'\n&, args[1]);
svc = service_find_by_name(args[1]); 。。// 会从已经存在的service_list里面去查找,是否已经有同名的service存在
if (svc) {
// 如果发现有同名的service存在的话,则会返回error
parse_error(state, &ignored duplicate definition of service '%s'\n&, args[1]);
nargs -= 2;
// 去除service关键字与service的name
svc = calloc(1, sizeof(*svc) + sizeof(char*) * nargs); // malloc这个结构体
if (!svc) { // 如果malloc失败的话,提示out of memory
parse_error(state, &out of memory\n&);
svc-&name = args[1];
// 设置service的name为service关键字后的第一个参数
svc-&classname = &default&;
// 默认的classname为default
memcpy(svc-&args, args + 2, sizeof(char*) * nargs); // 将args剩余的参数复制到svc的args里面
svc-&args[nargs] = 0;
// 给args的最后一项设置为0
svc-&nargs =
// 参数的数目等于传进来的参数的数目
svc-&onrestart.name = &onrestart&; // 设置onrestart.name为onrestart
list_init(&svc-&mands); // 初始化onrestart的链表
list_add_tail(&service_list, &svc-&slist);
// 将当前的service结构体加入到了service_list的链表里面
从上面我们知道,在执行完parse_service之后,会初始化service的一些属性,将service servicename之后的做为args进行保存。
另外,将这个解析出来的service加入到service_list的链表里面。
然后接下来,去执行的就是
state-&parse_line = parse_line_那我们像action,再来看看parse_line_service的操作
static void parse_line_service(struct parse_state *state, int nargs, char **args)
struct service *svc = state-&
struct command *
int i, kw, kw_
if (nargs == 0) {
svc-&ioprio_class = IoSchedClass_NONE;
kw = lookup_keyword(args[0]);
switch (kw) {
case K_capability:
case K_class:
if (nargs != 2) {
parse_error(state, &class option requires a classname\n&);
svc-&classname = args[1];
case K_console:
svc-&flags |= SVC_CONSOLE;
case K_disabled:
svc-&flags |= SVC_DISABLED;
svc-&flags |= SVC_RC_DISABLED;
case K_ioprio:
if (nargs != 3) {
parse_error(state, &ioprio optin usage: ioprio &rt|be|idle& &ioprio 0-7&\n&);
} else {    。。。。
case K_onrestart:
        nargs--;
        args++;
        kw = lookup_keyword(args[0]);
        if (!kw_is(kw, COMMAND)) {
            parse_error(state, &invalid command '%s'\n&, args[0]);
           
        }
        kw_nargs = kw_nargs(kw);
        if (nargs & kw_nargs) {
            parse_error(state, &%s requires %d %s\n&, args[0], kw_nargs - 1,
                kw_nargs & 2 ? &arguments& : &argument&);
           
        }
        cmd = malloc(sizeof(*cmd) + sizeof(char*) * nargs);
        cmd-&func = kw_func(kw);
        cmd-&nargs =
        memcpy(cmd-&args, args, sizeof(char*) * nargs);
        list_add_tail(&svc-&mands, &cmd-&clist);
       
...............
可以看到,parse_line_service的这个函数,主要就是将解析service的每一行,将其对应进不同的case里面,进行service结构体的填充。
可能这样讲,理解起来会有困难。
但是为了方便理解,我们从init.rc里面找个例子出来分析:
service servicemanager /system/bin/servicemanager
class core
user system
group system
onrestart restart healthd
onrestart restart zygote
onrestart restart media
onrestart restart surfaceflinger
onrestart restart drm
在parse_line_service的时候,会在
class的关键字的时候,执行到
case K_class:
if (nargs != 2) { // 判断是否是两个token,如果不是的话,格式错误
parse_error(state, &class option requires a classname\n&);
svc-&classname = args[1];
也就是将service的classname从&default&修改为“args[1]”
在user system的的option的时候,
case K_user:
if (nargs != 2) {
parse_error(state, &user option requires a user id\n&);
svc-&uid = decode_uid(args[1]);
会将uid设置为system对应的uid
另外需要注意的是,在解析的过程中,会有一个比较重要的option是restart,来看一下当执行到这个关键字的时候的时候,会运行什么。
case K_onrestart:
kw = lookup_keyword(args[0]);
if (!kw_is(kw, COMMAND)) {
// 判断是否是command,如果restart之后跟的不是command的话,就会返回error
parse_error(state, &invalid command '%s'\n&, args[0]);
kw_nargs = kw_nargs(kw);
// 获得当前command所需的参数
if (nargs & kw_nargs) { // 如果传递的参数小于我们需要的参数的话,会返回error
parse_error(state, &%s requires %d %s\n&, args[0], kw_nargs - 1,
kw_nargs & 2 ? &arguments& : &argument&);
cmd = malloc(sizeof(*cmd) + sizeof(char*) * nargs); // 初始化command
cmd-&func = kw_func(kw);
// 将kw所包含的func赋值给cmd-&func
cmd-&nargs =
// 将参数的个数保存为nargs
memcpy(cmd-&args, args, sizeof(char*) * nargs); // 将这些参数复制到cmd的args中
list_add_tail(&svc-&mands, &cmd-&clist); // 将这些command加入到service结构体的内部链表中
至此,我们分析了所有关于init.rc的解析问题。
在service的解析后,会生成一条链表保存service的结构体,然后service的结构体里面自己运行维护一个action。
这个action会包含所有的restatt包含的内容,也就是restart的option关键字后会包含要执行的command
这个的结构应该比action的要简单和明了的多。
分析完了解析,我们应该去看一下android是如何在启动的过程中去执行这些action和service的。
本文已收录于以下专栏:
相关文章推荐
如果 android init.rc中启动的service 默认是disable的,如何才能启动此服务呢?
Android 控制用户定义 service
修改/etc/init.rc
添加用户定义service 定义
service xxx /usr/sbin/xxx
user roo...
一、init.rc语法规则
1.init.rc文件的内容主要分类
动作(Action)
命令(Commands)
服务(Services)
选项(Options)
触发(trigger)
...
我在博文《Android程序的安全系统》中提到两种让root权限的办法。最近在网上发现很多朋友转载那篇文章,但是对那篇文章中提到的第一种方法怎样实现,不是很明白。本文将会以一个例子实现来演示怎样让一个...
开篇:为什么写这篇文章
先说下我自己的情况,我是个普通的大四学生,之前在学校一直做Android应用开发,找实习的时候也一直想找相关的工作,来到现在这家公司以后,由于业务调整,被领导安排去做底层开发,...
Android init.rc文件解析过程详解(二)
3、parse_new_section代码如下:
void parse_new_section(struct parse_state *...
前文简要介绍了Android应用程序的Activity的启动过程。在Android系统中,应用程序是由Activity组成的,因此,应用程序的启动过程实际上就是应用程序中的默认Activity的启动过...
经过两年的时间,终于完成对Android系统的研究了。Android是一个博大精深的系统,老罗不敢说自己精通了(事实上最讨厌的就是说自己精通神马神马的了,或者说企业说要招聘精通神马神马的人才),但是至...
在Android系统中,所有的应用程序进程以及系统服务进程SystemServer都是由Zygote进程孕育(fork)出来的,这也许就是为什么要把它称为Zygote(受精卵)的原因吧。由于Zygot...
在Android系统中,应用程序进程都是由Zygote进程孵化出来的,而Zygote进程是由Init进程启动的。Zygote进程在启动时会创建一个Dalvik虚拟机实例,每当它孵化一个新的应用程序进程...
他的最新文章
讲师:何宇健
讲师:董岩
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)Android: 如何调试init.rc中的service - CSDN博客
Android: 如何调试init.rc中的service
1、更改将要调试的service的class类型:
2、添加触发条件
4、单步调试
用start命令启动要调试的service,比如:start servicemanager
本文已收录于以下专栏:
相关文章推荐
本文主要来自$ANDROID_SOURCE/system/init/readme.txt的翻译.
Android init.rc文件由系统第一个启动的init程序解析,此文件由语句组...
如何调试手机根目录下的init,rc等类似文件
将system/core/rootdir/下的init.rc等文件修改后。重新编一个boot,img刷入手机即可,这时手机启动后,查看根...
在Android开发中经常会遇到,在应用层想去执行一个脚本来完成某些底层相关的操作,但在应用层又没有root权限。
所以,老大给出一种方法完美解决此问题,又把上层和底层进行了隔离,非常好的策略。
在Android编译过程中,
之前写过一篇关于android5.0 init的介绍,这篇博客是介绍android6.0init,之前有的代码介绍不详细。而且分析 解析init.rc那块代码也没有结合init.rc介绍。一、 mai...
通过property_set(&ctl.start&, service_xx);来启动init.rc中的service是一个很方便方法来调用某个可执行程序或某个脚本程序service service_...
Platform: Rockchip
OS: Android 6.0
Kernel: 3.10.92
正常有USB口调试过程如下:
1. 使用USB数据线连接设备。
2. 在命令行输入adb tcp...
在分析完解析init.rc的action之后,剩下的一部分就是解析service了。
而解析service还是需要回到parse_config里面来。根据前面的知识,我们也可以很容易的知道在关键字为s...
android的init进程初始化的时候,除了对系统作一些必要的初始化外,就是启动service了。而service是定义在init脚本中的,故很有必要了解一下,init中对service的处理。
开篇:为什么写这篇文章
先说下我自己的情况,我是个普通的大四学生,之前在学校一直做Android应用开发,找实习的时候也一直想找相关的工作,来到现在这家公司以后,由于业务调整,被领导安排去做底层开发,...
他的最新文章
讲师:何宇健
讲师:董岩
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)本帖子已过去太久远了,不再提供回复功能。Android init.rc如何启动service去执行sh脚本 - CSDN博客
Android init.rc如何启动service去执行sh脚本
在Android开发中经常会遇到,在应用层想去执行一个脚本来完成某些底层相关的操作,但在应用层又没有root权限。
所以,老大给出一种方法完美解决此问题,又把上层和底层进行了隔离,非常好的策略。
1、在需要执行脚本的时候,应用层去设置一个property,在init.rc中去监测此property的值,当监测到此property的值符合要求时,去start service,来执行我们的脚本文件;
2、脚本执行完成后,在去重置此property的值,来stop service。
有产品需求需要在工厂菜单里面添加M5芯片的升级,方便以后的调试。
1、在工厂apk里面,M5需要升级的时候,去setprop&dev.skym5update.enable=1 去启动sky_M5_update &service来执行sky_m5_update.sh
2、脚本执行完成后重置setprop&dev.skym5update.enable=0来停止sky_M5_update &service
3、sky_M5_update &service在开机的时候不需要去执行,把参数disabled加上即可。
#for V620 M5 update
service sky_M5_update /system/bin/sky_m5_update.sh
& & class main
& & user root
& & group root
& & disabled
on property:dev.skym5update.enable=1
& & start sky_M5_update
on property:dev.skym5update.enable=0
& & stop sky_M5_update
本文已收录于以下专栏:
相关文章推荐
[Android] 在開機的時候,執行你想要的 shell script
雖然 init.rc 很好用,但還是有其缺陷... 像是我要 echo 某些字串到檔案時,他就做不到了 :(
所以可以搭...
init-android.sh
# IJK_FFMPEG_UPSTREAM=git://git.videolan.org/ffmpeg.git
IJK_FFMPEG_UPSTREAM=...
通过property_set("ctl.start", service_xx);来启动init.rc中的service是一个很方便方法来调用某个可执行程序或某个脚本程序service service_...
开篇:为什么写这篇文章
先说下我自己的情况,我是个普通的大四学生,之前在学校一直做Android应用开发,找实习的时候也一直想找相关的工作,来到现在这家公司以后,由于业务调整,被领导安排去做底层开发,...
git中把commit删了后,并不是真正的删除,而是变成了悬空对象(dangling commit)。我们只要把把这悬空对象(dangling commit)找出来,用git rebase也好,用gi...
维基百科上SSH的定义如下
Secure Shell(縮寫为SSH),由IETF的網路工作小組(Network Working Group)所制定;SSH為一项建立在应用层和传输层基础上的安全协议,为...
本文编辑整理自:
/blog/1300713
http://web.mit.edu/bitbucket/git-doc/git-cherry-pick.tx...
LinuxDeviceDrive...
在这个明星亮相粉丝疯狂泛滥的年代——李宇春,一个坚持称自己为歌手的姑娘,执着的为喜欢音乐的朋友歌唱,她喜欢舞台,拒绝还音。我知道不能错过一位歌手的现场,因为这是对她最大的肯定。
激活控制台;此时以下按键生效
列出所有快捷键;按q返回
脱离当前会话;这样可以暂时返回Shell界面,输入tmux ...
他的最新文章
讲师:宋宝华
讲师:何宇健
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)

我要回帖

更多关于 service init.d 的文章

 

随机推荐