【Android】killProcessesWithOpenFiles分析

问题的引入:

卸载应用的时候,system_server被kill掉导致系统重启


Log

05-01 11:05:25.661595   462  473 E ProcessKiller: Process system_server (1194) has open file/mnt/asec/com.netease.newsreader.activity-2/base.apk

05-01 11:05:25.661670   462  473 W ProcessKiller: Sending Terminated to process 1194

 

在代码中查找ProcessKiller,得到

android/system/vold/Process.cpp

void Process::killProcessesWithOpenFiles(const char*path, int signal) {

    DIR*    dir;

    structdirent* de;

 

    if (!(dir= opendir("/proc"))) {

       SLOGE("opendir failed (%s)", strerror(errno));

       return;

    }

 

    while((de = readdir(dir))) {

        intpid = getPid(de->d_name);

        charname[PATH_MAX];

 

        if(pid == -1)

           continue;

       getProcessName(pid, name, sizeof(name));

 

        charopenfile[PATH_MAX];

 

        if(checkFileDescriptorSymLinks(pid, path, openfile, sizeof(openfile))) {

           SLOGE("Process %s (%d) has open file %s", name, pid, openfile);

        }else if (checkFileMaps(pid, path, openfile, sizeof(openfile))) {

           SLOGE("Process %s (%d) has open filemap for %s", name, pid,openfile);

        }else if (checkSymLink(pid, path, "cwd")) {

           SLOGE("Process %s (%d) has cwd within %s", name, pid, path);

        }else if (checkSymLink(pid, path, "root")) {

           SLOGE("Process %s (%d) has chroot within %s", name, pid,path);

        }else if (checkSymLink(pid, path, "exe")) {

           SLOGE("Process %s (%d) has executable path within %s", name,pid, path);

        }else if(checkSocketLink(pid, path)) {

           SLOGE("Process %s (%d) has socket related to %s", name, pid,path);

        }else {

           continue;

        }

 

        if(signal != 0) {

            SLOGW("Sending %s to process%d", strsignal(signal), pid);

           kill(pid, signal);

        }

    }

   closedir(dir);

}

 

分析killProcessesWithOpenFiles

 

查看/proc,里面存放的是进程相关信息

/proc/[pid]/fd 里是[pid]这个进程打开的文件fd,ls –l 可以看到对应的文件链接

killProcessesWithOpenFiles 的原理就是遍历proc目录,再遍历fd目录,如果发现文件链接就是要查找的路径,就发送一个kill命令


这里猜想一种方式,用来强制关闭文件,来解决本例中的问题,本例是由于/mnt/asec/com.netease.newsreader.activity-2/base.apk被打开了,导致卸载应用的时候,调用了killProcessesWithOpenFiles,把system_server kill掉了导致系统重启,由于不知道在哪里打开处理的,

这里尝试这个不得已的方法,就是强制把system_server里打开的/mnt/asec/com.netease.newsreader.activity-2/base.apk的文件描述符close掉

以/mnt/asec/com.netease.newsreader.activity-2为例

查看system_server的pid

ps |grep system_server

ps |grep system_server

system   1155  516   2809436 191304 SyS_epoll_ 7f804d6260 S  system_server

 

根据得到的pid 1155到proc里进行查看

root:/proc/1155/fd # ls -l | grep mnt

ls -l | grep mnt

lr-x------ root    root              2015-05-02 14:30    199 ->/mnt/asec/com.netease.newsreader.activity-2/base.apk


 

得到打开/mnt/asec/com.netease.newsreader.activity-2/base.apk的fd199

 

这样就可以通过发送信号的方式在system_server里close(fd)

 

system_server注册信号

kill –l  查看信号

1) SIGHUP      2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP

 6)SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR1

11) SIGSEGV    12) SIGUSR2     13) SIGPIPE     14) SIGALRM     15) SIGTERM

16) SIGSTKFLT  17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP

21) SIGTTIN    22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ

26) SIGVTALRM  27) SIGPROF     28) SIGWINCH    29) SIGIO       30) SIGPWR

31) SIGSYS     34) SIGRTMIN    35)SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3

38) SIGRTMIN+4 39) SIGRTMIN+5  40)SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8

43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13

48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51)SIGRTMAX-13 52) SIGRTMAX-12

53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7

58) SIGRTMAX-6 59) SIGRTMAX-5  60)SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2

63) SIGRTMAX-1 64) SIGRTMAX

 

修改system_server的程序

vi ./frameworks/base/core/jni/com_android_internal_os_Zygote.cpp

 

//test

void sigTest(intsig)

{

        if (sig == 38)

        {

                ALOGI("=====testsystem_server===== sig = %d", sig);

        }

        else

        {

                ALOGI("=====else testsystem_server===== sig = %d", sig);

        }

}

 

// Utility routine to fork zygote and specializethe child process.

static pid_t ForkAndSpecializeCommon(JNIEnv* env,uid_t uid, gid_t gid, jintArray javaGids,

                                     jint debug_flags,jobjectArray javaRlimits,

                                     jlongpermittedCapabilities, jlong effectiveCapabilities,

                                     jintmount_external,

                                     jstringjava_se_info, jstring java_se_name,

                                     boolis_system_server, jintArray fdsToClose,

                                     jstringinstructionSet, jstring dataDir) {

  SetSigChldHandler();

 

  pid_t pid =fork();

 

  if (pid ==0) {

    // Thechild process.

   gMallocLeakZygoteChild = 1;

 

    // Cleanup any descriptors which must be closed immediately

   DetachDescriptors(env, fdsToClose);

 

    // Keepcapabilities across UID change, unless we're staying root.

    if (uid!= 0) {

     EnableKeepCapabilities(env);

    }

 

   DropCapabilitiesBoundingSet(env);

//

        signal(38, sigTest);

//

 

 

手机root后进行测试,不root没有kill发送信号的权限


ps | grep system_serv

system   1088  447   2730844 207340 SyS_epoll_ 7fa9081260 S  system_server

 

得到pid 1088,发送信号,这里使用约定的38

root:/ # kill -38 1088

07-02 16:19:17.891: I/Zygote(1088): =====testsystem_server===== sig = 38

 

现在有另外一个问题,如何跨进程把fd传给system_server

一个方法是回避这个问题,让system_server到/proc/ 里进行遍历查找,和Process.cpp里一样

或者通过socket等方法传送数据

 

小结

通过分析测试,可以认识到Process::killProcessesWithOpenFiles(const char*path, int signal)的处理原理和/proc/的内容结构,另外通过信号和system_server进行交互的处理方法可以揭开system_server的面纱。

 





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值