网站首页 > 技术文章 正文
说到双进程守护,大家第一点想到的肯定是Android里面的双进程守护,然而我们今天不讲这个,因为有弊端。大家有没有,kill app后servece都被kill了,你让他们谁拉谁?所以说我们要看的更深一些,大家有没有发现一个很奇怪的东西,就是Android设备你可以在进程看到很多系统servece,你们就不好奇为啥这个系统servece就一直能运行吗?我们今天就讲这个,c层的双进程守护,涉及到好几个知识点,主要是linux中多进程,unix domain套接字实现跨进程通信,linux的信号处理以及exec函数族的用法(当然不是所有的都讲,之后慢慢讲,因为怕刚学的人不懂。)。看到套接字有没有很熟悉,java三次握手四次挥手。这些内容是不是很熟悉。可是我们说了,这是基于C++的,所以希望看完这个大家都有所学,学以致用,而不是看完就丢了,你的工作会有很多这样的需求(PS:我也不想这么干啊!国内的google服务全kill了,GM部门新成立的推送联盟感觉没啥用,涉及到各家手机厂商大佬们的利益,他也没法协调。所以我们只能耍耍流氓咯。我也不支持大家这么做,没办法,谁叫这是GM为老大呢?)。
我在想要不要先讲一下原理,因为有些长,算了,讲一下吧!谁叫我啰嗦呢?(关于现在app涉及各种隐晦的权限,我在这里说一下原则问题哈,技术本身没有错,用善则善,用恶则恶。我们都希望一个好的环境做更好的事情。)
<1> 子进程(监视进程)如何监视到父进程死亡?
当父进程死亡以后,子进程就成为了孤儿进程由Init进程领养,于是我们可以在一个循环中读取子进程的父进程PID,当变为1就说明其父进程已经死亡,于是可以重启父进程。这里因为采用了循环,所以就有了新问题,那就是耗电。耗电的问题大家先想一想怎么解决,当然本文也会讲到,对用户多负责一点,也是对我们自己负责(重声原则问题,看上面)。
<2>父进程(监视进程)如何监视到子进程的死亡?
很简单,在linux中,子进程被终止时,会向父进程发送SIG_CHLD信号,于是我们可以安装信号处理函数,并在此信号处理函数中重新启动创建监视进程;
<3>父子进程间的通信
父子进程间建立通信通道,然后通过监视此通道来感知对方的存在,这样不会存在之前提到的耗电量的问题,采用了轮询父进程PID的办法,但是还是留出了父子进程的通信通道。(暂时不讲这个)
现在开始写代码,请看下面先来个java类,给外部提供一个API接口,当然所有的实现都通过native方法在C++中完成!爆红我们先不管,等会处理
然后我们写.cpp类,看下图(如果你不想看文字觉得枯燥就直接看图,我在代码里面写的注释应该算是很清楚),然后说一下sigaction函数,它是用于改变进程接收到特定信号后的行为。它有三个参数
int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact) 参数 --第一个参数是信号的值,可以为除了SIGKILL及SIGSTOP外的任何一个特定有效的信号(因为这两个信号定义了自己的处理函数,将导致信号安装错误) --第二个参数是指向节后sigaction的一个实例的指针,在sigaction的实例中,指定了对特定信号的处理,可以为NULL,进程会以缺省方式对信号处理 --第三个参数oldact指向的对象用来保存原来对相应信号的处理,可以为NULL 返回值:函数成功返回0,失败返回-1。
然后我们这个sigaction现在干什么呢?
首先sigaction信号处理sa.sa_flags=SA_RESTART:使被信号打断的系统调用自动重新发起信号处理交给sig_handler处理的,当子进程挂了的时候会向其父进程发送一个SIGCHLD信号,父进程就会收到SIGCHLD信号,并且开始执行sig_handler方法,重生成子进程。
然后调用create_child()方法(这个时候估计有人就奇怪了,怎么你一会说函数,一会说方法,首先明确我是搞Android的,我们跟JAVA一样都是叫方法,所以习惯性的。)。
说下原理:
一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。就是相当于克隆了一个自己。
当pid==0 说明是子进程(这个时候我们就开启子线程child_start_monitor()),pid>0是父进程
开启子线程:讲一下里面的参数以及功能
原型:int pthread_create((pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) 用法:#include <pthread.h> 功能:创建线程(实际上就是确定调用该线程函数的入口点),在线程创建以后,就开始运行相关的线程函数。 说明:thread:线程标识符; attr:线程属性设置; start_routine:线程函数的起始地址(这里我们写上我们需要守护的service); arg:传递给start_routine的参数; 返回值:成功,返回0;出错,返回-1。
然后是指针函数,返回值是指针的函数。有些难理解吧!我们类比一下, 如果是java的话,它就相当于run()方法。这下应该知道了吧!然后我们在讲一下原理:
这里在代码中我们明显可以看到while循环,为什么要循环呢?很简单,就是我们要不断的判断父进程是不是被干掉了,子进程反复的循环判断父进程是否被干掉,如果被干掉就说明小插件的服务被干掉了。这也就是为什么会出现耗电问题,其实有办法优化,有兴趣的老铁可以自己想想,或者查阅相关资料,下次再发一篇关于优化的。咋们继续,如果父进程被干掉了,那么它的子进程就会被init托管,而这个进程的id就是1。那么我们就要重启父进程,调用am.startservice,制定服务的进程id。
最后,上面都只是讲到从创建子进程拉起父进程,那么子进程咋办,所以我们还需要下面这个方法:
好了,现在基本已经写完了.cpp文件,讲的太多就容易感觉枯燥。然后生成.so文件,上次没讲到如果生成.so文件报这个错咋办,看下图:
这个错下面给了解决办法,我们不细说这个错是为什么。一讲又是很长,直接说解决办法,两种方法:
第一:创建Android.mk和Application.mk。(详见上文) 第二:在你的gradle.propperties文件加上这么一句话:android.deprecatedNdkCompileLease=1541151645526
OK,咋们继续小锤子一下。好了,暂时文章到此结束。谢谢大家花时间看这么枯燥的文章,如果有大神大看到文章中有什么地方有错误,希望直接指出,我会第一时间改进,因为不希望出现误人子弟,再次表示感谢。
由于我日常很忙,手里两三个项目,所以基本上很难抽时间出来分享,不过在经过几天的思想斗争后,我觉得再忙我也要写一些技术的文章,因为回顾,学习是很重要的,我想要进步。从下周开始每周分享四篇HTML+CSS+JS的文章,从基础到最后能开发项目为止(基础就是帮助没学过但想学习的人从头教,系统的学),加上固定两篇Android的技术文章(下周开始不固定源码解析,因为忙所以写关于源码的可能容易跳票。),有兴趣的希望大家一起学,共同进步。码字真的不容易,花了两个小时,因为我是所有的代码都是现写的,边写边截图真心累。
猜你喜欢
- 2024-10-27 NDK开发——FFmpeg视频解码 ffmpeg ndk
- 2024-10-27 Camera基本代码架构 camera calibrator
- 2024-10-27 android 功耗分析方法和优化(1) 功耗app
- 2024-10-27 Cocos Creator v2.3.2 发布了!全新 Launcher 效率飞起!
- 2024-10-27 如何androd动态注册编写计算器 淘宝动态评分计算器在线
- 2024-10-27 高通平台OV8856 Camera的bring up总结
- 2024-10-27 高通平台移植GC2145 Camera驱动 高通驱动安装
- 2024-10-27 《坎公骑冠剑》光炮Android Mk.99技能与背景故事
- 2024-10-27 ubuntu移植libwebp到Android平台 ubuntu移植到arm
- 2024-10-27 步步为营,十分钟学会 Native JNI(附带彩蛋)
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- oraclesql优化 (66)
- 类的加载机制 (75)
- feignclient (62)
- 一致性hash算法 (71)
- dockfile (66)
- 锁机制 (57)
- javaresponse (60)
- 查看hive版本 (59)
- phpworkerman (57)
- spark算子 (58)
- vue双向绑定的原理 (68)
- springbootget请求 (58)
- docker网络三种模式 (67)
- spring控制反转 (71)
- data:image/jpeg (69)
- base64 (69)
- java分页 (64)
- kibanadocker (60)
- qabstracttablemodel (62)
- java生成pdf文件 (69)
- deletelater (62)
- com.aspose.words (58)
- android.mk (62)
- qopengl (73)
- epoch_millis (61)
本文暂时没有评论,来添加一个吧(●'◡'●)