From 7c96342ef17c84bbf6156545d38fe0921b0f7114 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Tue, 4 Nov 2025 18:43:04 +0000 Subject: [PATCH 1/4] libutil: Improve kinfo_getproc(3) manual page Add comprehensive documentation for struct kinfo_proc: - Add complete C-style struct definition with types and inline comments showing all user-accessible fields - Document key fields including process identifiers, credentials, memory statistics, runtime information, and flags - Clarify process flag fields (ki_flag, ki_kiflag, ki_flag2) with examples and header file references - Add complete, compilable example program demonstrating memory usage reporting - Add CAVEATS section documenting ABI stability, machine-dependent fields, and portability considerations across BSD systems - Clarify description of function behavior and memory allocation - Add cross-references to related manual pages The struct definition excludes internal kernel pointers and uses a single ellipsis for additional fields, following the style of other system structure documentation. Signed-off-by: Vsevolod Stakhov --- lib/libutil/kinfo_getproc.3 | 248 +++++++++++++++++++++++++++++++++++- 1 file changed, 244 insertions(+), 4 deletions(-) diff --git a/lib/libutil/kinfo_getproc.3 b/lib/libutil/kinfo_getproc.3 index b49a7a254603c3..4b49ebe382f026 100644 --- a/lib/libutil/kinfo_getproc.3 +++ b/lib/libutil/kinfo_getproc.3 @@ -23,7 +23,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd May 10, 2020 +.Dd November 4, 2025 .Dt KINFO_GETPROC 3 .Os .Sh NAME @@ -42,15 +42,176 @@ This function is used for obtaining process information from the kernel. .Pp The .Ar pid -field contains the process identifier. +argument specifies the process identifier. This should be a process that you have privilege to access. +.Pp This function is a wrapper around .Xr sysctl 3 with the .Dv KERN_PROC_PID mib. -While the kernel returns a packed structure, this function expands the -data into a fixed record format. +It retrieves the process information from the kernel and returns it as a +.Vt struct kinfo_proc +allocated with +.Xr malloc 3 . +.Ss Process Information Structure +The +.Vt struct kinfo_proc +contains numerous fields describing a process: +.Bd -literal +struct kinfo_proc { + int ki_structsize; /* size of this structure */ + int ki_layout; /* reserved: layout identifier */ + pid_t ki_pid; /* process identifier */ + pid_t ki_ppid; /* parent process identifier */ + pid_t ki_pgid; /* process group identifier */ + pid_t ki_tpgid; /* tty process group identifier */ + pid_t ki_sid; /* session identifier */ + pid_t ki_tsid; /* terminal session identifier */ + sigset_t ki_siglist; /* signals arrived but not delivered */ + sigset_t ki_sigmask; /* current signal mask */ + sigset_t ki_sigignore; /* signals being ignored */ + sigset_t ki_sigcatch; /* signals being caught by user */ + uid_t ki_uid; /* effective user id */ + uid_t ki_ruid; /* real user id */ + uid_t ki_svuid; /* saved effective user id */ + gid_t ki_rgid; /* real group id */ + gid_t ki_svgid; /* saved effective group id */ + short ki_ngroups; /* number of groups */ + gid_t ki_groups[KI_NGROUPS]; /* groups */ + vm_size_t ki_size; /* virtual size */ + segsz_t ki_rssize; /* resident set size in pages */ + segsz_t ki_swrss; /* resident set size before last swap */ + segsz_t ki_tsize; /* text size (pages) */ + segsz_t ki_dsize; /* data size (pages) */ + segsz_t ki_ssize; /* stack size (pages) */ + u_short ki_xstat; /* exit status for wait & stop signal */ + u_short ki_acflag; /* accounting flags */ + fixpt_t ki_pctcpu; /* %cpu for process during ki_swtime */ + u_int64_t ki_runtime; /* real time in microsec */ + struct timeval ki_start; /* starting time */ + struct timeval ki_childtime; /* time used by process children */ + long ki_flag; /* P_* flags */ + long ki_kiflag; /* KI_* flags */ + int ki_traceflag; /* kernel trace points */ + char ki_stat; /* S* process status */ + signed char ki_nice; /* process "nice" value */ + char ki_lock; /* process lock (prevent swap) count */ + char ki_tdname[TDNAMLEN+1]; /* thread name */ + char ki_wmesg[WMESGLEN+1]; /* wchan message */ + char ki_login[LOGNAMELEN+1]; /* setlogin name */ + char ki_lockname[LOCKNAMELEN+1]; /* lock name */ + char ki_comm[COMMLEN+1]; /* command name */ + char ki_emul[KI_EMULNAMELEN+1]; /* emulation name */ + char ki_loginclass[LOGINCLASSLEN+1]; /* login class */ + uint64_t ki_tdev; /* controlling tty dev */ + int ki_oncpu; /* which cpu we are on (machdep) */ + int ki_lastcpu; /* last cpu we were on (machdep) */ + int ki_tracer; /* pid of tracing process */ + int ki_flag2; /* P2_* flags */ + int ki_fibnum; /* default FIB number */ + int ki_jid; /* process jail ID */ + int ki_numthreads; /* number of threads in total */ + lwpid_t ki_tid; /* thread id */ + struct priority ki_pri; /* process priority */ + struct rusage ki_rusage; /* process rusage statistics */ + struct rusage ki_rusage_ch; /* rusage of children processes */ + long ki_sflag; /* PS_* flags */ + ... /* additional fields */ +}; +.Ed +.Pp +Key fields include: +.Bl -tag -width ".Va ki_rusage" +.It Va ki_pid +Process identifier. +.It Va ki_ppid +Parent process identifier. +.It Va ki_pgid +Process group identifier. +.It Va ki_sid +Session identifier. +.It Va ki_uid +Effective user ID. +.It Va ki_ruid +Real user ID. +.It Va ki_rgid +Real group ID. +.It Va ki_comm +Command name (up to +.Dv COMMLEN +characters). +.It Va ki_stat +Process status character. +See +.Xr ps 1 +for status character meanings (e.g., R=runnable, S=sleeping, Z=zombie). +.It Va ki_flag +Process flags indicating process state and attributes. +Flags include +.Dv P_TRACED +(being traced), +.Dv P_WEXIT +(exiting), +.Dv P_SUGID +(had set-id privileges), +.Dv P_JAILED +(in jail), and others defined in +.In sys/proc.h . +.It Va ki_kiflag +Additional kernel information flags defined in +.In sys/user.h , +such as +.Dv KI_CTTY +(has controlling tty) and +.Dv KI_SLEADER +(session leader). +.It Va ki_flag2 +Extended process flags (P2_* flags) defined in +.In sys/proc.h , +including security and tracing-related flags. +.It Va ki_nice +Process scheduling priority. +.It Va ki_size +Virtual memory size in bytes. +.It Va ki_rssize +Resident set size in pages. +.It Va ki_tsize +Text (code) size in pages. +.It Va ki_dsize +Data size in pages. +.It Va ki_ssize +Stack size in pages. +.It Va ki_start +Process start time as a +.Vt struct timeval . +.It Va ki_runtime +Accumulated runtime in microseconds. +.It Va ki_rusage +Resource usage statistics as a +.Vt struct rusage . +See +.Xr getrusage 2 +for details. +.It Va ki_pctcpu +CPU usage percentage (fixed point value). +.It Va ki_numthreads +Number of threads in the process. +.It Va ki_jid +Jail ID, or 0 if not jailed. +.It Va ki_sflag +Process session flags. +.It Va ki_oncpu , Va ki_lastcpu +Current and last CPU the process ran on. +These fields are machine-dependent. +.El +.Pp +Additional fields provide signal masks, credentials, kernel addresses, +and internal state. +Some fields contain kernel pointers and are only meaningful within the +kernel. +Some fields are machine-dependent and their layout may vary across +architectures. .Sh RETURN VALUES On success the .Fn kinfo_getproc @@ -66,8 +227,57 @@ On failure the .Fn kinfo_getproc function returns .Dv NULL . +.Sh EXAMPLES +The following example retrieves and displays process memory information: +.Bd -literal -offset indent +#include +#include +#include +#include +#include +#include +#include + +int +main(int argc, char *argv[]) +{ + struct kinfo_proc *kp; + int pagesize; + pid_t pid; + + if (argc != 2) + errx(1, "usage: %s pid", argv[0]); + + pid = atoi(argv[1]); + pagesize = getpagesize(); + + kp = kinfo_getproc(pid); + if (kp == NULL) + err(1, "kinfo_getproc"); + + printf("Process %d (%s) memory usage:\\n", + kp->ki_pid, kp->ki_comm); + printf(" Virtual size: %zu bytes\\n", + (size_t)kp->ki_size); + printf(" Resident size: %zu KB\\n", + (size_t)(kp->ki_rssize * pagesize) / 1024); + printf(" Text size: %zu KB\\n", + (size_t)(kp->ki_tsize * pagesize) / 1024); + printf(" Data size: %zu KB\\n", + (size_t)(kp->ki_dsize * pagesize) / 1024); + printf(" Stack size: %zu KB\\n", + (size_t)(kp->ki_ssize * pagesize) / 1024); + + free(kp); + return (0); +} +.Ed .Sh SEE ALSO +.Xr ps 1 , +.Xr getpagesize 2 , +.Xr getrusage 2 , .Xr free 3 , +.Xr kinfo_getallproc 3 , .Xr malloc 3 , .Xr sysctl 3 .Sh HISTORY @@ -75,3 +285,33 @@ The .Fn kinfo_getproc function first appeared in .Fx 7.0 . +.Sh CAVEATS +The +.Vt struct kinfo_proc +structure is not a stable ABI. +Fields may be added, removed, or reordered between +.Fx +releases. +The +.Va ki_structsize +field should be checked to detect changes. +.Pp +Some structure fields are machine-dependent and may not be present +or may have different sizes on all architectures. +Applications that use machine-dependent fields are not portable +across architectures. +.Pp +The +.Vt struct kinfo_proc +structure and its field names are specific to +.Fx . +Other BSD systems provide similar functionality but with different +structure definitions and field names. +Portable applications should avoid relying on the structure layout. +.Pp +Many fields contain kernel virtual addresses which are only meaningful +within the kernel and should not be dereferenced by user programs. +.Pp +The resource usage information in +.Va ki_rusage +may be updated asynchronously and may not reflect instantaneous values. From c0729fae54abff31c0577cab62bf0a514b9ec571 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Tue, 4 Nov 2025 19:27:05 +0000 Subject: [PATCH 2/4] libutil: Improve kinfo_getproc(3) example and cross-references Enhance the kinfo_getproc(3) manual page example: - Make example work without arguments by defaulting to current process when no PID is specified - Make memory output consistent by displaying all values in KB instead of mixing bytes and KB - Add compilation instructions showing that -lutil is required Improve struct documentation: - Add comment about ki_structsize and KINFO_PROC_SIZE macro for determining actual structure size - Direct readers to for full structure definition - Move ellipsis inside comment to make struct syntactically valid C Add cross-reference to kinfo_getproc(3) in libprocstat(3) manual page since it provides comprehensive documentation for struct kinfo_proc. Signed-off-by: Vsevolod Stakhov --- lib/libprocstat/libprocstat.3 | 3 ++- lib/libutil/kinfo_getproc.3 | 21 ++++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/lib/libprocstat/libprocstat.3 b/lib/libprocstat/libprocstat.3 index 2617a8827a6dbf..cea1f4ed5d7721 100644 --- a/lib/libprocstat/libprocstat.3 +++ b/lib/libprocstat/libprocstat.3 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd April 3, 2022 +.Dd November 4, 2025 .Dt LIBPROCSTAT 3 .Os .Sh NAME @@ -577,6 +577,7 @@ argument indicates an actual error message in case of failure. .Xr shm_open 2 , .Xr socket 2 , .Xr elf 3 , +.Xr kinfo_getproc 3 , .Xr kvm 3 , .Xr queue 3 , .Xr sem_open 3 , diff --git a/lib/libutil/kinfo_getproc.3 b/lib/libutil/kinfo_getproc.3 index 4b49ebe382f026..27c1146db3a6fa 100644 --- a/lib/libutil/kinfo_getproc.3 +++ b/lib/libutil/kinfo_getproc.3 @@ -117,7 +117,8 @@ struct kinfo_proc { struct rusage ki_rusage; /* process rusage statistics */ struct rusage ki_rusage_ch; /* rusage of children processes */ long ki_sflag; /* PS_* flags */ - ... /* additional fields */ + /* ... additional fields, see for full definition. + * Use ki_structsize or KINFO_PROC_SIZE for actual struct size. */ }; .Ed .Pp @@ -228,7 +229,8 @@ On failure the function returns .Dv NULL . .Sh EXAMPLES -The following example retrieves and displays process memory information: +The following example retrieves and displays process memory information. +If no argument is provided, it displays information for the current process: .Bd -literal -offset indent #include #include @@ -245,10 +247,10 @@ main(int argc, char *argv[]) int pagesize; pid_t pid; - if (argc != 2) - errx(1, "usage: %s pid", argv[0]); + if (argc > 2) + errx(1, "usage: %s [pid]", argv[0]); - pid = atoi(argv[1]); + pid = (argc == 2) ? atoi(argv[1]) : getpid(); pagesize = getpagesize(); kp = kinfo_getproc(pid); @@ -257,8 +259,8 @@ main(int argc, char *argv[]) printf("Process %d (%s) memory usage:\\n", kp->ki_pid, kp->ki_comm); - printf(" Virtual size: %zu bytes\\n", - (size_t)kp->ki_size); + printf(" Virtual size: %zu KB\\n", + (size_t)kp->ki_size / 1024); printf(" Resident size: %zu KB\\n", (size_t)(kp->ki_rssize * pagesize) / 1024); printf(" Text size: %zu KB\\n", @@ -272,6 +274,11 @@ main(int argc, char *argv[]) return (0); } .Ed +.Pp +The above example can be compiled with: +.Bd -literal -offset indent +cc -o procmem procmem.c -lutil +.Ed .Sh SEE ALSO .Xr ps 1 , .Xr getpagesize 2 , From a6b07babb5a8f9cd19fdf256d13c098dcd094980 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Thu, 6 Nov 2025 12:02:06 +0000 Subject: [PATCH 3/4] Update lib/libutil/kinfo_getproc.3 Co-authored-by: Alexander Ziaee --- lib/libutil/kinfo_getproc.3 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/libutil/kinfo_getproc.3 b/lib/libutil/kinfo_getproc.3 index 27c1146db3a6fa..b9058555512ad7 100644 --- a/lib/libutil/kinfo_getproc.3 +++ b/lib/libutil/kinfo_getproc.3 @@ -123,7 +123,7 @@ struct kinfo_proc { .Ed .Pp Key fields include: -.Bl -tag -width ".Va ki_rusage" +.Bl -tag -width "ki_rusage" .It Va ki_pid Process identifier. .It Va ki_ppid From d38e5dae8f5fbac5c5988ab0c9b42d684b46dfcc Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Thu, 6 Nov 2025 12:02:47 +0000 Subject: [PATCH 4/4] Update lib/libutil/kinfo_getproc.3 Co-authored-by: Alexander Ziaee --- lib/libutil/kinfo_getproc.3 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/libutil/kinfo_getproc.3 b/lib/libutil/kinfo_getproc.3 index b9058555512ad7..6a985682fa24f1 100644 --- a/lib/libutil/kinfo_getproc.3 +++ b/lib/libutil/kinfo_getproc.3 @@ -312,7 +312,9 @@ The .Vt struct kinfo_proc structure and its field names are specific to .Fx . -Other BSD systems provide similar functionality but with different +Other +.Bx +systems provide similar functionality but with different structure definitions and field names. Portable applications should avoid relying on the structure layout. .Pp