在C语言中,我如何以编程方式找出Linux/Ubuntu上是否已经运行了某个进程,以避免它启动两次?我正在寻找类似于pidof的东西。
在C语言中,我如何以编程方式找出Linux/Ubuntu上是否已经运行了某个进程,以避免它启动两次?我正在寻找类似于pidof的东西。
您可以在/proc
中遍历pid
条目,并检查cmdline
文件中的进程或对exe
链接执行readlink
(以下使用第一种方法)。
#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;
}
#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;
}
有方法可以避免使用/proc
(这样做可能有很好的理由,例如/proc
可能根本没有安装,或者它可能被链接到某个欺骗性的东西中,或者该pid已经隐藏在/proc
中)。 值得注意的是,下面的方法看起来并不那么好,我希望有一个适当的API来解决这个问题!
无论如何,1997年Unix编程FAQ的第1.9节说:
使用带有0信号编号的kill()
。 这个调用有四种可能的结果:
kill()
返回 0
这意味着存在具有给定 PID 的进程,并且系统将允许您向其发送信号。进程是否为僵尸进程取决于系统。
kill()
返回 -1,errno
== ESRCH
要么不存在具有给定 PID 的进程,要么安全增强功能导致系统拒绝其存在。(在某些系统上,该进程可能是僵尸进程。)
kill()
返回 -1,errno
== EPERM
系统不允许您杀死指定的进程。这意味着进程存在(同样,它可能是僵尸进程),或者存在严格的安全增强功能(例如,您的进程不允许向任何人发送信号)。
kill()
返回 -1,并带有其他值的 errno
您有麻烦了!
EPERM
成功或失败意味着进程存在,而任何其他错误意味着它不存在。