以编程方式确定程序是否正在运行

发布于 2024-11-27 16:29:13 字数 73 浏览 2 评论 0原文

在 C 中,如何以编程方式找出进程是否已在 Linux/Ubuntu 上运行,以避免启动两次?我正在寻找类似于 pidof 的东西。

In C, how can I find out programmatically if a process is already running on Linux/Ubuntu to avoid having it start twice? I'm looking for something similar to pidof.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

醉酒的小男人 2024-12-04 16:29:13

您可以遍历 /proc 中的 pid 条目,并在 cmdline 文件中检查您的进程或执行 readlink > 在exe链接上(下面使用第一种方法)。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>

pid_t proc_find(const char* name) 
{
    DIR* dir;
    struct dirent* ent;
    char* endptr;
    char buf[512];

    if (!(dir = opendir("/proc"))) {
        perror("can't open /proc");
        return -1;
    }

    while((ent = readdir(dir)) != NULL) {
        /* if endptr is not a null character, the directory is not
         * entirely numeric, so ignore it */
        long lpid = strtol(ent->d_name, &endptr, 10);
        if (*endptr != '\0') {
            continue;
        }

        /* try to open the cmdline file */
        snprintf(buf, sizeof(buf), "/proc/%ld/cmdline", lpid);
        FILE* fp = fopen(buf, "r");

        if (fp) {
            if (fgets(buf, sizeof(buf), fp) != NULL) {
                /* check the first token in the file, the program name */
                char* first = strtok(buf, " ");
                if (!strcmp(first, name)) {
                    fclose(fp);
                    closedir(dir);
                    return (pid_t)lpid;
                }
            }
            fclose(fp);
        }

    }

    closedir(dir);
    return -1;
}


int main(int argc, char* argv[]) 
{
    if (argc == 1) {
        fprintf("usage: %s name1 name2 ...\n", argv[0]);
        return 1;
    }

    int i;
    for(int i = 1; i < argc; ++i) {
        pid_t pid = proc_find(argv[i]);
        if (pid == -1) {
            printf("%s: not found\n", argv[i]);
        } else {
            printf("%s: %d\n", argv[i], pid);
        }
    }

    return 0;
}

You can walk the pid entries in /proc and check for your process in either the cmdline file or perform a readlink on the exe link (The following uses the first method).

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>

pid_t proc_find(const char* name) 
{
    DIR* dir;
    struct dirent* ent;
    char* endptr;
    char buf[512];

    if (!(dir = opendir("/proc"))) {
        perror("can't open /proc");
        return -1;
    }

    while((ent = readdir(dir)) != NULL) {
        /* if endptr is not a null character, the directory is not
         * entirely numeric, so ignore it */
        long lpid = strtol(ent->d_name, &endptr, 10);
        if (*endptr != '\0') {
            continue;
        }

        /* try to open the cmdline file */
        snprintf(buf, sizeof(buf), "/proc/%ld/cmdline", lpid);
        FILE* fp = fopen(buf, "r");

        if (fp) {
            if (fgets(buf, sizeof(buf), fp) != NULL) {
                /* check the first token in the file, the program name */
                char* first = strtok(buf, " ");
                if (!strcmp(first, name)) {
                    fclose(fp);
                    closedir(dir);
                    return (pid_t)lpid;
                }
            }
            fclose(fp);
        }

    }

    closedir(dir);
    return -1;
}


int main(int argc, char* argv[]) 
{
    if (argc == 1) {
        fprintf("usage: %s name1 name2 ...\n", argv[0]);
        return 1;
    }

    int i;
    for(int i = 1; i < argc; ++i) {
        pid_t pid = proc_find(argv[i]);
        if (pid == -1) {
            printf("%s: not found\n", argv[i]);
        } else {
            printf("%s: %d\n", argv[i], pid);
        }
    }

    return 0;
}
素手挽清风 2024-12-04 16:29:13

这与 John Ledbetter 发布的代码相同。最好参考 /proc/pid/ 目录中名为 stat 的文件,而不是 cmdline,因为前者提供进程状态和进程名称。 cmdline 文件提供了启动进程的完整参数。所以在某些情况下会失败。无论如何,约翰给出的想法是好的。这里我贴出John修改后的代码。我正在Linux中寻找c代码来检查dhcp是否正在运行。有了这段代码,我就能够做到这一点。我希望它对像我这样的人有用。

#include <sys/types.h>
#include <dirent.h>
#include<unistd.h>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

pid_t proc_find(const char* name) 
{
    DIR* dir;
    struct dirent* ent;
    char buf[512];

    long  pid;
    char pname[100] = {0,};
    char state;
    FILE *fp=NULL; 

    if (!(dir = opendir("/proc"))) {
        perror("can't open /proc");
        return -1;
    }

    while((ent = readdir(dir)) != NULL) {
        long lpid = atol(ent->d_name);
        if(lpid < 0)
            continue;
        snprintf(buf, sizeof(buf), "/proc/%ld/stat", lpid);
        fp = fopen(buf, "r");

        if (fp) {
            if ( (fscanf(fp, "%ld (%[^)]) %c", &pid, pname, &state)) != 3 ){
                printf("fscanf failed \n");
                fclose(fp);
                closedir(dir);
                return -1; 
            }
            if (!strcmp(pname, name)) {
                fclose(fp);
                closedir(dir);
                return (pid_t)lpid;
            }
            fclose(fp);
        }
    }


closedir(dir);
return -1;
}


int main(int argc, char* argv[]) 
{
    int i;
    if (argc == 1) {
        printf("usage: %s name1 name2 ...\n", argv[0]);
        return 1;
    }

    for( i = 1; i < argc; ++i) {
        pid_t pid = proc_find(argv[i]);
        if (pid == -1) {
            printf("%s: not found\n", argv[i]);
        } else {
            printf("%s: %d\n", argv[i], pid);
        }
    }

    return 0;
}

This is the same as the code posted by John Ledbetter . It is good to refer to the file named stat in /proc/pid/ directory than cmdline since the former gives process states and process name. The cmdline file gives complete arguments with which the process is started. So that fails in some cases. Any way the idea given by John is good. Here I posted the modified code of John. I was looking for the code in c in Linux to check dhcp is running or not . With this code, I am able to do that. I hope it may be useful for someone like me.

#include <sys/types.h>
#include <dirent.h>
#include<unistd.h>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

pid_t proc_find(const char* name) 
{
    DIR* dir;
    struct dirent* ent;
    char buf[512];

    long  pid;
    char pname[100] = {0,};
    char state;
    FILE *fp=NULL; 

    if (!(dir = opendir("/proc"))) {
        perror("can't open /proc");
        return -1;
    }

    while((ent = readdir(dir)) != NULL) {
        long lpid = atol(ent->d_name);
        if(lpid < 0)
            continue;
        snprintf(buf, sizeof(buf), "/proc/%ld/stat", lpid);
        fp = fopen(buf, "r");

        if (fp) {
            if ( (fscanf(fp, "%ld (%[^)]) %c", &pid, pname, &state)) != 3 ){
                printf("fscanf failed \n");
                fclose(fp);
                closedir(dir);
                return -1; 
            }
            if (!strcmp(pname, name)) {
                fclose(fp);
                closedir(dir);
                return (pid_t)lpid;
            }
            fclose(fp);
        }
    }


closedir(dir);
return -1;
}


int main(int argc, char* argv[]) 
{
    int i;
    if (argc == 1) {
        printf("usage: %s name1 name2 ...\n", argv[0]);
        return 1;
    }

    for( i = 1; i < argc; ++i) {
        pid_t pid = proc_find(argv[i]);
        if (pid == -1) {
            printf("%s: not found\n", argv[i]);
        } else {
            printf("%s: %d\n", argv[i], pid);
        }
    }

    return 0;
}
还给你自由 2024-12-04 16:29:13

有一些方法可以避免 /proc 使用(并且可能有充分的理由这样做,例如 /proc 可能根本没有安装,和/或它可能已被安装)符号链接到一些欺骗性的东西,或者 pid 已隐藏在 /proc 中)。当然,下面的方法看起来不太好,我希望有一个合适的 API!

无论如何,1997 年 Unix 编程常见问题解答 的第 1.9 节说:

使用 kill()< /code> 其中 0 为信号编号。此调用有四种可能的结果:

  • kill() returns 0

    这意味着存在一个具有给定 PID 的进程,并且
    系统将允许您向其发送信号。这是
    取决于系统,该进程是否可能是僵尸进程。

  • kill() 返回 -1,errno == ESRCH

    要么不存在具有给定 PID 的进程,要么安全
    增强功能导致系统否认其存在。 (在
    在某些系统中,该进程可能是僵尸进程。)

  • kill() 返回 -1,errno == EPERM

    系统不允许您终止指定的进程。
    这意味着该进程存在(同样,它可能是一个
    僵尸)或严厉的安全增强存在(例如你的
    不允许进程向任何人发送信号。

  • kill() 返回 -1,以及 errno 的其他值

    你有麻烦了!

最常用的技术是使用 EPERM 来假设成功或失败
意味着该进程存在,任何其他错误都意味着它
没有。

There are ways to avoid /proc usage (and there might be good reasons to do so, e.g. /proc might not be installed at all, and/or it might have been symlinked to something deceptive, or that pid has been hidden in /proc). Granted, the below method doesn't look that good, I wish there were a proper API for that!

Anyway, section 1.9 of a 1997 Unix programming FAQ says:

Use kill() with 0 for the signal number. There are four possible results from this call:

  • kill() returns 0

    This implies that a process exists with the given PID, and the
    system would allow you to send signals to it. It is
    system-dependent whether the process could be a zombie.

  • kill() returns -1, errno == ESRCH

    Either no process exists with the given PID, or security
    enhancements are causing the system to deny its existence. (On
    some systems, the process could be a zombie.)

  • kill() returns -1, errno == EPERM

    The system would not allow you to kill the specified process.
    This means that either the process exists (again, it could be a
    zombie) or draconian security enhancements are present (e.g. your
    process is not allowed to send signals to anybody).

  • kill() returns -1, with some other value of errno

    You are in trouble!

The most-used technique is to assume that success or failure with EPERM
implies that the process exists, and any other error implies that it
doesn't.

帅气尐潴 2024-12-04 16:29:13

pidof 的工作原理是遍历/proc 文件系统。在 C 中,您可以通过枚举 /proc 来执行类似的操作;为每个 X 打开 /proc/X/cmdline ,其中 X 是一个或多个十进制数字的列表。我不知道您是否有任何可移植性要求,但如果您要依赖 /proc 的可用性,请记住这一点。

在类 UNIX 系统上,通过包装程序的启动并维护 PID 文件来更常见地解决此问题。有关此方法的经典示例,请参阅 /etc/init.d/*。您需要小心确保读取或写入 PID 文件的代码以安全的方式(原子地)执行此操作。如果您的目标操作系统有更强大的 init(例如 systemd),您可能能够将这项工作外包给那项工作。

pidof works by walking over the /proc filesystem. In C, you could do something similar by enumerating /proc; opening /proc/X/cmdline for every X where X is a list of one or more decimal numbers. I don't know if you have any portability requirements but bear that in mind if you are to rely on the availability of /proc.

This problem is more commonly solved on UNIX-like systems by wrapping the start-up of the program and maintaining a PID file. See /etc/init.d/* for classic examples of this approach. You will need to be careful to ensure that the code which reads of writes the PID file does so in a safe manner (atomically). If your target OS has a more capable init (such as systemd), you may be able to out source this work to that.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文