贴一个进程双守护,利用文件锁的特性来实现

Android中的保活机制 Android中的保活是一个永不过时的话题,因为每一个APP都希望能在后台不停的运行去搜集用户数据,在Android 系统处于较低版本的时候(目前最新版本为12,较低版本指的是8以下),很多APP借助于系统层面的漏洞研发出了各种保活的方法,但是随着Android 版本的不断更新,过往的保活方法渐渐失效,Android中的保活成为了一个越来越难办到的事情,但是我认为这是一个好事,如非这样你永远不知道你的手机后台到底有多少APP背着你干了多少事情。当然,系统的事情不是我们能掌控的了的。那么,我们先来看看以前为了 阅读详情
/*
 * SSIDMonitor.h
 *
 *  Created on: 2015-3-19
 *      Author: hgm
 */

#ifndef SSIDMONITOR_H_
#define SSIDMONITOR_H_

#include <jni.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_feizhang_ssidmonitor_MainActivity
 * Method:    uninstall
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_com_feizhang_ssidmonitor_MainActivity_uninstall(JNIEnv *,jobject, jstring,jint,jint,jstring);

#ifdef __cplusplus
}
#endif
#endif

这个是一个典型的java调用c语言的接口,贴在这里不是贴错了,而是本来就是为了实现一个安卓app而做的。顺便回忆一下c++的对象模型,因为看着这个为java调用的c接口是十分非常的顺眼啊。

JNIEXPORT dllexport 不解释,告诉编译器该函数导出

JNICALL   stdcall 不解释,告诉编译器该函数的参数压栈方式

void 函数返回值

Java_com_feizhang_ssidmonitor 包名

MainActivity需要扩展的java类

uninstall 需要扩展的java类成员函数

JNIENV*进程执行环境变量,可以理解为虚拟机句柄

jobject,扩展的java类实例

后面四个为成员函数参数


#include <stdio.h>
#include <jni.h>
#include <malloc.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <android/log.h>
#include "SSIDMonitor.h"
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>


#define LOG_TAG "System.out.c"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)

static const char* active_name  = "com.feizhang.ssidmonitor/com.feizhang.ssidmonitor.MainActivity";
static const char* connect_path = "/data/data/com.feizhang.ssidmonitor/my.sock";
static int using_sdk_version = 0;

/*
 * ret = 0 文件已经上锁
 * ret = 1 文件上锁
 * ret = -1 出错
 *
 * flock锁的释放非常具有特色,
 * 即可调用LOCK_UN参数来释放文件锁,
 * 也可以通过关闭fd的方式来释放文件锁(flock的第一个参数是fd),
 * 意味着flock会随着进程的关闭而被自动释放掉。
 *
 * 再此我们使用了这个函数的这个特性用来检测被监听进程是否还在存活
 * 之所以如此是因为安卓系统更新后(包括各种管家升级后)在清除进程时
 * 不再优雅清除而是直接kill掉,导致以前在析构函数中重启服务无法使
 * 用
 */
static int connected_fd = -1;
static int connected_alive(int get_lock,int closefd){
	int flag = get_lock ? (LOCK_EX|LOCK_NB) : (LOCK_UN);

	connected_fd = open(connect_path,O_RDWR|O_CREAT,0644);
	errno = 0;
	if(-1 == connected_fd){
		LOGE("open file failed : %d(%s)",errno,strerror(errno));
		return -1;
	}
	int ret = flock(connected_fd,flag);
	if(-1 == ret && EWOULDBLOCK != errno){
		LOGE("process is alive : ... %d(%s)",errno,strerror(errno));
		close(connected_fd);
		return -1;
	}
	LOGD("process locked file : ret = %d , errno = %d(%s)",ret,errno,strerror(errno));
	if(closefd) close(connected_fd);
	return 0 == ret;
}
/*
 * 重新启动宿主进程
 */
static void excute_active(){
	int ret = 0;
	if(using_sdk_version < 17){
		ret = execlp("am", "am", "start", "-n", active_name,(char*)NULL);
	}else{
		ret =execlp("am", "am", "start", "--user", "0","-n",active_name,(char*)NULL);
	}
	if(-1 == ret){
		LOGE("Execute a new active failed : %d(%s)",errno,strerror(errno));
	}
}
/**
 * 返回值 char* 这个代表char数组的首地址
 * Jstring2CStr 把java中的jstring的类型转化成一个c语言中的char 字符串
 */
char* Jstring2CStr(JNIEnv* env, jstring jstr) {
	char* rtn = NULL;
	jclass clsstring = env->FindClass("java/lang/String"); //String
	jstring strencode = env->NewStringUTF("GB2312"); // 得到一个java字符串 "GB2312"
	jmethodID mid = env->GetMethodID(clsstring, "getBytes","(Ljava/lang/String;)[B"); //[ String.getBytes("gb2312");
	jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid, strencode); // String .getByte("GB2312");
	jsize alen = env->GetArrayLength(barr); // byte数组的长度
	jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);
	if (alen > 0) {
		rtn = (char*) malloc(alen + 1); //"\0"
		memcpy(rtn, ba, alen);
		rtn[alen] = 0;
	}
	env->ReleaseByteArrayElements(barr, ba, 0); //
	return rtn;
}

/*
 * 扩展宿主进程的行为
 * 因为用java写一个守护进程比较困难
 * 所以在此使用ndk进行扩展,开启一个守护进程
 * 来监视宿主进程是否被杀死或者被卸载掉
 * */

extern "C"  JNIEXPORT void JNICALL Java_com_feizhang_ssidmonitor_MainActivity_uninstall(
		JNIEnv * env, jobject obj, jstring packageDir, jint sdkVersion,jint sleepTime,jstring reportUrl) {
	// 1,将传递过来的java的包名转为c的字符串
	char * pd = Jstring2CStr(env, packageDir);
	char * rp = Jstring2CStr(env,reportUrl);
	using_sdk_version = sdkVersion;

	/*
	 * 本函数调用多次导致守护进程也启动多次
	 * 原理:
	 * 当宿主进程第二次启动时,如果第一次
	 * */
	if(connected_alive(1,0) <= 0){
		LOGD("local port is using daemon process is running ...");
		return;
	}
	LOGD("packagedDir = %s,sleepTime = %d,reportURL = %s",pd,sleepTime,rp);
	// 2,创建当前进程的克隆进程
	pid_t pid = fork();

	// 3,根据返回值的不同做不同的操作,<0,>0,=0
	if (pid < 0) {
		// 说明克隆进程失败
		LOGD("current crate process failure");
		return;
	}
	if (pid > 0) {
		// 说明克隆进程成功,而且该代码运行在父进程中
		LOGD("crate process success,current parent pid = %d", pid);
		free(pd);
		free(rp);
		return;
	}

	//释放有可能继承自文件句柄以及锁资源
	close(connected_fd);
	// 说明克隆进程成功,而且代码运行在子进程中
	LOGD("crate process success,current child pid = %d", pid);
	// 4,在子进程中监视/data/data/包名这个目录
	for (; JNI_TRUE; sleep(sleepTime)) {
		FILE* file = fopen(pd, "rt");
		if (file == NULL) {
			break;
		}
		fclose(file);
		LOGD("app run normal,will be checked service ... %d",sleepTime);
		if(1 == connected_alive(1,1)){
			excute_active();
			//重启应用,守护进程退出
			return ;
		}
	}
	// 应用被卸载了,通知系统打开用户反馈的网页
	LOGD("app uninstall,current sdkversion = %d,url = %s", sdkVersion,rp);
	if (using_sdk_version < 17) {
		// Android4.2以前的版本无需指定用户
		execlp("am", "am", "start", "-a", "android.intent.action.VIEW", "-d",rp, (char*) NULL);
		return;
	}
	// Android4.2系统之后支持多用户操作,所以得指定用户
	execlp("am", "am", "start", "--user", "0", "-a","android.intent.action.VIEW", "-d", rp, (char*) NULL);
}


 注释已经很清楚了,就不解释了


mutex-node:使用文件锁(而不是redis)为Node.js跨进程命名为互斥体 互斥体 使用文件锁(而不是redis!)为Node.js跨进程命名为Mutex。 npm install https://github.com/Perennials/mutex-node 这是端口。 例子 var Mutex = require ( 'Mutex' ) ; var mutex = new Mutex ( 'should_happen_one_at_a_time' ) ; mutex . lock ( ) ; // .. do something and rest assured this is the only process doing it mutex . unlock ( ) ; 原料药 建设者 构造一个互斥体。 它以解锁状态启动。 您提供的名称在系统临时目录中作为带有扩展名.mutex的文件名使用,因此不要太喜欢该名称。 考虑到只有相互排斥的进程使用相同的 立即下载

相关推荐

linux守护进程加排它锁文件锁

在linux下实现守护进程并加上排它锁(文件锁),避免重复启动进程

Node.js 版本文件锁方法简介

我们平时在集群环境的时候加锁常常使用redis,如果就单pod实例某个操作想加锁再操作的话,不是用redis,可以考虑使用文件锁。 通常我们需要把nodejs的api文档放一下,这样方便查找一些api File system | Node.js v14.18.0 Documentation 一、File文件加锁 1、open版本 一开始通过百度回发现使用fs的open方法进行加锁。 var fs = require("fs"); fs.open("test.txt","wx",func.

xiangzaixiansheng的博客 2608

DELPHI进程守护源码

运行后,进程无法被关闭,关闭后会自动启动,永远无法结束,用途你懂的

nodejs中的共享资源和锁

在Node.js中,如果你使用锁来同步代码,通常是为了防止多个线程或进程同时访问共享资源,这可能导致数据不一致或其他问题。请注意,如果你的代码是多进程当在Node.js中使用锁来同步访问共享资源时,可以确保多个操作不会同时访问或修改共享资源,从而避免数据竞争和数据不一致的问题。例如,如果你知道某个操作可能需要更长的时间,可以考虑使用更细粒度的锁策略或避免长时间持有锁。使用release()方法: 如果你使用的是其他类型的锁或库,可能会有一个不同的方法来释放锁。// 在这里访问共享资源。

zz_ll9023的博客 1838

lock代码关于锁

lock 代码关于锁

文件锁(Delphi + C)

锁定选择的文件后,文件只能看到存在,不能被打开,运行,拷贝,删除.

【亲测免费】 Node.js 正确锁文件库:proper-lockfile 指南

Node.js 正确锁文件库:proper-lockfile 指南 项目介绍 Node.js Proper Lockfile 是一个为 Node.js 设计的高级文件锁定解决方案,旨在提供可靠且跨平台的文件锁机制。它通过解决并发访问场景下的竞态条件,确保多个进程在尝试访问共享资源(如配置文件、数据库连接字符串等)时能够安全地进行同步。此库特别关注兼容性和性能,适用于需要文件级互斥操作的应用。 ...

gitblog_00394的博客 677

Solidworks钣金设计:折弯系数、K因子与折弯扣除的实战应用解析

本文深入解析Solidworks钣金设计中折弯系数、K因子与折弯扣除的核心概念与实战应用。通过厘清三者间的逻辑关系与换算方法,并结合材料特性、工艺参数及车间实测,指导工程师精准确定展开长度,确保设计图纸与加工实物的一致性,有效提升钣金件设计精度与生产效率。

weixin_29268267的博客 921

Windows编程之双进程守护

Windows编程之双进程守护Windows编程之双进程守护 需求分析 设计原理 相关函数 设计详细 方法1 方法2 项目测试情况 方法1 方法2 总结 需求分析设计实现双进程守护程序,当两个进程同时运行时,关闭其中任意一个,另一个进程会识别出来并马上打开被关闭的进程。设计原理相关函数CreateEvent( ) CreateEvent是一个Windows API函数。它用来创建或打开一个命名的或

Birldlee的博客 6077

游程理论提取灾害事件特征V2---基于MATLAB语言的编程实现

游程理论,灾害事件,MATLAB

EWBA_GIS_RS_ER的博客 3793

GStreamer 源代码入门

GStreamer 是一个高度模块化的多媒体框架,其源代码结构清晰,设计精良。

深之JohnChen的专栏 953

基于文件锁的共享内存进程状态检测方案

共享内存是进程间通信(IPC)的高效方式,但也面临着"脆弱性"的困境。正如尼采所言,"所有伟大的事物都有着同样的命运:它们由自身的力量毁灭自己",共享内存也因其强大而存在内在的脆弱性。当进程异常终止时,它们往往无法正确清理共享资源,导致整个系统陷入不可用状态。

探索C++编程的奥秘,分享深入的技术见解和实践,旨在激发读者创造力与解决问题的思维。 1127

5、数据库基础概念与数据建模全解析

本文深入解析了数据库的基础概念,包括函数依赖、决定因素和多值依赖等关键依赖关系,同时探讨了数据建模的重要方法论,如IDEF1X、信息工程和陈方法。此外,还介绍了SQL Server管理工作室的图表功能,帮助用户进行数据库的可视化设计。通过本文,读者将掌握数据库设计的核心知识,为构建高效、可扩展的数据库系统奠定基础。

81

这就是守护进程嘛

守护进程的原理,进程组和会话,以及单实例的守护进程如何创建

duchenlong的博客 508

机器人外接 USB 音响完整配置指南

摘要:本文介绍了为机器人配置外接音响的方法。由于内置音响音量小且有散热噪音,建议使用Type-C接口外接音响。配置步骤包括:1)通过aplay -l命令查看音响端口信息;2)使用aplay命令测试音频播放;3)通过amixer命令设置音量。关键点在于正确识别音响的卡号(如card 2)和设备号(如device 0),并在命令中准确配置这些参数即可实现外接音响的正常使用。

m0_47999117的博客 356

3D扩散模型的构建与优化:多模态融合在三维物体生成中的作用【附核心代码实例】

随着技术的发展,基于扩散模型的3D内容生成已经成为一个激动人心的领域。通过不断优化扩散模型的结构和算法,结合多模态信息、视角控制和高效网络架构,未来的3D生成技术将不仅能够生成逼真的物体,还能满足虚拟现实、游戏设计、电影制作等行业对高质量、实时生成的需求。

一键难忘的博客 2862

Linux守护进程完全指南:从原理到实战

脱离终端、后台常驻、系统托管经典双 fork 作用:脱离进程组 + 杜绝终端重绑定风险四大强制初始化:切根目录、重置 umask、关闭 fd、脱离会话生产优先:syslog 日志、PID 文件锁、优雅信号、最小权限。

枕星而眠的博客 824

《AgentScope-Java 深入浅出教程》第2章 环境搭建与第一个智能体

创建// 【导入说明】/*** 时间相关工具类* 工具类是普通的 Java 类,通过注解声明为工具。* 智能体可以根据用户需求自动调用这些工具。*/// 【工具定义】获取当前时间@Tool(name = "get_current_time", // 工具名称:LLM 看到的名称description = "获取指定时区的当前时间" // 工具描述:帮助 LLM 理解何时使用// 【参数定义】// @ToolParam 的 name 属性是必需的!

步子哥的博客 417

Android后台保活技术深度解析:突破系统限制的进程守护方案

在Android开发领域,后台保活一直是开发者面临的重大技术挑战。从音乐播放中断到导航路线丢失,从即时消息延迟到健康监测数据丢失,这些用户体验痛点都源于Android系统对后台应用的严格管控。面对这一难题,AndroidKeepAlive项目通过创新的进程守护机制,为开发者提供了稳定可靠的后台保活解决方案。 ## 开发者痛点:后台存活率低下的现实困境 随着Android系统版本的不断升级,Go

gitblog_01022的博客 1019

把数字化转型真正落到组织里:读懂 SAP 的 OCM 六维框架

摘要: SAP的变革管理框架(OCM)强调数字化转型不仅是技术任务,更需关注组织与人的适应性。OCM包含六大维度:变革战略(明确方向与风险)、变革领导力(统一关键管理者行动)、变革沟通(分层传递信息)、变革实现(细化岗位级影响)、变革赋能(按角色设计培训)和变革有效性(持续评估)。该框架贯穿项目全周期,尤其在云项目中,需从早期规划变革策略,避免后期高代价调整。OCM的核心是将系统设计转化为组织语言,确保业务真正采纳新方式运作。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1433

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

守护进程的单实例实现

为了正常工作,守护进程应该实现为单实例的,也就是在任一时刻只运行该守护进程的一个副本,因为这个守护进程要排它的访问一个设备。这里需要用到文件锁的机制,如果守护进程创建一个文件,并且在整个文件上加上一把锁,那就只允许创建一把这样的写锁,在此之后如果试图再创建一把这样的写锁就将失败,以此向续守护进程副本指明已经有一个副本正在运行。而这个锁文件通常都放在/var/run目录中,锁文件的名字通常是name

打印/传真嵌入式开发--张志龙的专栏 8179

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

NFS 及文件锁

文件锁是一种确保当您访问文件时(通常是通过软件应用程序),在您完成检查之前没有人可以更改文件的行为。如果您想修改文件,则文件锁可确保在您完成修改之前没有其他人可以检查或修改文件。最早的 Unix 版本除了创建锁文件外,没有办法锁定文件。这个想法是两个或多个进程将或多或少地同时尝试通过 open() 系统调用的 O_EXCL 标志以独占模式创建锁文件。操作系统会将成功返回给赢得比赛的进程,并且将“文件存在”错误返回给失败的进程。这种方案的一个问题是它依赖于获胜进程在退出之前删除锁定文件。...

HHFQ的博客 2346

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

守护进程、进程组、会话

原文地址:http://blog.youkuaiyun.com/yuxue_23/article/details/12162785 1.进程、进程组与会话关系及其特性。 (1)  每个进程都有一个进程ID唯一识别(pid_t pid=getpid()); (2) 每个进程都属于一个进程组(getpgrp()),进程组属于一个会话(getsid(getpid())),是子集关系,即包含与被包含

不积跬步无以至千里 730

进程、进程组、会话以及守护进程

1.进程、进程组与会话关系及其特性。 (1)  每个进程都有一个进程ID唯一识别(pid_t pid=getpid()); (2) 每个进程都属于一个进程组(getpgrp()),进程组属于一个会话(getsid(getpid())),是子集关系,即包含与被包含。 (3) 进程组通常与同一作业相关联,接收同一终端的各种信号。进程组有唯一的进程组ID(类型与进程ID相同),可以有组长进程(进程

Linux学习笔记 3616

unix/linux 进程间文件锁

转自 http://www.cnblogs.com/hjslovewcl/archive/2011/03/14/2314333.html 有三种不同的文件锁,这三种都是“咨询性”的,也就是说它们依靠程序之间的合作,所以一个项目中的所有程序封锁政策的一致是非常重要的,当你的程序需要和第三方软件共享文件时应该格外地小心。有些程序利用诸如 FIlENAME.lock 的文件锁文件,然后简单地...

as_2014的博客 162

python守护进程运行_Python守护进程和脚本单例运行详解

本篇文章主要介绍了Python守护进程和脚本单例运行,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧一、简介守护进程最重要的特性是后台运行;它必须与其运行前的环境隔离开来,这些环境包括未关闭的文件描述符、控制终端、会话和进程组、工作目录以及文件创建掩码等;它可以在系统启动时从启动脚本/etc/rc.d中启动,可以由inetd守护进程启动,也可以有作业规划进程crond启...

weixin_39610678的博客 469
上一篇: 实例一
下一篇: c#使用sc命令注册开发Windows服务
FlyAnyWhere
博客等级 码龄24年 5粉丝 28原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值