A MacFUSE-Based Process File System for Mac OS X© Amit Singh. All Rights Reserved. Written in May 2007
Processes as Files
The process file system ("procfs" for brevity, or simply "/proc", because that's where it is usually mounted) has become a common entity on Unix-like systems. For example, Solaris, Linux, and the various modern BSDs all have procfs. In general, procfs uses the file metaphor to provide both a view of currently running processes and perhaps an interface to control them. However, some procfs implementations export so many types of information that they are nothing short of the proverbial kitchen sink. Implementations can also differ in the format they use to export such information. For example, Solaris procfs favors the binary format philosophy, assuming that developers will write interesting user-space tools that use that "raw" information. In contrast, Linux favors formatted text to export information through procfs, allowing end users and administrators to simply view that information using familiar file utilities.
Tom J. Killian created the first implementation of a process file system. It was for Eighth Edition UNIX. See T. J. Killian, "Processes as Files," USENIX Summer Conference Proceedings, Salt Lake City, UT, USA (June 1984).
/proc on Mac OS X (not)
Mac OS X does not provide a process file system. It does provide alternative interfaces such as
sysctl(3) and the now obsolete
sysctl(3) interface provides read and write access to a management information base (MIB) whose contents are various categories of kernel information, such as information related to processes, file systems, virtual memory, networking, and debugging in general. When the
/dev/kmem device is available, the
kvm(3) interface provides access to raw kernel memory. Besides, the I/O Kit programming interfaces and tools such as
IORegistryExplorer.app allow user-space inspection of a variety of kernel information on Mac OS X.
sysctl() system call was introduced in 4.4BSD as a safe, reliable, and portable (across kernel versions) way to perform user-kernel data exchange.
In 2003, shortly after I was introduced to Mac OS X, I began a quick-and-dirty implementation of procfs for Mac OS X. Meant as nothing more than a "random experiment", my approach was to take
pseudofs source from FreeBSD and morph them to work on Mac OS X. Shortly after I had the thing mounting, I ran into a kernel panic. (Writing in-kernel file systems is very conducive to this behavior.) Before I could begin two-machine debugging, one of the two Macintosh computers I had access to had catastrophic hardware failure. Apple gave me extremely poor repair experience (taking weeks to fix one problem and returning the machine with something else broken; repeat this several times over). So much so that by the time the machine finally worked, I had no interest left in debugging procfs for Mac OS X.
A MacFUSE-Based procfs
Fast forward to late 2006. I was wrapping up MacFUSE, a Mac OS X implementation of the FUSE (File System in User Space) mechanism. The first Mac OS X-specific example file system I wrote for MacFUSE was procfs—this time as a user-space file system, of course. I've been meaning to release it as an open source MacFUSE example, but didn't find the time to package it up until now.
The MacFUSE version of procfs makes heavy use of the Mach programming interfaces. Moreover, the implementation uses a set of macros that depend on the C++ version of the pcre (Perl Compatible Regular Expressions) library. The macros are meant to make it easier to extend the file system.
Detailed information on understanding and using the Mach interfaces used by procfs can be found in the book Mac OS X Internals. In particular, refer to Chapters 6 (The xnu Kernel), 7 (Processes), 8 (Virtual Memory), and 9 (Interprocess Communication).
Compiling and Using procfs
Since procfs depends on the pcre libraries, you will first need to download, compile, and install pcre. Note that if you install pcre in a location other than
/usr/local/, you will need to modify the
Makefile in procfs source. The
Makefile also assumes that you have the MacFUSE libraries installed under
$ tar -jxvf pcre-<version>.tar.bz2
$ cd pcre-<version>
$ CFLAGS="-O -g -arch i386 -arch ppc -isysroot /Developer/SDKs/MacOSX10.4u.sdk" \
CXXFLAGS="-O -g -arch i386 -arch ppc -isysroot /Developer/SDKs/MacOSX10.4u.sdk" \
LDFLAGS="-arch i386 -arch ppc" \
./configure --prefix=/usr/local --disable-dependency-tracking
$ sudo make install
$ cd /work/macfuse/filesystems/procfs
Having successfully compiled procfs, you can mount it, say, on the
/proc directory, as follows.
$ sudo mkdir /proc
$ sudo chown root:wheel /proc
$ sudo ./procfs /proc
procfs on /proc (read-only, synchronous)
Now you can explore the process file system on Mac OS X.
$ ls -F /proc
0/ 151/ 212/ 35/ 47/
1/ 165/ 215/ 36/ 51/
1166/ 187/ 218/ 38/ 5338/
1187/ 194/ 221/ 39/ 54/
1196/ 195/ 23/ 3954/ 59/
1216/ 196/ 27/ 3976/ 62/
131/ 200/ 28807/ 40/ 64/
140/ 201/ 28902/ 42/ 67/
145/ 202/ 32/ 43/ 867/
146/ 204/ 33/ 45/ 95/
15094/ 206/ 34/ 46/ hardware/
There is a directory under
/proc for each process on the system, with the numeric process ID (pid) being the directory name. pid 0 corresponds to the kernel, pid 1 is
launchd, and so on.
$ cd /proc/867
$ ls -l
0 dr-xr-xr-x 1 root wheel 0 May 7 23:44 .
0 dr-xr-xr-x 1 root wheel 0 May 7 23:44 ..
0 dr-xr-xr-x 1 root wheel 0 May 7 23:44 carbon
0 -r--r--r-- 1 root wheel 0 May 7 23:44 cmdline
0 -r--r--r-- 1 root wheel 0 May 7 23:44 jobc
0 -r--r--r-- 1 root wheel 0 May 7 23:44 paddr
0 dr-xr-xr-x 1 root wheel 0 May 7 23:44 pcred
0 -r--r--r-- 1 root wheel 0 May 7 23:44 pgid
0 -r--r--r-- 1 root wheel 0 May 7 23:44 ppid
0 dr-xr-xr-x 1 root wheel 0 May 7 23:44 task
0 -r--r--r-- 1 root wheel 0 May 7 23:44 tdev
0 -r--r--r-- 1 root wheel 0 May 7 23:44 tpgid
0 dr-xr-xr-x 1 root wheel 0 May 7 23:44 ucred
0 -r--r--r-- 1 root wheel 0 May 7 23:44 wchan
For a given pid, the
/proc/pid/ directory has some files containing certain BSD-level information. The
carbon/ subdirectory contains additional information for processes that are also Carbon processes. The
ucred/ subdirectories contains files exporting process and user credentials, respectively.
$ ls -F carbon
$ cat carbon/name carbon/psn
$ cat cmdline
$ ls -F ucred
$ cat ucred/groups ucred/uid
501(singh) 81(appserveradm) 79(appserverusr) 80(admin)
task/ subdirectory contains a variety of Mach task information: scheduling data, virtual memory regions, Mach ports, threads, register state, and so on.
$ cd task
$ ls -F
absolutetime_info/ ports/ tokens/
basic_info/ role vmmap
$ cat role
$ cat vmmap
00000000-00001000 4K ---/--- COPY - DEFAULT uwir=0 sub=0
00001000-000dc000 876K r-x/rwx COPY - DEFAULT uwir=0 sub=0
15a54000-15ada000 536K r--/rwx COPY - DEFAULT uwir=0 sub=0
15ade000-15ede000 4096K rw-/rwx COPY - DEFAULT uwir=0 sub=0
$ ls -F basic_info
policy suspend_count user_time
resident_size system_time virtual_size
$ ls -F events_info
cow_faults messages_received syscalls_mach
csw messages_sent syscalls_unix
$ ls -F ports
1003/ 1f03/ 2f03/ 4003/ 507/ 6423/ 7b03/ 8e03/ a887/ d093/
1e03/ 2e03/ 3f03/ 5003/ 62b7/ 79f7/ 8d03/ a7c7/ d03/
$ ls -F ports/1003
msgcount qlimit seqno sorights task_rights
$ cat ports/1003/task_rights
$ ls -F threads
7b03/ 7c03/ 7d03/ 7e03/ 7f03/ 8003/ 8103/ 8203/
$ ls -F threads/7b03
$ ls -F threads/7b03/basic_info
cpu_usage policy sleep_time system_time
flags run_state suspend_count user_time
$ ls -F threads/7b03/states
debug/ exception/ float/ thread/
$ ls -F threads/7b03/states/thread
cs eax ebx edi eflags es esp gs
ds ebp ecx edx eip esi fs ss
$ cat threads/7b03/states/thread/esp
hardware/ subdirectory contains subdirectories for several pieces of hardware on the machine, allowing certain hardware data to be read from virtual files.
In a subsequent version of procfs, the
/hardware/ subdirectory was moved to appear under the
/system/ subdirectory, which in turn now contains
$ ls -F /proc/hardware
cpus/ lightsensor/ motionsensor/ mouse/ tpm/
$ ls -F /proc/hardware/cpus
$ ls -F /proc/hardware/cpus/0
$ cat /proc/hardware/cpus/0/data
slot 0 (master), running
type 7, subtype 4
6751211 ticks (user 91036 system 141938 idle 6517257 nice 980)
cpu uptime 18h 45m 12s
$ cat /proc/hardware/motionsensor/data
-7 -1 0
$ cat /proc/hardware/motionsensor/data
-37 -1 0
$ cat /proc/hardware/lightsensor/data
$ cat /proc/hardware/lightsensor/data
Although there's no universal standard for either the hierarchy of file system objects in procfs or the contents of these objects, some implementations are rather popular because of the prevalence of their underlying operating systems. For example, FreeBSD contains linprocfs, a process file system that emulates a subset of Linux procfs. linprocfs was necessary for Linux binary emulation to work completely. This procfs implementation doesn't attempt to conform to any other implementation. For somebody with enough determination and time, it could be an interesting project to create a Linux-compatible (or Solaris-compatible, or whatever) version of MacFUSE-based procfs for Mac OS X.
The source for procfs can be accessed on the MacFUSE project web site.
The following is a Leopard-only precompiled Universal binary for procfs.