Получение списка PID из /proc в Linux

Я делаю программу, которая может видеть, возникают ли ошибки страниц в некоторых процессах, и мой метод сделать это - получить PID всех процессов и увидеть rss, maj_flt и т. д., ища в каждом отдельном /proc/[PID], проверяя, есть ли общее изменение maj_flt.

Но чтобы получить PID всех запущенных процессов, мне нужно получить их непосредственно из моей программы на C, без использования существующих команд оболочки, таких как ps, top и т. д.

Кто-нибудь знает, где находятся текущие данные PID в /proc или где-то еще? Или, если есть другой способ сделать это, например, получить его с помощью функции системного вызова в моей программе C?


person rabbit    schedule 12.08.2020    source источник


Ответы (2)


К сожалению, нет системного вызова, который выводит список PID. В Linux вы должны получить эту информацию через виртуальную файловую систему /proc.

Если вам нужен список PID запущенных в данный момент процессов, вы можете использовать opendir() и readdir(), чтобы открыть /proc и перебрать список файлов/папок там. Затем вы можете проверить папки, имя файла которых является числом. После проверки вы можете просто открыть /proc/<PID>/stat, чтобы получить нужную информацию (в частности, вы хотите 12-е поле majflt).

Вот простой рабочий пример (может потребоваться дополнительная проверка ошибок и корректировка):

#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>
#include <ctype.h>

// Helper function to check if a struct dirent from /proc is a PID folder.
int is_pid_folder(const struct dirent *entry) {
    const char *p;

    for (p = entry->d_name; *p; p++) {
        if (!isdigit(*p))
            return 0;
    }

    return 1;
}

int main(void) {
    DIR *procdir;
    FILE *fp;
    struct dirent *entry;
    char path[256 + 5 + 5]; // d_name + /proc + /stat
    int pid;
    unsigned long maj_faults;

    // Open /proc directory.
    procdir = opendir("/proc");
    if (!procdir) {
        perror("opendir failed");
        return 1;
    }

    // Iterate through all files and folders of /proc.
    while ((entry = readdir(procdir))) {
        // Skip anything that is not a PID folder.
        if (!is_pid_folder(entry))
            continue;

        // Try to open /proc/<PID>/stat.
        snprintf(path, sizeof(path), "/proc/%s/stat", entry->d_name);
        fp = fopen(path, "r");

        if (!fp) {
            perror(path);
            continue;
        }

        // Get PID, process name and number of faults.
        fscanf(fp, "%d %s %*c %*d %*d %*d %*d %*d %*u %*lu %*lu %lu",
            &pid, &path, &maj_faults
        );

        // Pretty print.
        printf("%5d %-20s: %lu\n", pid, path, maj_faults);
        fclose(fp);
    }

    closedir(procdir);
    return 0;
}

Пример вывода:

    1 (systemd)           : 37
   35 (systemd-journal)   : 1
   66 (systemd-udevd)     : 2
   91 (dbus-daemon)       : 4
   95 (systemd-logind)    : 1
  113 (dhclient)          : 2
  143 (unattended-upgr)   : 10
  148 (containerd)        : 11
  151 (agetty)            : 1
  ...
person Marco Bonelli    schedule 12.08.2020
comment
Разве closedir(procdir); не следует вызывать после завершения? - person jpo38; 19.01.2021
comment
@ jpo38 действительно, спасибо, что указали на это. - person Marco Bonelli; 19.01.2021
comment
Кроме того, здесь усекается имя процесса. Можно подождать, чтобы прочитать /proc/‹pid›/exe, используя ссылку для чтения (см. ), чтобы получить полное имя исполняемого файла. - person jpo38; 19.01.2021

Linux предоставляет псевдофайловую систему в /proc, чтобы помочь пользователям получать информацию о процессе, а не выполнять системные вызовы. Список каталогов в /proc/[pid] и анализ файлов, таких как psinfo или cmdline, — это практичный способ получения информации о процессе.

Я не уверен, какие свойства процесса вы хотите получить, но я рекомендую вам ввести «man proc» в командной строке, чтобы вы могли выяснить, какой из файлов в /proc/[pid] содержит нужную вам информацию. Я предполагаю, что /proc/[pid]/stat содержит необходимую вам информацию.

person John Park    schedule 12.08.2020