Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is top able to see memory usage

Tags:

c++

memory

macos

What language is top written in? I want to write a c++ program that can see how much memory individual processes are using in OSX. I can't make use of /proc, because that's not on OSX. top is able to find out how much memory processes are using so it doesn't use it either. I want to know how it finds out.

like image 619
node ninja Avatar asked Apr 30 '11 04:04

node ninja


1 Answers

It takes some digging through the source to figure it out, but Top uses the task_info() call to interface with the Mach kernel and gather memory statistics. You can read some mostly correct information about task_info() at http://www.gnu.org/software/hurd/gnumach-doc/Task-Information.html. I say mostly correct because there's at least one difference I've found in the OS X implementation: memory sizes are reported in bytes, not pages.

As a summary, you pass task_info() a "target task" (mach_task_self() if you want information about your program itself, otherwise use task_for_pid() or processor_set_tasks()) and tell it you want "basic info," the category under which virtual and resident memory sizes fall. Then task_info() fills in a task_basic_info struct with the information you want.

Here's a class I wrote to get the resident memory size. It also shows how you can use sysctl to get information about your system (how much physical ram you have, in this instance):

#include <sys/sysctl.h>
#include <mach/mach.h>
#include <cstdio>
#include <stdint.h>
#include <unistd.h>

////////////////////////////////////////////////////////////////////////////////
/*! Class for retrieving memory usage and system memory statistics on Mac OS X.
//  (Or probably any system using the MACH kernel.)
*///////////////////////////////////////////////////////////////////////////////
class MemoryInfo
{
    public:
        /** Total amount of physical memory (bytes) */
        uint64_t physicalMem;

        ////////////////////////////////////////////////////////////////////////
        /*! Constructor queries various memory properties of the system
        *///////////////////////////////////////////////////////////////////////
        MemoryInfo()
        {
            int mib[2];
            mib[0] = CTL_HW;
            mib[1] = HW_MEMSIZE;

            size_t returnSize = sizeof(physicalMem);
            if (sysctl(mib, 2, &physicalMem, &returnSize, NULL, 0) == -1)
                perror("Error in sysctl call");
        }

        ////////////////////////////////////////////////////////////////////////
        /*! Queries the kernel for the amount of resident memory in bytes.
        //  @return amount of resident memory (bytes)
        *///////////////////////////////////////////////////////////////////////
        static size_t Usage(void)
        {
            task_t targetTask = mach_task_self();
            struct task_basic_info ti;
            mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT;

            kern_return_t kr = task_info(targetTask, TASK_BASIC_INFO_64,
                                         (task_info_t) &ti, &count);
            if (kr != KERN_SUCCESS) {
                printf("Kernel returned error during memory usage query");
                return -1;
            }

            // On Mac OS X, the resident_size is in bytes, not pages!
            // (This differs from the GNU Mach kernel)
            return ti.resident_size;
        }
};
like image 181
Julian Panetta Avatar answered Sep 18 '22 00:09

Julian Panetta