Linux程序已运行实体的检测以及其PID的获得

程序中经常需要有这么一个功能:只允许本程序的单个实例运行,即不能多次运行一个程序。检测某个进程是否在运行,在shell中可以很轻松的用命令ps -A|grep xxx找出来,但对于程序来说,该怎么检测呢?我参考了aecium程序的方法:同样调用ps -A|grep xxx。也许会存在更先进的方法,比如dbus、系统信号量之类的技术,总之这个不会是最好的方法,不过且看看其技巧。

首先要获得当前进程的名字以便传给grep,一般通过main的argv[0]可得到运行时的程序名,不过要注意的是,通过路径运行的程序如./a.out,argv[0]也是./a.out的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
 
void program_unique_check(const char* program)
{
    FILE    *fd;
    pid_t   id = 0;
    char    command[50] = {0};
    char    pid_num[50] = {0};
    const char* program_name;
 
    program_name = strrchr (program, '/');
 
    //过滤得到程序的文件名
    if (program_name)
        ++program_name;
    else
        program_name = program;
 
    //组成执行的命令ps -Ao pid,comm|grep xxx
    sprintf(command, "ps -Ao pid,comm|grep %s", program_name);
 
    printf ("Command to excute: %s\n", command);
 
    //以管道方式执行命令
    if ( (fd = popen(command, "r")) == NULL ) {
        perror("popen");
        exit(EXIT_FAILURE);
    }
 
    //从管道读回执行结果,这里只为了取得PID,所以只读取前最多20个字符(PID不可能有那么长吧!)
    fgets(pid_num, 20, fd);
    printf ("Result :\n%s\n", pid_num);
 
    //转换结果字符为整形数值
    id = atoi(pid_num);
    printf ("DETECTED PID: %d\n", id);
 
    //判断是否自己
    if (getpid() == id)
        printf ("This's my self: %d\n", id);
    else {
        printf ("Here's one already running: %d\nI'll kill him!\n", id);
        //SIGKILL信号,当然也可以是其他信号的
        if ( kill (id, SIGKILL) == -1 ) {
    		perror("kill");
    		exit(EXIT_FAILURE);
        }
    }
}
 
int main (int argc, char**argv)
{
    program_unique_check(argv[0]);
    sleep (10);
    return 0;
}

本来还考虑,字符串传入atoi()要不要过滤,所以一开始还用了|awk ‘{print $1}’来给命令结尾,不过发现atoi只读取第一段有效数据来进行转换,就简化这点了。

ZDClient和ZLEVOClient都已经加入了运行实例检测的功能,-l参数可通过信号通知原运行程序离线。

文章分类 Programming, Unix/Linux 标签: , , ,
5 comments on “Linux程序已运行实体的检测以及其PID的获得
  1. bones7456说道:

    总觉得这个办法不太好.人家把 ZDClient 改个名字运行,就看不出来了…

  2. PT说道:

    确实~但是不同名字的程序算不算同一个程序呢?哈哈~

    一般用户没那么刁难的……

  3. B2Kee说道:

    哇,可怜才刚在学linux c 紧跟大牛步伐。。

  4. AzureSky说道:

    http://www.azuresky.net.ru/blog/read.php/14.htm

    只让程序执行一个副本,这是APUE的一个例子,你的实现很别扭,看来你没看过APUE,哈哈,要看看了

  5. PT说道:

    所以我说这不是最好的方法,呵呵.

    文件锁信号量锁等方法确实更常用,dhclient、apt都是用了文件锁的方法,而全局信号量锁在win下很常见;

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*