c++ afficher - API Linux pour lister les processus en cours?




pid commande (9)

J'ai besoin d'une API C / C ++ qui me permet de lister les processus en cours sur un système Linux, et de lister les fichiers ouverts par chaque processus.

Je ne veux pas finir par lire directement le système / proc / file.

Quelqu'un peut-il penser à un moyen de le faire?


Answers

http://procps.sourceforge.net/

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

Est la source de ps et d'autres outils de processus. Ils utilisent en effet proc (indiquant qu'il s'agit probablement de la méthode conventionnelle et la meilleure). Leur source est très lisible. Le fichier

/procps-3.2.8/proc/readproc.c

Peut être utile. Aussi une suggestion utile telle que postée par ephemient est de lier à l'API fournie par libproc , qui devrait être disponible dans votre repo (ou déjà installé je dirais) mais vous aurez besoin de la variation "-dev" pour les en-têtes et autres.

Bonne chance


Si vous ne voulez pas lire depuis '/ proc. Ensuite, vous pouvez envisager d'écrire un module noyau qui implémentera votre propre appel système. Et votre appel système doit être écrit afin qu'il puisse obtenir la liste des processus en cours, tels que:

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

Le code ci-dessus est tiré de mon article ici http://linuxgazette.net/133/saha.html Une fois que vous avez votre propre appel système, vous pouvez l'appeler à partir de votre programme d'espace utilisateur.


La seule façon de le faire sans lire / proc serait d'appeler "ps aux", passer par chaque ligne, lire la deuxième colonne (le PID) et appeler lsof -p [PID] avec.

... Je suggère de lire / proc;)


Lire proc n'est pas trop mal. Je ne peux pas vous montrer en C ++, mais le code D suivant devrait vous pointer dans la bonne direction:

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);
    }
}

Ici vous allez (C / C ++):

Vous auriez pu le trouver ici: http://ubuntuforums.org/showthread.php?t=657097

#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 ;
}

Il y a une bibliothèque libprocps du projet procps-ng . Sur Ubuntu 13.04, si vous faites strace ps , vous pouvez voir que ps utilise libprocps .


Moyen facile de pid fin de n'importe quel processus par nom

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);
}

Si vous ne le faites pas, je suppose que toute API que vous utiliserez finira par lire le système de fichiers / proc. Voici quelques exemples de programme faisant ceci:

Mais malheureusement, cela ne constitue pas une API.


J'utiliserais Valgrind et Callgrind comme base pour ma suite d'outils de profilage. Ce qu'il est important de savoir, c'est que Valgrind est essentiellement une machine virtuelle:

(wikipedia) Valgrind est essentiellement une machine virtuelle utilisant des techniques de compilation juste-à-temps (JIT), y compris la recompilation dynamique. Rien du programme original ne fonctionne directement sur le processeur hôte. Au lieu de cela, Valgrind convertit d'abord le programme en une forme temporaire, plus simple, appelée Intermediate Representation (IR), qui est une forme SSA non liée au processeur. Après la conversion, un outil (voir ci-dessous) est libre de faire toutes les transformations qu'il souhaite sur l'IR, avant que Valgrind ne convertisse l'IR en code machine et laisse le processeur hôte l'exécuter.

Callgrind est un profileur construit sur cela. Le principal avantage est que vous n'avez pas à exécuter votre application pendant des heures pour obtenir un résultat fiable. Même un deuxième passage est suffisant pour obtenir des résultats solides et fiables, car Callgrind est un profileur non- probing.

Un autre outil construit sur Valgrind est Massif. Je l'utilise pour profiler l'utilisation de la mémoire de tas. Cela fonctionne très bien. Qu'est-ce que cela fait, c'est qu'il vous donne des instantanés de l'utilisation de la mémoire - des informations détaillées QU'EST-CE QUE détient pourcentage de la mémoire, et que l'OMS avait mis là. Ces informations sont disponibles à différents moments de l'exécution de l'application.





c++ c linux api process