rabbit
rabbit

Reputation: 43

Getting list of PIDs from /proc in Linux

I'm making a program that can see if page faults occur in some processes, and my method to do this is to get all process's PIDs and see rss, maj_flt etc. by seeking in every single /proc/[PID], checking if there's a change in total maj_flt.

But in order to get all running process's PIDs, I need to get those directly from my C program, without using existing shell commands like ps, top etc.

Does anyone know where the running PID data exists in /proc or somewhere else? Or if there's another way to do this, like getting it by system call function in my C program?

Upvotes: 4

Views: 9593

Answers (3)

Marco Bonelli
Marco Bonelli

Reputation: 69276

There is no syscall that exposes a list of PIDs unfortunately. The way you are supposed to get this information in Linux is through the /proc virtual filesystem.

If you want a list of PIDs of currently running processes, you can use opendir() and readdir() to open /proc and iterate over the list of files/directories in there. Then you can check for directories having a filename that is a number. After checking, you can then open /proc/<PID>/stat to get the information you want (in particular, you want the 12th field majflt).

Here's a simple working example (some more error checking and adjustments might be needed):

#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 directory.
int is_pid_dir(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 directories of /proc.
    while ((entry = readdir(procdir))) {
        // Skip anything that is not a PID directory.
        if (!is_pid_dir(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;
}

Sample output:

    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
  ...

Upvotes: 9

Tombart
Tombart

Reputation: 32378

You can use openproc to query data available in virtual /proc filesystem (see man 3 openproc). procps library is needed in order to compile the code.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <proc/readproc.h>

// compile with:
// gcc environ.c -lprocps -o bin/environ
int main(){

  PROCTAB* proc = openproc(PROC_FILLSTAT);
  proc_t proc_info;
  memset(&proc_info, 0, sizeof(proc_info));
  while (readproc(proc, &proc_info) != NULL) {
    printf("%i,%i:\t %lu\n", proc_info.ppid, proc_info.tid, proc_info.maj_flt);
  }
  closeproc(proc);
}

Upvotes: 0

John Park
John Park

Reputation: 1764

Linux provides pseudo filesystem in /proc to help users get process information rather than providing system calls. Listing directory in /proc/[pid] and parsing files like psinfo or cmdline is a practical way of getting process information.

I'm not sure which properties of process you want to get, but I recommend to you to type 'man proc' on command line so that you can figure out which of the files in /proc/[pid] contains information you need. I guess /proc/[pid]/stat contains information you need.

Upvotes: 1

Related Questions