libproc for process listing on OSX

On OSX if you need to manage other processes, a sensible place to start is NSRunningApplication class. You can instantiate one of these with a pid:

NSRunningApplication *a = 
    [NSRunningApplication runningApplicationWithProcessIdentifier:pid];

An NSRunningApplication object has amongst other things, the following properties:

  • executableURL
  • bundleURL
  • bundleIdentifier

That sounds promising, but there’s a catch: NSRunningApplication can’t tell you about everything running on your system. For example, process 548 on my system is the com.apple.sandboxd Launch Daemon. But ask NSRunningApplication about it and you’ll get:

  • executableURL: (null)
  • bundleURL: (null)
  • bundleIdentifier: (null)

On the other hand point it at Preview and NSRunningApplication is a champion:

  • executableURL: file:///Applications/Preview.app/Contents/MacOS/Preview
  • bundleURL: file:///Applications/Preview.app
  • bundleIdentifier: com.apple.Preview

I’m not sure precisely what the criteria is for some process to be properly recognised by NSRunningApplication, maybe it needs to be registered with a bundle ID, but luckily there’s another way to enumerate processes on OSX that digs deeper into the BSD layer: libproc.

This is a poorly documented (unsupported?) C API that you can learn more about from /usr/include/libproc.h, but in a nutshell there are two calls that most people would care about:

  • proc_listpids() to get a list of pids
  • proc_pidpath() to get the executable path associated with the pid

They can be put together with something like this:

int pidCount = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0);
unsigned long pidsBufSize = sizeof(pid_t) * (unsigned long)pidCount;
pid_t * pids = malloc(pidsBufSize);
bzero(pids, pidsBufSize);
proc_listpids(PROC_ALL_PIDS, 0, pids, (int)pidsBufSize);
char pathBuffer[PROC_PIDPATHINFO_MAXSIZE];
for (int i=0; i < pidCount; i++) {
    bzero(pathBuffer, PROC_PIDPATHINFO_MAXSIZE);
    proc_pidpath(pids[i], pathBuffer, sizeof(pathBuffer));
    printf("pid %d = %s\n", pids[i], pathBuffer);
}

That will give you the executable path of every process, even those that NSRunningApplication cannot grok.

Advertisements
This entry was posted in Uncategorized and tagged . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s