单实例应用程序
一、概念:一个程序在系统中只能启动一个实例,这样的程序称为单实例应用程序。例如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] = { '\0' }; 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\n", filePath.c_str(), strerror(errno)); 75 close(fd); 76 return false; 77 } 78 } 79 80 // 锁定文件后,将该进程的pid写入文件 81 char buf[16] = { '\0' }; 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\n", 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\n"); 103 return 1; 104 } 105 106 printf("Process start...\n"); 107 sleep(5); 108 printf("Process end...\n"); 109 110 return 0; 111 }