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

Fra*_*lea 31 c linux pid process

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

Joh*_*ter 30

您可以在文件中查看pid条目/proc并在cmdline文件中检查您的过程,或者readlinkexe链接上执行(以下使用第一种方法).

#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;
}
Run Code Online (Sandbox Code Playgroud)


yuv*_*asy 14

这与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;
}
Run Code Online (Sandbox Code Playgroud)


RCL*_*RCL 14

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

无论如何,1997年Unix编程FAQ的第1.9节说:

使用kill()与0信号编号.此调用有四种可能的结果:

  • kill() 返回0

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

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

    具有给定PID的进程不存在,或者安全性增强导致系统拒绝其存在.(在某些系统上,该过程可能是一个僵尸.)

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

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

  • kill() 返回-1,其他值为 errno

    你有麻烦了!

最常用的技术是假设成功或失败EPERM 意味着该过程存在,而任何其他错误意味着它不存在.

  • 重新阅读你的问题之后...如果你想要的只是阻止进程运行两次,你可以创建一个具有唯一名称的命名内核对象(例如信号量或共享内存)并在开始时检查它是否存在.它可能比锁定文件更好,因为如果您的进程崩溃,它将自动消失. (2认同)