Linux编程之《只运行一个实例》以及动态获取当前程序名称
2016-10-30 22:29
811 查看
转载自:http://www.cnblogs.com/highway-9/p/5517990.html
linux平台中实现程序单例运行,以及动态获取当前程序名称
有些时候,我们要求一个程序在系统中只能启动一个实例。比如,Windows自带的播放软件Windows Medea Player在Windows里就只能启动一个实例。原因很简单,如果同时启动几个实例,却播放不同的文件,那么声音和图像就会引起混乱。在设计模式中,就有一个SINGLETON模式。对于程序而言,我们只有在程序启动的时候去检测某个设置,如果程序没有启动,就把设置更新为程序已经启动,然后正常启动程序;如果程序已经启动,那么就终止程序的启动。在程序退出的时候把设置恢复为程序没有启动。按照上面的思路,我们很容易就能想出一些方法:
文件锁
共享内存
管道
注册表(windows实现)
etc...
该实例是使用文件锁来实现单例的,下面将完整代码贴上。
linux平台中实现程序单例运行,以及动态获取当前程序名称
概述
有些时候,我们要求一个程序在系统中只能启动一个实例。比如,Windows自带的播放软件Windows Medea Player在Windows里就只能启动一个实例。原因很简单,如果同时启动几个实例,却播放不同的文件,那么声音和图像就会引起混乱。在设计模式中,就有一个SINGLETON模式。对于程序而言,我们只有在程序启动的时候去检测某个设置,如果程序没有启动,就把设置更新为程序已经启动,然后正常启动程序;如果程序已经启动,那么就终止程序的启动。在程序退出的时候把设置恢复为程序没有启动。按照上面的思路,我们很容易就能想出一些方法:文件锁
共享内存
管道
注册表(windows实现)
etc...
该实例是使用文件锁来实现单例的,下面将完整代码贴上。
/************************************************ * 该例程讲解Linux下程序只运行一个实例的编程实现 * * 编写只运行一个实例的程序有很多种方式,比如通过管道 * 共享内存、文件锁等,主要是要有一个全局flag标志该程序 * 已经在运行了,本程序使用文件锁来实现单实例 ************************************************/ #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <string> #ifndef PATH_MAX #define PATH_MAX 1024 // 默认最大路径长度 #endif std::string currentExeName() { char buf[PATH_MAX] = {'\0'}; int ret = readlink("/proc/self/exe", buf, PATH_MAX); if (ret < 0 || ret >= PATH_MAX) { return ""; } std::string path(buf); int pos = path.find_last_of("/"); if (pos == -1) { return ""; } path = path.substr(pos + 1, path.size() - 1); 4000 return path; } bool runSingleInstance() { // 获取当前可执行文件名 std::string processName = currentExeName(); if (processName.empty()) { exit(1); } // 打开或创建一个文件 std::string filePath = std::string("/var/run/") + processName + ".pid"; int fd = open(filePath.c_str(), O_RDWR | O_CREAT, 0666); if (fd < 0) { printf("Open file failed, error : %s", strerror(errno)); exit(1); } // 将该文件锁定 // 锁定后的文件将不能够再次锁定 struct flock fl; fl.l_type = F_WRLCK; // 写文件锁定 fl.l_start = 0; fl.l_whence = SEEK_SET; fl.l_len = 0; int ret = fcntl(fd, F_SETLK, &fl); if (ret < 0) { if (errno == EACCES || errno == EAGAIN) { printf("%s already locked, error: %s\n", filePath.c_str(), strerror(errno)); close(fd); return false; } } // 锁定文件后,将该进程的pid写入文件 char buf[16] = {'\0'}; sprintf(buf, "%d", getpid()); ftruncate(fd, 0); ret = write(fd, buf, strlen(buf)); if (ret < 0) { printf("Write file failed, file: %s, error: %s\n", filePath.c_str(), strerror(errno)); close(fd); exit(1); } // 函数返回时不需要调用close(fd) // 不然文件锁将失效 // 程序退出后kernel会自动close return true; } int main() { if (!runSingleInstance()) { printf("Process is already running\n"); return 1; } printf("Process start...\n"); sleep(5); printf("Process end...\n"); return 0; }
相关文章推荐
- Linux Socket编程实例(一个Hello World程序)
- Windows & Linux(Unix) 获取当前程序运行目录
- Unix/Linux环境C编程入门教程(22) C/C++如何获取程序的运行时间
- linux 使用非当前登录运行程序方式,如root登录用test运行一个test.sh
- Linux Socket编程实例(一个Hello World程序)
- python获取当前运行函数名称的方法实例代码
- Delphi编程获取系统当前进程、窗口句柄、文件属性以及程序运行状态(8种应用)
- Windows & Linux(Unix) 获取当前程序运行目录
- 保证程序只有一个实例运行 &&& 动态调用DLL的研究
- Unix/Linux环境C编程入门教程(22) C/C++如何获取程序的运行时间
- 获取当前运行程序的名称或者是路径
- 图片 缩略 和 水印 以及 C#获取当前程序运行路径的方法集合
- Linux编程之《只运行一个实例》
- Java反射代码--01.通过类名称加载一个类并且获取当前类实例
- [linux基础] 通过进程id获取运行程序的程序名称
- 动态获取程序的版本名称的方法以及dialog的简单用法以及两种上下文的区别
- UNIX-LINUX编程实践教程->第八章->实例代码注解->写一个简单的shell->在shell中启动另一个程序
- Linux Socket编程实例(一个Hello World程序)
- 如何统计一个程序打开的实例个数,及当前在运行的个数
- Linux Socket编程实例(一个Hello World程序)