linux下c/c++实例之三只允许单个程序运行

来源:转载

一、简介

      Linux下允许本程序只运行一次,以防止对共享数据的破坏。linux各个版本下的检测程序都不相同,但思想相同,可以重复使用。

二、详解

1、Centos下的单程序运行

(1)代码singleton.cpp:

#include <unistd.h>#include <iostream>#include <fcntl.h>#include <string>#include <string.h>#include <libgen.h>#include <dirent.h>#include <stdio.h>#include <stdlib.h>using namespace std;bool is_prog_run(){ long pid; char full_name[1024] = {0}; char proc_name[1024] = {0}; int fd; pid = getpid(); cout<<"pid:"<<pid<<endl; sprintf(full_name, "/proc/%ld/cmdline", pid); if (access(full_name, F_OK) == 0) { fd = open(full_name, O_RDONLY); if (fd == -1) return false; //lseek(fd, 184, SEEK_SET); read(fd, proc_name, 1024); close(fd); } else { return false; } //cout<<"proc_name:"<<proc_name<<endl; char self_proc_name[512] = {0}; char *p = proc_name; int pt = 0; while(*p != ' ' && *p != '/0') { self_proc_name[pt] = *p; p++; pt++; } //cout<<"self_proc_name:"<<self_proc_name<<endl; string self_final_name = basename(self_proc_name); cout<<"self_final_name:"<<self_final_name<<endl; DIR *dir; struct dirent *result; dir = opendir("/proc"); while((result = readdir(dir)) != NULL) { if (!strcmp(result->d_name, ".") || !strcmp(result->d_name, "..") || !strcmp(result->d_name, "self") || atol(result->d_name) == pid) continue; memset(full_name, 0, sizeof(full_name)); memset(proc_name, 0 ,sizeof(proc_name)); sprintf(full_name, "/proc/%s/cmdline", result->d_name); if (access(full_name, F_OK) == 0) { fd = open(full_name,O_RDONLY); if (fd == -1) continue; //lseek(fd, 184, SEEK_SET); read(fd, proc_name, 1024); close(fd); char *q = proc_name; pt = 0; memset(self_proc_name, 0, sizeof(self_proc_name)); while(*q != ' ' && *q != '/0') { self_proc_name[pt] = *q; q++; pt++; } string other_final_name = basename(self_proc_name); if (self_final_name == other_final_name) { cout<<"other_final_name:"<<other_final_name<<endl; return true; } } } return false;}int main(int argc, char *argv[]){ int ch; if (is_prog_run()) { cout<<"ERROR:one aplication is running"<<endl; exit(1); } while(1){cout<<"go.........."<<endl;sleep(1);} return 0;}

(2)编译运行

g++ -o singleton singleton.cpp./singleton
一个终端先执行:

另一个终端再执行(提示错误,只能运行一个程序): 

2、AIX、HP、TRUE64下单程序运行

(1)代码singleton.cpp:
/**检测是否有相同的程序同时运行,包括AIX、HP、TRUE64*/#include <iostream>#include <string>#include <vector>#include <dirent.h>#include <unistd.h>#include <libgen.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <string.h>using namespace std;#define AIXtypedef bool(*CALL_BACK)(string, string);void string_to_array(const string& the_str, char delimiter, vector<string>& the_vector){ string dst = ""; int i; the_vector.resize(0); for (i = 0; i < the_str.length(); i++) { if (the_str[i] != delimiter) { if (the_str[i] == ' ') continue; dst += the_str[i]; } else { if (!dst.empty()) { the_vector.push_back(dst); dst = ""; } } } if (!dst.empty()) the_vector.push_back(dst);}bool is_prog_run_once(CALL_BACK call_back){#if defined(AIX) DIR* dirp; dirent ent; dirent* result; char full_name[1024]; int fd; long pid; char proc_name[1024]; pid = getpid(); sprintf(full_name, "/proc/%ld/psinfo", pid); if (access(full_name, F_OK) == 0) { fd = open(full_name, O_RDONLY); if (fd == -1) return false; lseek(fd, 184, SEEK_SET); read(fd, proc_name, 1024); close(fd); } else { return false; }#ifdef DEBUGRUN cout<<"full_name:"<<full_name<<endl; cout<<"proc_name:"<<proc_name<<endl;#endif vector<string> tmp_array; int ch; string_to_array(proc_name, ' ', tmp_array); char* self_argv[256]; //assert(tmp_array.size() <= 256); for (int i = 0; i < tmp_array.size(); i++) self_argv[i] = const_cast<char*>(tmp_array[i].c_str()); char sz_self_proc_name[512] ; strcpy(sz_self_proc_name, tmp_array[0].c_str()) ; string self_proc_name = basename(sz_self_proc_name); string self_host_id; string self_module_id; string self_proc_id; optind = 1; while ((ch = getopt(tmp_array.size(), self_argv, ":p:m:")) != -1) { switch (ch) { case 'm': self_module_id = optarg; break; case 'p': self_proc_id = optarg; break; } } dirp = opendir("/proc"); if (!dirp) return false;#ifdef DEBUGRUN cout<<"sz_self_proc_name:"<<sz_self_proc_name<<endl; cout<<"self_module_id:"<<self_module_id<<endl; cout<<"self_proc_id:"<<self_proc_id<<endl;#endif while (readdir_r(dirp, &ent, &result) == 0 && result != 0) { if (!strcmp(ent.d_name, ".") || !strcmp(ent.d_name, "..") || atol(ent.d_name) == pid) continue; sprintf(full_name, "/proc/%s/psinfo", ent.d_name); if (access(full_name, F_OK) == 0) { fd = open(full_name,O_RDONLY); if (fd == -1) continue; lseek(fd, 184, SEEK_SET); read(fd, proc_name, 1024); close(fd); string_to_array(proc_name, ' ', tmp_array); char* other_argv[256]; //assert(tmp_array.size() <= 256); for (int i = 0; i < tmp_array.size(); i++) other_argv[i] = const_cast<char*>(tmp_array[i].c_str()); char sz_other_proc_name[512] ; strcpy(sz_other_proc_name, tmp_array[0].c_str()) ; string other_proc_name = basename(sz_other_proc_name); string other_module_id; string other_proc_id; optind = 1; while ((ch = getopt(tmp_array.size(), other_argv, ":m:p:")) != -1) { switch (ch) { case 'm': other_module_id = optarg; break; case 'p': other_proc_id = optarg; break; } }#ifdef DEBUGRUN cout << "self_proc_name = [" << self_proc_name << "]" << std::endl ; cout << "other_proc_name = [" << other_proc_name << "]" << std::endl ;#endif if (/*self_proc_name != other_proc_name ||*/self_proc_id != other_proc_id) continue; if (self_module_id==other_module_id){ closedir(dirp); return true; } if(call_back!=NULL&&(*call_back)(self_module_id,other_module_id)){//返回true,则表式存在冲突的模块已经在运行 closedir(dirp); return true; } } } closedir(dirp); return false;#endif#ifdef HPUX pst_status proc_status ; vector<string> self_argvs ; vector<string> proc_argvs ; pid_t self_pid = getpid(); if (pstat_getproc(&proc_status, sizeof(struct pst_status), 0, self_pid) == 1) { string_to_array(proc_status.pst_cmd, ' ', self_argvs) ; if (self_argvs.size() < 7) { return false ; } } else { return false ; } proc_status.pst_idx = 0; while (1) { int nret ; nret = pstat_getproc(&proc_status, sizeof(struct pst_status), 1, proc_status.pst_idx) ; proc_status.pst_idx ++ ; if (nret == 1) { proc_argvs.clear() ; string_to_array(proc_status.pst_cmd, ' ', proc_argvs) ; if (proc_argvs.size() >= 7) { int i ; for ( i = 0; i < 7; i ++) { if (self_argvs[i] != proc_argvs[i]) break; } if (i >= 7 && proc_status.pst_pid != self_pid) { return true ; } } } else if (errno == EOVERFLOW) {// if match 64bits process and this program was compiled under 32bits mode this error would occur continue; } else break; } return false ;#endif#ifdef TRUE64 DIR* dirp; dirent ent; dirent* result; char full_name[1024]; int fd; long pid; char proc_name[1024]; struct prpsinfo psinfo ; char arglist[PSARGS_SZ + 1] ; int i ; pid = getpid(); sprintf(full_name, "/proc/%ld", pid); if (access(full_name, F_OK) == 0) { fd = open(full_name, O_RDONLY); if (fd == -1) return false; if (ioctl(fd, PIOCPSINFO, &psinfo) < 0) { close(fd) ; return false ; } close(fd); } else { return false; } vector<string> tmp_array; int ch; memcpy(arglist, psinfo.pr_psargs, PSARGS_SZ) ; arglist[PSARGS_SZ] = 0 ; for (i = 0; i < PSARGS_SZ; i ++) { arglist[i] = (arglist[i] == 0)?' ':arglist[i] ; } string_to_array(arglist, ' ', tmp_array); char* self_argv[256]; //assert(tmp_array.size() <= 256); for (int i = 0; i < tmp_array.size(); i++) self_argv[i] = const_cast<char*>(tmp_array[i].c_str()); char sz_self_proc_name[512] ; strcpy(sz_self_proc_name, tmp_array[0].c_str()) ; string self_proc_name = basename(sz_self_proc_name); string self_host_id; string self_module_id; string self_proc_id; vector<string> self_threads; optind = 1; while ((ch = getopt(tmp_array.size(), self_argv, ":h:m:p:t:")) != -1) { switch (ch) { case 'h': self_host_id = optarg; break; case 'm': self_module_id = optarg; break; case 'p': self_proc_id = optarg; break; case 't': self_threads.push_back(optarg); break; } } #ifdef DEBUGLY cout << "self_proc_name =[" << self_proc_name << "]" << std::endl ; cout << "self_host_id =[" << self_host_id << "]" << std::endl ; cout << "self_module_id =[" << self_module_id << "]" << std::endl ; cout << "self_proc_id =[" << self_proc_id << "]" << std::endl ; if (self_threads.size() > 0) { cout << "self_thread_id =[" << self_threads[0] << "]" << std::endl ; }#endif dirp = opendir("/proc");#ifdef DEBUGLY cout << "after opendir" << std::endl ;#endif if (!dirp) return false;#ifdef DEBUGLY cout << "before readdir_r" << std::endl ;#endif while (readdir_r(dirp, &ent, &result) == 0 && result != 0) { if (!strcmp(ent.d_name, ".") || !strcmp(ent.d_name, "..") || atol(ent.d_name) == pid) continue; sprintf(full_name, "/proc/%s", ent.d_name);#ifdef DEBUGLY cout << "full_name = [" << full_name << "]" << std::endl ;#endif if (access(full_name, F_OK) == 0) { fd = open(full_name,O_RDONLY); if (fd == -1) continue; if (ioctl(fd, PIOCPSINFO, &psinfo) < 0) { close(fd) ; continue ; } close(fd); memcpy(arglist, psinfo.pr_psargs, PSARGS_SZ) ; arglist[PSARGS_SZ] = 0 ; for (i = 0; i < PSARGS_SZ; i ++) { arglist[i] = (arglist[i] == 0)?' ':arglist[i] ; }#ifdef DEBUGLY cout << "before string_to_array other" << std::endl ;#endif string_to_array(arglist, ' ', tmp_array); char* other_argv[256]; //assert(tmp_array.size() <= 256); for (int i = 0; i < tmp_array.size(); i++) other_argv[i] = const_cast<char*>(tmp_array[i].c_str()); char sz_other_proc_name[512] ; strcpy(sz_other_proc_name, tmp_array[0].c_str()) ; string other_proc_name = basename(sz_other_proc_name); string other_host_id; string other_module_id; string other_proc_id; vector<string> other_threads; optind = 1; while ((ch = getopt(tmp_array.size(), other_argv, ":h:m:p:t:")) != -1) { switch (ch) { case 'h': other_host_id = optarg; break; case 'm': other_module_id = optarg; break; case 'p': other_proc_id = optarg; break; case 't': other_threads.push_back(optarg); break; } } #ifdef DEBUGLY cout << "other_proc_name =[" << other_proc_name << "]" << std::endl ; cout << "other_host_id =[" << other_host_id << "]" << std::endl ; cout << "other_module_id =[" << other_module_id << "]" << std::endl ; cout << "other_proc_id =[" << other_proc_id << "]" << std::endl ; cout << "---------------------------------------------" << std::endl << std::endl ;#endif if (self_proc_name != other_proc_name || self_host_id != other_host_id || self_module_id != other_module_id || self_proc_id != other_proc_id) continue; if (self_threads.size() == 0 || other_threads.size() == 0) return true; for (vector<string>::const_iterator iter = self_threads.begin(); iter != self_threads.end(); ++iter) { if (std::find(other_threads.begin(), other_threads.end(), *iter) != other_threads.end()) return true; } } } closedir(dirp); return false;#else return false;#endif}bool check_relation(string self, string other){ cout<<"self:"<<self<<endl; cout<<"other:"<<other<<endl; return false;}/*************测试代码***********/int main(){ CALL_BACK call_back = check_relation; bool flag = is_prog_run_once(call_back); cout<<"falg:"<<flag<<endl; while(1) {sleep(1);} return 0;}

三、总结

(1)读者可根据自己的操作系统选择相应的处理方式,系统不同可能结果会有出入。
(2)上述代码都是检测运行程序的程序名称,若系统中有重复的程序名称则不再使用,可以参考其他的更多的单程序运行方式。
(3)若有建议,请留言,在此先感谢!



分享给朋友:
您可能感兴趣的文章:
随机阅读: