Monday, June 08, 2026

Measuring Physical and Virtual Memory Usage in FreeBSD

Here is a C++ program to print the physical and virtual memory used by a process on FreeBSD. It uses the kernel's sysctl interface to read process information, so it does not depend on parsing the output of any command line tool.

What this program does

  • It includes the necessary headers for system calls and I/O operations.
  • It uses std::atoi() for argument parsing and <iomanip> for formatting output.
  • The main function handles command line arguments:
    • If an argument is provided, it is converted to an integer with std::atoi().
    • If the converted PID is invalid (0 or negative), an error message is displayed.
    • If no argument is provided, it uses getpid() to get the current process ID.
  • It sets up the Management Information Base (MIB) for the sysctl call to retrieve process information.
  • It calculates the physical memory (resident set size) and virtual memory used by the process.
  • It uses std::fixed and std::setprecision(2) to format the output with two decimal places.

The program

#include <iostream>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/user.h>
#include <unistd.h>
#include <cstdlib>
#include <iomanip>

void print_memory_usage(pid_t pid) {
    int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
    struct kinfo_proc kp;
    size_t len = sizeof(kp);

    if (sysctl(mib, 4, &kp, &len, NULL, 0) == -1) {
        std::cerr << "Error: sysctl failed for PID " << pid << std::endl;
        return;
    }

    // Convert pages to KB
    long page_size = sysconf(_SC_PAGESIZE);
    double physical_memory_kb = (double)kp.ki_rssize * page_size / 1024.0;
    double virtual_memory_kb = (double)kp.ki_size / 1024.0;

    std::cout << "Process ID: " << pid << std::endl;
    std::cout << std::fixed << std::setprecision(2);
    std::cout << "Physical memory used: " << physical_memory_kb << " KB" << std::endl;
    std::cout << "Virtual memory used: " << virtual_memory_kb << " KB" << std::endl;
}

int main(int argc, char* argv[]) {
    pid_t pid;

    if (argc > 1) {
        pid = std::atoi(argv[1]);
        if (pid <= 0) {
            std::cerr << "Invalid PID. Please provide a positive integer." << std::endl;
            return 1;
        }
    } else {
        pid = getpid();
    }

    print_memory_usage(pid);

    return 0;
}

To compile and run

  • Save the code to a file, e.g., memory-usage.cpp.
  • Compile it with the FreeBSD default compiler: clang++ memory-usage.cpp -o memory-usage (or g++ -o memory-usage memory-usage.cpp).
  • Run the program for the current process: ./memory-usage
  • Or run it for a specific process ID: ./memory-usage 1234 (replace 1234 with the desired PID).

Sample run

root@freebsd:~/hwcode # clang++ memory-usage.cpp -o memory-usage
root@freebsd:~/hwcode # ./memory-usage 919
Error: sysctl failed for PID 919
root@freebsd:~/hwcode # ./memory-usage 839
Process ID: 839
Physical memory used: 2228.00 KB
Virtual memory used: 12844.00 KB
root@freebsd:~/hwcode # ./memory-usage
Process ID: 922
Physical memory used: 3188.00 KB
Virtual memory used: 14244.00 KB

The first call with PID 919 fails because no such process exists. The second reads a specific running process, and the third, with no argument, reports the program's own process (PID 922 here). The program prints the physical and virtual memory usage in KB for either the specified process ID or the current process if no ID is provided.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.