web-dev-qa-db-fra.com

API Linux pour lister les processus en cours?

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

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

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

47
Thomi

http://procps.sourceforge.net/

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

Est la source de ps et autres outils de processus. Ils utilisent en effet proc (indiquant que c'est probablement le moyen conventionnel et le meilleur). Leur source est assez lisible. Le fichier

/procps-3.2.8/proc/readproc.c

Peut être utile. Aussi, une suggestion utile comme posted by ephemient est un lien vers l'API fournie par libproc, qui devrait être disponible dans votre référentiel (ou déjà installée, je dirais) mais vous aurez besoin de la variante "-dev" pour les en-têtes et quoi-pas.

Bonne chance

39
Aiden Bell

Si vous ne voulez pas lire dans '/ proc. Ensuite, vous pouvez envisager d’écrire un module de noyau qui implémentera votre propre appel système. Et votre appel système doit être écrit pour pouvoir 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 à l'adresse 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.

23
user59634

Ici vous allez (C/C++):

Vous pourriez l'avoir trouvé 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 ;
}
7
Stefan Steiger

Si vous ne le faites pas, alors je suppose que l’API que vous utiliserez lira le système de fichiers/proc. Voici quelques exemples de programme faisant cela:

Mais malheureusement, cela ne constitue pas une API.

7
shodanex

PS et tous les autres outils (SAUF pour les modules de noyau) sont lus à partir de /proc. /proc est un système de fichiers spécial créé à la volée par le noyau afin que les processus en mode utilisateur puissent lire des données qui ne seraient autrement disponibles que pour le noyau. 

La manière recommandée est donc de lire à partir de /proc.

Vous pouvez rapidement et intuitivement examiner le système de fichiers /proc pour voir comment il se structure . Pour chaque processus, il existe un /proc/pid où pid est le numéro d'identification du processus. Dans ce dossier, vous trouverez plusieurs fichiers contenant différentes données sur le processus en cours.

strace ps -aux

vous verrez comment le programme ps lit ces données à partir de /proc.

5
daniel

Il existe une bibliothèque libprocps à partir du projet procps-ng . Sur Ubuntu 13.04, si vous utilisez strace ps, alors vous pouvez voir que ps utilise libprocps.

3
Craig McQueen

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

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

3
Lennart Koopmann

Lire proc n'est pas trop mauvais. Je ne peux pas vous montrer en C++, mais le code D suivant devrait vous orienter 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 = "État: [\ t] [SR]" ;
 RegExp rex; 
 RegExp rext; 

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

 rappel de bool (DirEntry * de) 
 {
 if (de.isdir) 
 {
 if (rex.find (de.name)> = 0) 
 {
 string [] a = explode (de.name, "/");
 string pid = a [longueur.a1]; 
 string x = cast (string) std.file.read (de.name ~ "/status");
 int n = rext.find (x); 
 si (n> = 0) 
 {
 x = cast (chaîne) std.file.read (de.name ~ "/cmdline");
 // Ceci est null terminé 
 si (x.length) x.length = x.length-1; 
 a = exploser (x, "/");
 si (une.longueur) 
 x = a [longueur.a1]; 
 autre
 x = ""; 
 si (x == cible) 
 {
 résultat ~ = pid ~ "/" ~ x; 
 } 
 } 
 } 
 } 
 retourne vrai; 
 } 

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

 void main (string [] args) 
 {
 rex = new RegExp (srex); 
 rext = new RegExp (trex); 
 string [] a = scanPidDirs (args [1]); 
 si (! a.length) 
 {
 writefln ("Introuvable"); 
 revenir;
 } 
 writefln ("% d processus correspondants", a.length); 
 foreach (s; a) 
 {
 string [] p = exploser (s, "/");
 int pid = atoi (p [0]); 
 writef ("Stop% s (% d)?", s, pid); 
 chaîne r = readln (); 
 if (r == "Y\n" || r == "y\n") 
 tuer (pid, SIGUSR1); 
 } 
} 
2
user253411

Un moyen facile de trouver le pid de tout processus par son 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);
}
0
Md Muazzam