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

一种较方便在Android中添加开机自启动的守护进程的方法

2012-10-26 15:41 429 查看
运用本方法的前提是你已经把android源码的sdk编译出来了。在你的Android源码目录下存在这两个目录:

./out/target/product/generic/ramdisk.img



./out/host/linux-x86/sdk/android-sdk_eng.root_linux-x86/platforms/android-2.3.4/images/ramdisk.img

下面通过在Android系统启动时启动一个守护进程,其功能是向指定文件中写。

共4步:1、解压ramdisk.img
2、用c语言完成要实现的功能 3、修改init.rc,启动c语言可执行程序 4、制作ramdisk.img

1、解压ramdisk.img:
解压、修改Android的ramdisk.img的手动方法:

将ramdisk.img复制一份到任何其他目录下,将其名称改为ramdisk.img.gz,并使用命令

gunzip ramdisk.img.gz

然后新建一个文件夹,叫ramdisk吧,进入,输入命令

cpio -i -F ../ramdisk.img

就能把ramdisk.img解压出来了并可以操作ramdisk里面的内容了。
2、完成一个C语言程序hello.c,来实现功能。

a。首先,代码如下:

[cpp]
view plaincopyprint?

<span style="font-size: 18px;">

/************************程序开始**************************/

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>
#include <sys/time.h>

#include <sys/resource.h>

#include <sys/types.h>

#include <sys/stat.h>
#include <fcntl.h>

int main(void)

{

int i=0;

int fd;

pid_t pid;

struct rlimit rl;

char str[]="hello world...\n";

umask(0);
if(getrlimit(RLIMIT_NOFILE,&rl)<0)

printf("getrlimit函数调用出现错误!\n");

if((pid=fork())<0)
{
printf("fork出现错误!\n");

exit(1);
}
else if(pid>0)//父进程退出

{
printf("父进程退出,它的ID为%d,它的子进程ID为%d\n",getpid(),pid);

exit(0);
}
//子进程
sleep(2);
printf("子进程ID为%d\n",getpid());

setsid();
if((pid=fork())<0)

{
printf("fork出现错误!\n");

return -1;
}
else if(pid>0)//第一个子进程退出

{
printf("第一个子进程退出,它的ID为%d,它的子进程ID为%d\n",getpid(),pid);
/*这个printf的内容可以被输出,貌似是因为它所在的进程虽然失去了终端,但它是一个会话组的首进程,因此看到有printf后,自己又申请了一个终端?*/

exit(0);
}

//第二个子进程
printf("不会输出这一行。\n");/*这个printf的内容将不会在屏幕上输出,原因可能是因为它所在的进程此时已经不是一个会话组的首进程,无法重新申请获得终端?*/

chdir("/");
if(rl.rlim_max==RLIM_INFINITY)

rl.rlim_max=1024;
printf("%d",(int)rl.rlim_max);

for(i=0;i<rl.rlim_max;i++)

close(i);
open("/dev/null",O_RDWR);

dup(0);
dup(0);

//每隔5s向文件内写入一次数据
while(1)
{
fd=open("/data/hello.txt",O_WRONLY|O_CREAT|O_APPEND,0766);/*这里的/data指的是android系统上的/data目录*/

write(fd,str,sizeof(str));

sleep(5);
}
close(fd);
exit(0);
}

/************************程序结束**************************/

</span>

/************************程序开始**************************/

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(void)
{

int i=0;

int fd;

pid_t pid;

struct rlimit rl;

char str[]="hello world...\n";

umask(0);
if(getrlimit(RLIMIT_NOFILE,&rl)<0)
printf("getrlimit函数调用出现错误!\n");
if((pid=fork())<0)
{
printf("fork出现错误!\n");
exit(1);
}
else if(pid>0)//父进程退出
{
printf("父进程退出,它的ID为%d,它的子进程ID为%d\n",getpid(),pid);
exit(0);
}
//子进程
sleep(2);
printf("子进程ID为%d\n",getpid());

setsid();
if((pid=fork())<0)
{
printf("fork出现错误!\n");
return -1;
}
else if(pid>0)//第一个子进程退出
{
printf("第一个子进程退出,它的ID为%d,它的子进程ID为%d\n",getpid(),pid); /*这个printf的内容可以被输出,貌似是因为它所在的进程虽然失去了终端,但它是一个会话组的首进程,因此看到有printf后,自己又申请了一个终端?*/
exit(0);
}

//第二个子进程
printf("不会输出这一行。\n");/*这个printf的内容将不会在屏幕上输出,原因可能是因为它所在的进程此时已经不是一个会话组的首进程,无法重新申请获得终端?*/
chdir("/");
if(rl.rlim_max==RLIM_INFINITY)
rl.rlim_max=1024;
printf("%d",(int)rl.rlim_max);
for(i=0;i<rl.rlim_max;i++)
close(i);
open("/dev/null",O_RDWR);
dup(0);
dup(0);

//每隔5s向文件内写入一次数据
while(1)
{
fd=open("/data/hello.txt",O_WRONLY|O_CREAT|O_APPEND,0766);/*这里的/data指的是android系统上的/data目录*/
write(fd,str,sizeof(str));
sleep(5);
}
close(fd);
exit(0);
}

/************************程序结束**************************/


b。然后编译此程序成为android下可执行程序:

在当前目录下建立Android.mk文件,输入以下内容:

[cpp]
view plaincopyprint?

<span style="font-size: 18px;">LOCAL_PATH:=$(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional LOCAL_MODULE:=helloworld LOCAL_SRC_FILES:=hello.c include $(BUILD_EXECUTABLE)</span>

LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE:=helloworld
LOCAL_SRC_FILES:=hello.c
include $(BUILD_EXECUTABLE)
保存退出,之后cd到android源码目录下,运行make helloworld 命令。如果成功编译,生成的helloworld会在目录out/target/product/generic/system/bin/下,把生成的helloworld执行文件push到模拟器的/data目录中去:

#adb
push helloworld /data

3、
修改ramdisk目录下init.rc文件,让其启动helloworld程序,
增加以下代码:

[cpp]
view plaincopyprint?

<span style="font-size: 18px;">

#add by me on 2010-10-18

service chpermission /data/ chpermission
oneshot</span>

#add by me on 2010-10-18
service chpermission   /data/ chpermission
oneshot


4、制作ramdisk.img:

init.rc修改之后,可以使用下列命令重新打包成镜像

cpio -i -t -F ../ramdisk.img > list

cpio -o -H newc -O lk.img < list

当前目录下生成的lk.img就是我们的新镜像了。

将ramdisk.img拷贝到sdk指向的目录。
重启模拟器。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: