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 AIX
typedef 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)若有建议,请留言,在此先感谢!

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乌托邦2号

博文不易,支持的请给予小小打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值