• 在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端。

    1. //检查进程是否正在运行,防止运行多个进程
    2. //返回0,表示第一次启动API,否则为多次,则应该不允许启动
    3. static int isProcessRunning()
    4. {
    5. //2022-08-09改为msgq通信确认进程是否存在,发送pid过去
    6. pid_t pid;
    7. int ret = 0; //参数需要一个指针,返回函数返回值
    8. pid = getpid(); //获得自己的pid
    9. //查询是否存在api进程,让服务进程查询
    10. if(api_send_and_waitack(eAPI_CHECK_APIRUN_CMD,pid,&ret)) //发送的第二个参数表示pid,参数3用于返回结果,0表示没有启动API,1表示已经存在,-1表示出错
    11. {
    12. printf("error : isProcessRunning pid = %d\n",pid);
    13. return -1;
    14. }
    15. return ret;
    16. }

    5.2 server端(是守护进程),收到api的含有pid消息后,首先判断全局变量api_pid(初始值为0)记录的进程在系统中是否存在,不存在则用全局变量api_pid记录下刚刚收到的pid数据,并且给api返回0,表示允许刚刚的api进程启动。如果之前的pid还在系统中,则不记录收该pid,并且返回1,表示进程已经存在,不允许api再次启动。

    1. case eAPI_CHECK_APIRUN_CMD: //判断API库是否已经在运行,防止API库被多个进程使用
    2. // printf("server : eAPI_CHECK_APIRUN_CMD pid = %d\n",pmsgbuf->param1);
    3. ret = check_api_running(); //看看是否存在
    4. if(ret == 0)
    5. {
    6. // printf("server : eAPI_CHECK_APIRUN_CMD 111\n");
    7. api_pid = pmsgbuf->param1; //记录该pid号
    8. msgbuf.param1 = 0; //表示进程不存在
    9. }
    10. else
    11. {
    12. // printf("server : eAPI_CHECK_APIRUN_CMD 222\n");
    13. msgbuf.param1 = 1; //表示进程存在
    14. }
    15. msgbuf.ret = 1; //表示有数据返回
    16. break;

    判断系统中是否存在某个pid的进程。 

    1. static int check_api_running(void)
    2. {
    3. char filename[256] = {0};
    4. if(api_pid < 1) //不存在这样的进程
    5. return 0;
    6. snprintf(filename,sizeof filename,"/proc/%d/exe",api_pid);
    7. printf("server : check_api_running filename = %s\n",filename);
    8. if(access(filename,F_OK ) != -1)
    9. {
    10. printf("server : check_api_running access ok\n");
    11. return 1; //进程已存在
    12. }
    13. printf("server : check_api_running access 0\n");
    14. return 0; //进程不存在
    15. }

     

    5.3 api收到应答后,根据应答来决定是否继续运行进程,收到的值为0,表示可以继续启动,收到值为1,则退出,进程不再运行。

    多次(可能小于100)测试(正常或异常终止api),暂时未发现问题。

     

    可能大家还有其他思路,欢迎来多多指教交流。

  • 相关阅读:
    SQL Server 2016(分离和附加数据库)
    Java强弱软虚4种引用
    sqoop学习
    本周投融报:NFT工具受资本青睐
    Vue:(四)数据代理
    1688阿里巴巴API 1688商品采集API 1688获取商品列表API 订单API
    使用 GitHub Action 自动更新 Sealos 集群的应用镜像
    iPhone 15 或将换成 USB-C 接口?网友:Lightning 已经落后了
    web网页设计实例作业HTML+CSS+JavaScript蔬菜水果商城购物设计
    【LeetCode】打砖块 [H](并查集)
  • 原文地址:https://blog.csdn.net/zhaozhi0810/article/details/126605946