Determine Process Info Programmatically in Darwin/Osx

Determine Process Info Programmatically in Darwin/OSX

Process info comes from pidinfo:

cristi:~ diciu$ grep proc_pidinfo /usr/include/libproc.h

int proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, int buffersize);

cpu load comes from host_statistics:

cristi:~ diciu$ grep -r host_statistics /usr/include/

/usr/include/mach/host_info.h:/* host_statistics() */

/usr/include/mach/mach_host.defs:routine host_statistics(

/usr/include/mach/mach_host.h:/* Routine host_statistics */

/usr/include/mach/mach_host.h:kern_return_t host_statistics

For more details, check out sources for top and lsof, they are open source (you need to register as an Apple developer but that's free of charge):

https://opensource.apple.com/source/top/top-111.20.1/libtop.c.auto.html

Later edit: All these interfaces are version specific, so you need to take that into account when writing production code (libproc.h):

/*
* This header file contains private interfaces to obtain process information.
* These interfaces are subject to change in future releases.
*/

Is it possible to sending a signal to a process in Darwin/XNU/OSX/macOS?

After reading the POSIX standard, I came to understand that kill had been extended to so that you can actually send any kind of signal that you specify and will not automatically cause the receiving application to terminate (unless you send SIGKILL).

Get /proc/ pid /map info with sysctl call under mac os

macOS' virtual memory subsystem is in the Mach-inherited part of the kernel, so those APIs are definitely the ones to use. For inspecting regions, look at mach_vm_region() (called vm_region in the original Mach - you will find more documentation for that), for reading memory, use mach_vm_read().

You may also find the vmmap command line utility to come in useful for exploration.

How do I determine the OS version at runtime in OS X or iOS (without using Gestalt)?

On OS X 10.10 (and iOS 8.0), you can use [[NSProcessInfo processInfo] operatingSystemVersion] which returns a NSOperatingSystemVersion struct, defined as

typedef struct {
NSInteger majorVersion;
NSInteger minorVersion;
NSInteger patchVersion;
} NSOperatingSystemVersion;

There is also a method in NSProcessInfo that will do the comparison for you:

- (BOOL)isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion)version

Beware, although documented to be available in OS X 10.10 and later, both operatingSystemVersion and isOperatingSystemAtLeastVersion: exist on OS X 10.9 (probably 10.9.2) and work as expected. It means that you must not test if NSProcessInfo responds to these selectors to check if you are running on OS X 10.9 or 10.10.

On iOS, these methods are effectively only available since iOS 8.0.

Get information on PID

I think you mean this:

ps -p <PID> -o start=
10:22am

where you substitute in your PID. The start= selects the start time and also suppresses the header line. If you want the header, use

ps -p <PID> -o start
STARTED
10:22am

Alternatively, you can get the start time formated more fully like this:

ps -p <PID> -o lstart=
Fri 26 Sep 10:22:50 2014

By the way, if you want a list of the keywords (like start and lstart above) you can either wade through the manage, or more simply, just give an invalid keyword and it will tell you all the ones it likes :-)

ps -o %rubbish
ps: %rubbish: keyword not found
ps: no valid keywords; valid keywords:
%cpu %mem acflag acflg args blocked caught comm command cpu cputime etime f flags gid group ignored
inblk inblock jobc ktrace ktracep lim login logname lstart majflt minflt msgrcv msgsnd ni nice nivcsw
nsignals nsigs nswap nvcsw nwchan oublk oublock p_ru paddr pagein pcpu pending pgid pid pmem ppid pri
pstime putime re rgid rgroup rss ruid ruser sess sig sigmask sl start stat state stime svgid svuid
tdev time tpgid tsess tsiz tt tty ucomm uid upr user usrpri utime vsize vsz wchan wq wqb wql wqr xstat

Retrieve system information on Mac OS X

For system-wide memory usage information under Mac OS X, open and read the file /usr/bin/vm_stat. Something like this:

static double ParseMemValue(const char * b)
{
while((*b)&&(isdigit(*b) == false))
b++;
return isdigit(*b) ? atof(b) : -1.0;
}

// Returns a number between 0.0f and 1.0f, with 0.0f meaning all RAM is available, and 1.0f meaning all RAM is currently in use
float GetSystemMemoryUsagePercentage()
{
FILE * fpIn = popen("/usr/bin/vm_stat", "r");
if (fpIn)
{
double pagesUsed = 0.0, totalPages = 0.0;
char buf[512];
while(fgets(buf, sizeof(buf), fpIn) != NULL)
{
if (strncmp(buf, "Pages", 5) == 0)
{
double val = ParseMemValue(buf);
if (val >= 0.0)
{
if ((strncmp(buf, "Pages wired", 11) == 0) ||
(strncmp(buf, "Pages active", 12) == 0)
)

pagesUsed += val;

totalPages += val;
}
}
else
if (strncmp(buf, "Mach Virtual Memory Statistics", 30) != 0)
break; // Stop at "Translation Faults". We don't care
// about anything at or below that
}
pclose(fpIn);

if (totalPages > 0.0)
return (float) (pagesUsed/totalPages);
}
return -1.0f; // Indicate failure
}

For a CPU usage indicator, do something like this:

#include <mach/mach_init.h>
#include <mach/mach_error.h>
#include <mach/mach_host.h>
#include <mach/vm_map.h>

static unsigned long long _previousTotalTicks = 0;
static unsigned long long _previousIdleTicks = 0;

// Returns 1.0f for "CPU fully pinned", 0.0f for "CPU idle", or somewhere in between
// You'll need to call this at regular intervals, since it measures the load between
// the previous call and the current one.
float GetCPULoad()
{
host_cpu_load_info_data_t cpuinfo;
mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
if (host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info_t)&cpuinfo, &count) == KERN_SUCCESS)
{
unsigned long long totalTicks = 0;
for(int i=0; i<CPU_STATE_MAX; i++)
totalTicks += cpuinfo.cpu_ticks[i];
return CalculateCPULoad(cpuinfo.cpu_ticks[CPU_STATE_IDLE], totalTicks);
}
else
return -1.0f;
}

float CalculateCPULoad(unsigned long long idleTicks, unsigned long long totalTicks)
{
unsigned long long totalTicksSinceLastTime = totalTicks-_previousTotalTicks;
unsigned long long idleTicksSinceLastTime = idleTicks-_previousIdleTicks;
float ret = 1.0f-((totalTicksSinceLastTime > 0) ? ((float)idleTicksSinceLastTime)/totalTicksSinceLastTime : 0);
_previousTotalTicks = totalTicks;
_previousIdleTicks = idleTicks;
return ret;
}

For network statistics, I don't know the solution (other than maybe to run netstat and parse the results somehow... it depends on what network statistics you are interested in I suppose).



Related Topics



Leave a reply



Submit