[Toybox] How toybox PS works.

Ed Maste emaste at freebsd.org
Thu Jan 31 06:06:35 PST 2019


On Wed, 30 Jan 2019 at 18:58, Rob Landley <rob at landley.net> wrote:
>
> The bigger problem for BSD/macos is ps.c parses /proc/$PID/stat to get its
> process information, and I don't think BSD even has that concept?

We do have a procfs, but its use is discouraged and is not compatible
with the Linux procfs. We do have a linprocfs for the Linux emulation
layer, but it's not mounted in a FreeBSD tree.

> No idea where
> BSD or MacOS versions of ps get this sort of data. (Bell Labs unix read /dev/mem
> and parsed the in-kernel process table structures. No really!

Yep, there are vestiges of this history in FreeBSD still, and I
believe the FreeBSD lsof port still works this way.

On FreeBSD ps links against libkvm and uses kvm_getprocs, from the man page:

     struct kinfo_proc *
     kvm_getprocs(kvm_t *kd, int op, int arg, int *cnt);

The kvm_getprocs() function returns a (sub-)set of active processes in
the kernel indicated by kd.  The op and arg arguments constitute a
predicate which limits the set of processes returned.  The value of op
describes the filtering predicate as follows:

   KERN_PROC_ALL         all processes and kernel visible threads
   KERN_PROC_PROC        all processes, without threads
   KERN_PROC_PID         processes with process ID arg
   KERN_PROC_PGRP        processes with process group arg
   KERN_PROC_SESSION     processes with session arg
   KERN_PROC_TTY         processes with TTY arg
   KERN_PROC_UID         processes with effective user ID arg
   KERN_PROC_RUID        processes with real user ID arg
   KERN_PROC_INC_THREAD  modifier to return all kernel visible threads
                         when filtering by process ID, process group,
                         TTY, user ID, and real user ID

The man page also includes a BUGS section that states "These routines
do not belong in the kvm interface" but they presumably will never
move.

Under the hood kvm_getprocs uses the sysctl interface,
kern.proc.<op>.<pid>. Source is here:
https://reviews.freebsd.org/source/src/browse/head/lib/libkvm/kvm_proc.c$491

I haven't looked at Darwin, but I suspect it uses the same interface.
Linking against libkvm on *BSD seems reasonable.

> In practice, the dirtree infrastructure that finds the processes (lib/dirtree.c)
> is recursive directory descent plumbing populating a tree of struct dirtree *
> structures for each entry and calling a callback function to filter and/or act
> upon them. Which means A) it assumes it's reading a filesystem to populate, B)
> our get_ps() is a callback function that knows about the /proc layout. There's
> also a get_threads() shim that descends an extra level for Linux's weird thread
> layout (and then calls get_ps() to do the reading once it's identified the next
> directory with something interesting).

For us including or excluding threads is just a flag to kvm_getprocs.

If it simplifies things leaving get_ps as a callback seems fine,
although replacing the dirtree search means there's probably a fair
bit that needs to be done differently. In any case for me the more
system-specific utilities are the lowest priority; the pure
text-processing and basic filesystem utilities are more interesting
initially.



More information about the Toybox mailing list