Linux API 列出正在运行的进程?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/939778/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 17:21:58  来源:igfitidea点击:

Linux API to list running processes?

c++clinuxapiprocess

提问by Thomi

I need a C/C++ API that allows me to list the running processes on a Linux system, and list the files each process has open.

我需要一个 C/C++ API,它允许我列出 Linux 系统上正在运行的进程,并列出每个进程打开的文件。

I do notwant to end up reading the /proc/ file system directly.

希望最终直接读取的/ proc /文件系统。

Can anyone think of a way to do this?

谁能想到一种方法来做到这一点?

采纳答案by Aiden Bell

http://procps.sourceforge.net/

http://procps.sourceforge.net/

http://procps.cvs.sourceforge.net/viewvc/procps/procps/proc/readproc.c?view=markup

http://procps.cvs.sourceforge.net/viewvc/procps/procps/proc/readproc.c?view=markup

Is the source of ps and other process tools. They do indeed use proc (indicating it is probably the conventional and best way). Their source is quite readable. The file

是ps等工艺工具的来源。他们确实使用 proc (表明它可能是传统和最好的方式)。他们的来源是相当可读的。文件

/procps-3.2.8/proc/readproc.c

May be useful. Also a useful suggestion as posted by ephemientis linking to the API provided by libproc, which should be available in your repo (or already installed I would say) but you will need the "-dev" variation for the headers and what-not.

可能有用。ephemient 发布的另一个有用的建议是链接到libproc提供的 API ,它应该在您的存储库中可用(或者我会说已经安装),但是您将需要标题和其他内容的“-dev”变体。

Good Luck

祝你好运

回答by shodanex

If you don't do it, then I guess whatever API you will use will end up reading the /proc filesystem. Here are some examples of program doing this:

如果您不这样做,那么我猜您将使用的任何 API 最终都会读取 /proc 文件系统。以下是一些执行此操作的程序示例:

But unfortunately, that does not constitute an API.

但不幸的是,这并不构成 API。

回答by Lennart Koopmann

The only way to do this without reading /proc would be to call "ps aux", go through every line, read the second column (the PID) and call lsof -p [PID] with it.

在不读取 /proc 的情况下执行此操作的唯一方法是调用“ps aux”,遍历每一行,读取第二列(PID)并使用它调用 lsof -p [PID]。

...I'd suggest reading /proc ;)

...我建议阅读 /proc ;)

回答by Lennart Koopmann

If you do not want to read from '/proc. Then you can consider writing a Kernel module which will implement your own system call. And your system call should be written so that it can obtain the list of current processes, such as:

如果您不想从 '/proc. 然后你可以考虑编写一个内核模块来实现你自己的系统调用。并且您的系统调用应该被写入,以便它可以获取当前进程的列表,例如:

/* ProcessList.c 
    Robert Love Chapter 3
    */
    #include < linux/kernel.h >
    #include < linux/sched.h >
    #include < linux/module.h >

    int init_module(void)
    {
    struct task_struct *task;
    for_each_process(task)
    {
    printk("%s [%d]\n",task->comm , task->pid);
    }

    return 0;
    }

    void cleanup_module(void)
    {
    printk(KERN_INFO "Cleaning Up.\n");
    }

The code above is taken from my article here at http://linuxgazette.net/133/saha.html.Once you have your own system call, you can call it from your user space program.

上面的代码取自我在http://linuxgazette.net/133/saha.html 上的文章。一旦您有了自己的系统调用,就可以从您的用户空间程序中调用它。

回答by daniel

PS and every other tool(EXCEPT for Kernel Modules) read from /proc. /procis a special filesystem created on the fly by the kernel so that user mode processes can read data that will otherwise only be available for the kernel.

PS 和所有其他工具(内核模块除外)从/proc. /proc是由内核动态创建的特殊文件系统,以便用户模式进程可以读取否则只能用于内核的数据。

The recommended way is therefore, reading from /proc.

因此,推荐的方法是从/proc.

You can quickly intuitively look at the /procfilesystem to see how its structured. For every process there is a /proc/pidwhere pid is the process id number. Inside this folder there are several files which include different data about the current process. If you run

您可以快速直观地查看/proc文件系统以了解其结构。对于每个进程,/proc/pid其中 pid 是进程 ID 号。在此文件夹中有几个文件,其中包含有关当前进程的不同数据。如果你跑

strace ps -aux

you will see how the program psreads this data from /proc.

您将看到程序如何ps/proc.

回答by daniel

Reading proc is not too bad. I can't show you in C++, but the following D code should point you in the right direction:

阅读proc还不错。我无法用 C++ 向您展示,但以下 D 代码应该为您指明正确的方向:

import std.stdio;
import std.string;
import std.file;
import std.regexp;
import std.c.linux.linux;

alias std.string.split explode;

string srex = "^/proc/[0-9]+$";
string trex = "State:[ \t][SR]";
RegExp rex;
RegExp rext;

   string[] scanPidDirs(string target)
   {
      string[] result;

      bool callback(DirEntry* de)
      {
         if (de.isdir)
         {
            if (rex.find(de.name) >= 0)
            {
                string[] a = explode(de.name, "/");
                string pid = a[a.length-1];
                string x = cast(string) std.file.read(de.name ~ "/status");
                int n = rext.find(x);
                if  (n >= 0)
                {
                    x = cast(string) std.file.read(de.name ~ "/cmdline");
                    // This is null terminated
                    if (x.length) x.length = x.length-1;
                    a = explode(x, "/");
                    if (a.length)
                       x = a[a.length-1];
                    else
                       x = "";
                     if  (x == target)
                    {
                        result ~= pid ~ "/" ~x;
                    }
                }
             }
          }
          return true;
      }

      listdir("/proc", &callback);
      return result.dup;
   }

void main(string[] args)
{
    rex= new RegExp(srex);
    rext= new RegExp(trex);
    string[] a = scanPidDirs(args[1]);
    if (!a.length)
    {
        writefln("Not found");
        return;
    }
    writefln("%d matching processes", a.length);
    foreach (s; a)
    {
       string[] p = explode(s, "/");
       int pid = atoi(p[0]);
       writef("Stop %s (%d)? ", s, pid);
       string r = readln();
       if (r == "Y\n" || r == "y\n")
          kill(pid, SIGUSR1);
    }
}

回答by Stefan Steiger

Here you go (C/C++):

给你(C/C++):

You could have found it here: http://ubuntuforums.org/showthread.php?t=657097

你可以在这里找到它:http: //ubuntuforums.org/showthread.php?t=657097

Essentially, what it does is loop through all numeric folders in /proc/<pid>, and then it does a readlink on /proc/<pid>/exe, or if you want the command-line-arguments cat /proc/<pid>/cmdline

本质上,它的作用是遍历 中的所有数字文件夹/proc/<pid>,然后在 上执行读取链接/proc/<pid>/exe,或者如果您想要命令行参数cat /proc/<pid>/cmdline

The file-descriptors open by the process are in /proc/<pid>/fd/<descriptor>, and you get the file name by doing a readlink on each symlink, e.g. readlink /proc/<pid>/fd/<descriptor>. fd can be a device, such as /dev/null, a socket, or a file, and potentially more.

进程打开/proc/<pid>/fd/<descriptor>的文件描述符在readlink /proc/<pid>/fd/<descriptor>. fd 可以是一个设备,例如 /dev/null、一个套接字或一个文件,可能还有更多。

#include <unistd.h>

ssize_t readlink(const char *path, char *buf, size_t bufsiz);
On success, readlink() returns the number of bytes placed in buf.
On error, -1 is returned and errno is set to indicate the error.

#include <unistd.h>

ssize_t readlink(const char *path, char *buf, size_t bufsiz);
成功时,readlink() 返回放置在 buf 中的字节数。
出错时,返回 -1 并设置 errno 以指示错误。

This is, by the way, the same that readproc.cdoes (or at least did).
Of course, hopefully they did it without buffer overflow possiblity.

顺便说一下,这与readproc.c(或至少是)相同。
当然,希望他们在没有缓冲区溢出的情况下做到了。

#ifndef __cplusplus
    #define _GNU_SOURCE
#endif

#include <unistd.h>
#include <dirent.h>
#include <sys/types.h> // for opendir(), readdir(), closedir()
#include <sys/stat.h> // for stat()

#ifdef __cplusplus
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdarg>
#else
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdarg.h>
#endif


#define PROC_DIRECTORY "/proc/"
#define CASE_SENSITIVE    1
#define CASE_INSENSITIVE  0
#define EXACT_MATCH       1
#define INEXACT_MATCH     0


int IsNumeric(const char* ccharptr_CharacterList)
{
    for ( ; *ccharptr_CharacterList; ccharptr_CharacterList++)
        if (*ccharptr_CharacterList < '0' || *ccharptr_CharacterList > '9')
            return 0; // false
    return 1; // true
}


int strcmp_Wrapper(const char *s1, const char *s2, int intCaseSensitive)
{
    if (intCaseSensitive)
        return !strcmp(s1, s2);
    else
        return !strcasecmp(s1, s2);
}

int strstr_Wrapper(const char* haystack, const char* needle, int intCaseSensitive)
{
    if (intCaseSensitive)
        return (int) strstr(haystack, needle);
    else
        return (int) strcasestr(haystack, needle);
}


#ifdef __cplusplus
pid_t GetPIDbyName(const char* cchrptr_ProcessName, int intCaseSensitiveness, int intExactMatch)
#else
pid_t GetPIDbyName_implements(const char* cchrptr_ProcessName, int intCaseSensitiveness, int intExactMatch)
#endif
{
    char chrarry_CommandLinePath[100]  ;
    char chrarry_NameOfProcess[300]  ;
    char* chrptr_StringToCompare = NULL ;
    pid_t pid_ProcessIdentifier = (pid_t) -1 ;
    struct dirent* de_DirEntity = NULL ;
    DIR* dir_proc = NULL ;

    int (*CompareFunction) (const char*, const char*, int) ;

    if (intExactMatch)
        CompareFunction = &strcmp_Wrapper;
    else
        CompareFunction = &strstr_Wrapper;


    dir_proc = opendir(PROC_DIRECTORY) ;
    if (dir_proc == NULL)
    {
        perror("Couldn't open the " PROC_DIRECTORY " directory") ;
        return (pid_t) -2 ;
    }

    // Loop while not NULL
    while ( (de_DirEntity = readdir(dir_proc)) )
    {
        if (de_DirEntity->d_type == DT_DIR)
        {
            if (IsNumeric(de_DirEntity->d_name))
            {
                strcpy(chrarry_CommandLinePath, PROC_DIRECTORY) ;
                strcat(chrarry_CommandLinePath, de_DirEntity->d_name) ;
                strcat(chrarry_CommandLinePath, "/cmdline") ;
                FILE* fd_CmdLineFile = fopen (chrarry_CommandLinePath, "rt") ;  // open the file for reading text
                if (fd_CmdLineFile)
                {
                    fscanf(fd_CmdLineFile, "%s", chrarry_NameOfProcess) ; // read from /proc/<NR>/cmdline
                    fclose(fd_CmdLineFile);  // close the file prior to exiting the routine

                    if (strrchr(chrarry_NameOfProcess, '/'))
                        chrptr_StringToCompare = strrchr(chrarry_NameOfProcess, '/') +1 ;
                    else
                        chrptr_StringToCompare = chrarry_NameOfProcess ;

                    //printf("Process name: %s\n", chrarry_NameOfProcess);
                    //printf("Pure Process name: %s\n", chrptr_StringToCompare );

                    if ( CompareFunction(chrptr_StringToCompare, cchrptr_ProcessName, intCaseSensitiveness) )
                    {
                        pid_ProcessIdentifier = (pid_t) atoi(de_DirEntity->d_name) ;
                        closedir(dir_proc) ;
                        return pid_ProcessIdentifier ;
                    }
                }
            }
        }
    }
    closedir(dir_proc) ;
    return pid_ProcessIdentifier ;
}

#ifdef __cplusplus
    pid_t GetPIDbyName(const char* cchrptr_ProcessName)
    {
        return GetPIDbyName(cchrptr_ProcessName, CASE_INSENSITIVE, EXACT_MATCH) ;
    }
#else
    // C cannot overload functions - fixed
    pid_t GetPIDbyName_Wrapper(const char* cchrptr_ProcessName, ... )
    {
        int intTempArgument ;
        int intInputArguments[2] ;
        // intInputArguments[0] = 0 ;
        // intInputArguments[1] = 0 ;
        memset(intInputArguments, 0, sizeof(intInputArguments) ) ;
        int intInputIndex ;
        va_list argptr;

        va_start( argptr, cchrptr_ProcessName );
            for (intInputIndex = 0;  (intTempArgument = va_arg( argptr, int )) != 15; ++intInputIndex)
            {
                intInputArguments[intInputIndex] = intTempArgument ;
            }
        va_end( argptr );
        return GetPIDbyName_implements(cchrptr_ProcessName, intInputArguments[0], intInputArguments[1]);
    }

    #define GetPIDbyName(ProcessName,...) GetPIDbyName_Wrapper(ProcessName, ##__VA_ARGS__, (int) 15)

#endif

int main()
{
    pid_t pid = GetPIDbyName("bash") ; // If -1 = not found, if -2 = proc fs access error
    printf("PID %d\n", pid);
    return EXIT_SUCCESS ;
}

回答by Craig McQueen

There's a library libprocpsfrom the procps-ngproject. On Ubuntu 13.04, if you do strace ps, then you can see that psuses libprocps.

有一个图书馆libprocpsprocps-ng项目。在 Ubuntu 13.04 上,如果你这样做了strace ps,那么你可以看到它ps使用libprocps.

回答by Md Muazzam

Easy way to fin pid of any process by name

按名称查找任何进程的 pid 的简单方法

pid_t GetPIDbyName(char* ps_name)
{

    FILE *fp;
    char *cmd=(char*)calloc(1,200);
    sprintf(cmd,"pidof %s",ps_name);
    fp=popen(cmd,"r");
    fread(cmd,1,200,fp);
    fclose(fp);
    return atoi(cmd);
}