在Linux下如何实现禁止运行该程序多次?
1. 声明:本程序因为使用了cs模型,所以解决方法的时候存在server端的配合。如果你没有server端的话,可能该方法不适合你。
2. 问题描述,动态库文件libabcd.so,提供api接口实现程序。但是这个api中涉及到串口通信,msgq等,就要考虑让该动态库只运行一个实例。
3. 使用进程名的办法判断该库是否运行在本案例中不太恰当,因为可能有不同名的进程使用了这个库,那是无法通过进程名来限制的。
4. 使用文件锁(临时文件,空文件)的方式,实验失败,比如意外终止进程(ctrl+c)的情况下,文件锁似乎就没有成功解锁,导致想再次运行的时候就无法启动,总是提示已存在进程,实际是无法给对应的文件加锁而导致的,处理的方法则必须手动删除上锁文件,才能再次运行该程序。
可能有人会说要捕获该信号试试,但应该考虑可能调用该库的进程可能会捕获该信号,这个时候两个捕获函数肯定有一个会失效,所以这个方法不行。终止进程的信号无法被捕获(和忽略),这又是另外一个问题了。
5. 我的解决办法:因为现在已有客户端和服务端,他们之间的通信是msgq(消息队列)。我就利用了服务端来记录客户端的pid号处理的。
5.1 api提供一个init的函数,这个函数是必须调用的,调用的时候,会获取进程id(getpid),并且把该进程pid通过msgq发送给server端。
//检查进程是否正在运行,防止运行多个进程
//返回0,表示第一次启动API,否则为多次,则应该不允许启动
static int isProcessRunning()
{
//2022-08-09改为msgq通信确认进程是否存在,发送pid过去
pid_t pid;
int ret = 0; //参数需要一个指针,返回函数返回值
pid = getpid(); //获得自己的pid
//查询是否存在api进程,让服务进程查询
if(api_send_and_waitack(eAPI_CHECK_APIRUN_CMD,pid,&ret)) //发送的第二个参数表示pid,参数3用于返回结果,0表示没有启动API,1表示已经存在,-1表示出错
{
printf("error : isProcessRunning pid = %d\n",pid);
return -1;
}
return ret;
}
5.2 server端(是守护进程),收到api的含有pid消息后,首先判断全局变量api_pid(初始值为0)记录的进程在系统中是否存在,不存在则用全局变量api_pid记录下刚刚收到的pid数据,并且给api返回0,表示允许刚刚的api进程启动。如果之前的pid还在系统中,则不记录收该pid,并且返回1,表示进程已经存在,不允许api再次启动。
case eAPI_CHECK_APIRUN_CMD: //判断API库是否已经在运行,防止API库被多个进程使用
// printf("server : eAPI_CHECK_APIRUN_CMD pid = %d\n",pmsgbuf->param1);
ret = check_api_running(); //看看是否存在
if(ret == 0)
{
// printf("server : eAPI_CHECK_APIRUN_CMD 111\n");
api_pid = pmsgbuf->param1; //记录该pid号
msgbuf.param1 = 0; //表示进程不存在
}
else
{
// printf("server : eAPI_CHECK_APIRUN_CMD 222\n");
msgbuf.param1 = 1; //表示进程存在
}
msgbuf.ret = 1; //表示有数据返回
break;
判断系统中是否存在某个pid的进程。
static int check_api_running(void)
{
char filename[256] = {0};
if(api_pid < 1) //不存在这样的进程
return 0;
snprintf(filename,sizeof filename,"/proc/%d/exe",api_pid);
printf("server : check_api_running filename = %s\n",filename);
if(access(filename,F_OK ) != -1)
{
printf("server : check_api_running access ok\n");
return 1; //进程已存在
}
printf("server : check_api_running access 0\n");
return 0; //进程不存在
}
5.3 api收到应答后,根据应答来决定是否继续运行进程,收到的值为0,表示可以继续启动,收到值为1,则退出,进程不再运行。
多次(可能小于100)测试(正常或异常终止api),暂时未发现问题。
可能大家还有其他思路,欢迎来多多指教交流。