Подтвердить что ты не робот

API Linux для отображения запущенных процессов?

Мне нужен C/С++ API, который позволяет мне перечислять запущенные процессы в системе Linux и перечислять файлы, открытые каждым процессом.

Я не хочу напрямую читать/proc/файловую систему.

Может ли кто-нибудь подумать о способе сделать это?

4b9b3361

Ответ 1

http://procps.sourceforge.net/

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

Является источником ps и другими инструментами процесса. Они действительно используют proc (указывая, что это, вероятно, обычный и лучший способ). Их источник вполне читабельен. Файл

/procps-3.2.8/proc/readproc.c

Может быть полезно. Также полезное предложение как , отправленное ephemient, ссылается на API, предоставляемый libproc, который должен быть доступен в вашем репо (или уже установленном, я бы сказал), но вам понадобится вариант -dev для заголовков и что-нет.

Удача

Ответ 2

Если вы не хотите читать из '/proc. Затем вы можете рассмотреть возможность создания модуля Kernel, который будет реализовывать ваш собственный системный вызов. И ваш системный вызов должен быть написан так, чтобы он мог получить список текущих процессов, например:

/* 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");
    }

Приведенный выше код взят из моей статьи здесь, в http://linuxgazette.net/133/saha.html. Когда у вас есть свой системный вызов, вы можете позвонить ему из своего программа пользовательского пространства.

Ответ 3

Если вы этого не сделаете, я думаю, что любой API, который вы будете использовать, закончит чтение файловой системы /proc. Вот несколько примеров выполнения этой программы:

Но, к сожалению, это не API.

Ответ 4

Вот, пожалуйста (C/C++):

Вы могли бы найти это здесь: http://ubuntuforums.org/showthread.php?t=657097

По сути, он выполняет цикл по всем числовым папкам в /proc/<pid>, а затем выполняет ссылку для чтения в /proc/<pid>/exe или, если вам нужны аргументы командной строки cat /proc/<pid>/cmdline

Файловые дескрипторы, открытые процессом, находятся в /proc/<pid>/fd/<descriptor>, и вы получаете имя файла, делая ссылку на чтение для каждой символической ссылки, например, readlink /proc/<pid>/fd/<descriptor>. fd может быть устройством, таким как /dev/null, сокетом или файлом, и, возможно, другим.

#include

ссылка для чтения ssize_t (const char * path, char * buf, size_t bufsiz);
В случае успеха readlink() возвращает количество байтов, помещенных в buf.
При ошибке возвращается -1, и errno устанавливается для указания ошибки.

Кстати, это то же самое, что 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 ;
}

Ответ 5

PS и любой другой инструмент (EXCEPT для модулей ядра), начиная с /proc. /proc - это специальная файловая система, созданная на ходу ядром, так что процессы пользовательского режима могут читать данные, которые в противном случае будут доступны только для ядра.

Поэтому рекомендуемый способ - чтение из /proc.

Вы можете быстро интуитивно взглянуть на файловую систему /proc, чтобы увидеть, как ее структурировано. Для каждого процесса существует /proc/pid, где pid - номер идентификатора процесса. Внутри этой папки есть несколько файлов, которые содержат разные данные о текущем процессе. Если вы запустите

strace ps -aux

вы увидите, как программа ps считывает эти данные из /proc.

Ответ 6

Единственный способ сделать это без чтения /proc - это вызвать "ps aux", пройти через каждую строку, прочитать второй столбец (PID) и вызвать с ним lsof -p [PID].

... Я бы предложил чтение/proc;)

Ответ 7

Там находится библиотека libprocps из проекта procps-ng. В Ubuntu 13.04, если вы выполняете strace ps, вы можете видеть, что ps использует libprocps.

Ответ 8

Чтение proc не так уж плохо. Я не могу показать вам на С++, но следующий код 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);
    }
}

Ответ 9

Легкий способ запланировать 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);
}

Ответ 10

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *mystrstr(const char *haystack,const char *needle);
main()
{
    char *str1="abc dc abcd abce";
    char *str2="ab";
    char *ptr=NULL;
    int cnt=0;
    int offset=0;

    while(*str1)
    {
        ptr=mystrstr(str1,str2);
        if(ptr==NULL) 
           break;

        cnt++;
        offset=ptr-str1+strlen(str2);
        str1=str1+offset;
    }
    printf("Num of substr [%s] = %d\n",str2,cnt );
}

char *mystrstr(const char *haystack,const char *needle)
{
    int i=0,j=1;
    for(;haystack[i];i++)
    {
        if(needle[0]==haystack[i])
        {
            for(;needle[j];j++)
            {
                if(needle[j]==haystack[i+j] )
                {
                    if(needle[j]!='\0')
                    continue;
                }
                else
                 break;
            }
            if(needle[j]=='\0')
                return haystack + i;
            else if(haystack[i]!='\0')
                continue;
        }
        if(haystack[i]=='\0')
         return NULL;
    }
}