zoukankan      html  css  js  c++  java
  • 单实例应用程序

    一、概念:一个程序在系统中只能启动一个实例,这样的程序称为单实例应用程序。例如Windows下的任务管理器、回收站、播放器、文件系统等等。

    二、实现思想与方法:

    (1)核心思想:在当前系统中,只需要有能表示程序是否启动的标志,那么就可以利用它来实现单实例应用程序。

    (2)具体步骤:每当程序启动的时候,都需要先检测这个启动标志,当标志指示已经有实例存在,则当前程序退出,否则把标志置位,再运行业务。

    (3)实现单实例应用程序的方法:共享内存、绑定端口、命名管道、文件锁等等。

    三、实现案例:运用文件锁实现

    代码转载:http://www.cnblogs.com/highway-9/p/5517990.html

      1 /************************************************
      2 * 该例程讲解Linux下程序只运行一个实例的编程实现
      3 *
      4 * 编写只运行一个实例的程序有很多种方式,比如通过管道
      5 * 共享内存、文件锁等,主要是要有一个全局flag标志该程序
      6 * 已经在运行了,本程序使用文件锁来实现单实例
      7 ************************************************/
      8 #include <unistd.h>
      9 #include <fcntl.h>
     10 #include <sys/stat.h>   
     11 #include <sys/types.h>
     12 #include <errno.h>
     13 #include <stdio.h>
     14 #include <stdlib.h>
     15 #include <string.h>
     16 #include <string>
     17 
     18 #ifndef PATH_MAX
     19 #define PATH_MAX 1024   // 默认最大路径长度
     20 #endif
     21 
     22 std::string currentExeName()
     23 {
     24     char buf[PATH_MAX] = { '' };
     25 
     26     int ret = readlink("/proc/self/exe", buf, PATH_MAX);
     27     if (ret < 0 || ret >= PATH_MAX)
     28     {
     29         return "";
     30     }
     31 
     32     std::string path(buf);
     33     int pos = path.find_last_of("/");
     34     if (pos == -1)
     35     {
     36         return "";
     37     }
     38 
     39     path = path.substr(pos + 1, path.size() - 1);
     40 
     41     return path;
     42 }
     43 
     44 bool runSingleInstance()
     45 {
     46     // 获取当前可执行文件名
     47     std::string processName = currentExeName();
     48     if (processName.empty())
     49     {
     50         exit(1);
     51     }
     52 
     53     // 打开或创建一个文件
     54     std::string filePath = std::string("/var/run/") + processName + ".pid";
     55     int fd = open(filePath.c_str(), O_RDWR | O_CREAT, 0666);
     56     if (fd < 0)
     57     {
     58         printf("Open file failed, error : %s", strerror(errno));
     59         exit(1);
     60     }
     61 
     62     // 将该文件锁定
     63     // 锁定后的文件将不能够再次锁定
     64     struct flock fl;
     65     fl.l_type = F_WRLCK; // 写文件锁定
     66     fl.l_start = 0;
     67     fl.l_whence = SEEK_SET;
     68     fl.l_len = 0;
     69     int ret = fcntl(fd, F_SETLK, &fl);
     70     if (ret < 0)
     71     {
     72         if (errno == EACCES || errno == EAGAIN)
     73         {
     74             printf("%s already locked, error: %s
    ", filePath.c_str(), strerror(errno));
     75             close(fd);
     76             return false;
     77         }
     78     }
     79 
     80     // 锁定文件后,将该进程的pid写入文件
     81     char buf[16] = { '' };
     82     sprintf(buf, "%d", getpid());
     83     ftruncate(fd, 0);
     84     ret = write(fd, buf, strlen(buf));
     85     if (ret < 0)
     86     {
     87         printf("Write file failed, file: %s, error: %s
    ", filePath.c_str(), strerror(errno));
     88         close(fd);
     89         exit(1);
     90     }
     91 
     92     // 函数返回时不需要调用close(fd)
     93     // 不然文件锁将失效
     94     // 程序退出后kernel会自动close
     95     return true;
     96 }
     97 
     98 int main()
     99 {
    100     if (!runSingleInstance())
    101     {
    102         printf("Process is already running
    ");
    103         return 1;
    104     }
    105 
    106     printf("Process start...
    ");
    107     sleep(5);
    108     printf("Process end...
    ");
    109 
    110     return 0;
    111 }
  • 相关阅读:
    Linux中的防火墙
    Jinja2模板概述
    Ansible触发器-tag标签-忽略错误
    Ansible流程控制
    Ansible变量
    Play-book格式写法
    Redis哨兵(Sentinel)
    Redis 主从复制
    Redis介绍及安装
    Keepalived高可用集群搭建
  • 原文地址:https://www.cnblogs.com/yongqiang/p/6076153.html
Copyright © 2011-2022 走看看