美文网首页
NDK双进程守护

NDK双进程守护

作者: 小熊_c37d | 来源:发表于2018-06-27 17:29 被阅读0次

    NDK层双进程守护

    系统关键服务杀得死吗?
    不能!

    那么系统服务是怎么来的:zygote

    在Android系统中,所有的应用程序进程以及系统服务进程SystemServer都是由Zygote进程孕育(fork)出来的,因为Android系统是基于Linux内核的,而在Linux系统中,所有的进程都是init进程的子孙进程,也就是说,所有的进程都是直接或者间接地由init进程fork出来的。Zygote进程也不例外,它是在系统启动的过程,由init进程创建的,在系统启动脚本system/core/rootdir/init.rc文件中,我们可以看到启动Zygote进程

    从上面介绍我们知道 android 所有的进程都是init进程的子孙进程
    我们看看init进程,从图可以看到PID=1

    图片.png

    从这个图我们看到zygote的PPID=1;也就是他 他的父进程就是init

    图片.png

    我们看到Phone进程的PPID=1330; 由此我们可以看出android的 所有系统进程都是由zygote产出

    图片.png

    fork

    所有的进程都是直接或者间接地由init进程fork出来的

    ok我们来fork

    图片.png

    我们先创建一个Watcher

    public class Watcher {
        static {
            System.loadLibrary("native-lib");
        }
    
        public native void  createWatcher(String  userId);
    
        public native void  connectMonitor();
    }
    
    

    我们要启动的服务

    public class ProcessService extends Service {
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        public int index;
        private static final String TAG = "ProcessService";
    
        @Override
        public void onCreate() {
            super.onCreate();
            Watcher watcher = new Watcher();
            watcher.createWatcher(String.valueOf(Process.myUid()));
            watcher.connectMonitor();
            Timer timer = new Timer();
            timer.scheduleAtFixedRate(new TimerTask() {
                @Override
                public void run() {
                    Log.i(TAG, "run: 你杀不死我 " + index);
                    index++;
          
    
                }
            }, 0, 5000);
    
        }
    
     
    }
    
    
    

    native-lib.cpp

    #include <jni.h>
    #include <string>
    #include <string.h>
    #include "native_lib.h"
    
    extern "C"
    JNIEXPORT jstring
    
    JNICALL
    Java_com_ndk_1guard_MainActivity_stringFromJNI(
            JNIEnv *env,
            jobject /* this */) {
        std::string hello = "Hello from C++";
        return env->NewStringUTF(hello.c_str());
    }
    
    
    const char *userId;
    /**
     * PATH=/dada/dada/包名/my.sock
     */
    const char *PATH = "/data/data/com.ndk_guard/my.sock";
    int m_child;
    
    void child_do_work() {
        //开启socket
        if (child_create_channel()) {
            child_listen_msg();
        }
    
    }
    
    void child_listen_msg() {
        fd_set rfds;
        //时间  3秒
        struct timeval timeout = {3, 0};
        while (1) {
            //清空内容
            FD_ZERO(&rfds);
    
            FD_SET(m_child, &rfds);
    
            //选择范围 一般+1;
    
            int r = select(m_child + 1, &rfds, NULL, NULL, &timeout);
    
    
    
            if (r > 0) {
                char pkg[256] = {0};
                //保证所读到的信息是指定apk客户端的信息
                if (FD_ISSET(m_child, &rfds)) {
                    //阻塞函数
                    int result = read(m_child, pkg, sizeof(pkg));
                    //一旦和apk断开  就执行下面代码
                    //开启服务
                    execl("am", "am", "startservice", "--user", userId,
                          "com.ndk_guard/com.ndk_guard.ProcessService", NULL);
                    break;
                }
            }
        }
    }
    
    /**
     * 开启socket 服务
     * @return
     */
    int child_create_channel() {
    
        int listenfd = socket(AF_LOCAL, SOCK_STREAM, 0);
        struct  sockaddr_un addr;
        unlink(PATH);
        memset(&addr, 0, sizeof(sockaddr));
        addr.sun_family = AF_LOCAL;
        strcpy(addr.sun_path, PATH);
        int connfd;
        if (bind(listenfd, (const sockaddr *) &addr, sizeof(sockaddr_un)) < 0) {
            LOGE("绑定错误");
            return 0;
        }
    
        //最多同时连接5个
        listen(listenfd, 5);
    
    
        //while 保证宿主连接成功
        while (1) {
            //返回值 客户端的地址 //阻塞函数
            if ((connfd = accept(listenfd, NULL, NULL)) < 0) {
                if (errno == EINTR) {
                    LOGE("读取错误EINTR");
                    continue;
                } else {
                    LOGE("读取错误");
                    return 0;
                }
            }
    
    
            m_child = connfd;
            LOGE("apk 父进程连接上 %s" , m_child);
            break;
        }
        return 1;
    }
    
    extern "C"
    JNIEXPORT void JNICALL
    Java_com_ndk_1guard_Watcher_createWatcher(JNIEnv *env, jobject instance, jstring userId_) {
        userId = env->GetStringUTFChars(userId_, 0);
        //开双进程
        pid_t pid = fork();
        if (pid < 0) {
            //fork失败
        } else if (pid == 0) {
            //子线程   守护进程
            child_do_work();
    
        } else if (pid > 0) {
            //主线程
        }
        env->ReleaseStringUTFChars(userId_, userId);
    }
    
    
    extern "C"
    JNIEXPORT void JNICALL
    Java_com_ndk_1guard_Watcher_connectMonitor(JNIEnv *env, jobject instance) {
        int socked;
        while (1) {
    
            LOGE("客户端  开始进行连接了");
            socked = socket(AF_LOCAL, SOCK_STREAM, 0);
            if (socked < 0) {
                LOGE("连接失败0");
                return;
            }
            struct  sockaddr_un addr;
    
            memset(&addr, 0, sizeof(sockaddr));
            addr.sun_family = AF_LOCAL;
            strcpy(addr.sun_path, PATH);
    
            if (connect(socked, (const sockaddr *) &addr, sizeof(sockaddr_un)) < 0) {
                LOGE("连接失败");
                close(socked);
                sleep(1);
                //在来下一次尝试连接
                continue;
            }
            LOGE("连接成功");
            break;
        }
    
    }
    
    

    native_lib.h

    
    
    #ifndef NDK_GUARD_NATIVE_LIB_H
    #define NDK_GUARD_NATIVE_LIB_H
    
    #endif //NDK_GUARD_NATIVE_LIB_H
    #include <sys/select.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <pthread.h>
    #include <signal.h>
    #include <sys/wait.h>
    #include <android/log.h>
    #include <sys/types.h>
    #include <sys/un.h>
    #include <errno.h>
    #include <stdalign.h>
    #include <linux/signal.h>
    #include <unistd.h>
    #include <sys/un.h>
    
    #define LOG_TAG "tuch"
    #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
    
    void child_do_work();
    void child_listen_msg();
    int child_create_channel();
    
    
    

    运行代码 启动服务

     startService(new Intent(this,ProcessService.class));
    
    

    我们启动的进程PPID=1330 也就是依赖于zygote PPID=4295 依赖我们fork出来的进程

    图片.png 图片.png 图片.png

    可以看到我们连接成功了 并且服务已经启动成功,接下来我们直接下死app

    图片.png 图片.png 图片.png 图片.png

    根据上图我们可以看到当你的app杀死后,会重新启动服务

    相关文章

      网友评论

          本文标题:NDK双进程守护

          本文链接:https://www.haomeiwen.com/subject/adxiyftx.html