KHELP(9)
π NAME π
so bestie, welcome to KHELP(9) β it's a page from the Kernel Developer's Manual, and it's all about the Kernel Helper Framework. the whole squad of things it covers:
khelpkhelp_init_osdkhelp_destroy_osdkhelp_get_idkhelp_get_osdkhelp_add_hhookkhelp_remove_hhookKHELP_DECLARE_MODKHELP_DECLARE_MOD_UMA
that's the roster. iconic lineup honestly. π
β¨ SYNOPSIS β¨
here's the whole vibe up front, copy it exactly bestie:
#include <sys/khelp.h>
#include <sys/module_khelp.h>
int khelp_init_osd(uint32_t classes, struct osd *hosd);
int khelp_destroy_osd(struct osd *hosd);
int32_t khelp_get_id(char *hname);
void * khelp_get_osd(struct osd *hosd, int32_t id);
int khelp_add_hhook(struct hookinfo *hki, uint32_t flags);
int khelp_remove_hhook(struct hookinfo *hki);
KHELP_DECLARE_MOD(hname, hdata, hhooks, version);
KHELP_DECLARE_MOD_UMA(hname, hdata, hhooks, version, ctor, dtor);
πΈ DESCRIPTION πΈ
okay so khelp gives you a whole framework for managing khelp modules, and those modules indirectly use the hhook(9) KPI to register their hook functions with hook points they're interested in inside the kernel. the whole goal of khelp modules? a structured way to dynamically extend the kernel at runtime in an ABI preserving manner. slay.
depending on which subsystem is providing the hook points, a khelp module might be able to associate per-object data for keeping relevant state alive between hook calls. and listen β hhook(9) and khelp are tightly integrated, like joined at the hip, so if you care about khelp at all you need to go read the hhook(9) manual page thoroughly too. no skipping, bestie. π«Ά
π Information for Khelp Module Implementors π
khelp modules are represented inside the khelp framework by a struct helper, and it has these members:
struct helper {
int (*mod_init) (void);
int (*mod_destroy) (void);
#define HELPER_NAME_MAXLEN 16
char h_name[HELPER_NAME_MAXLEN];
uma_zone_t h_zone;
struct hookinfo *h_hooks;
uint32_t h_nhooks;
uint32_t h_classes;
int32_t h_id;
volatile uint32_t h_refcount;
uint16_t h_flags;
TAILQ_ENTRY(helper) h_next;
};
so here's the tea: modules must instantiate a struct helper, but they're only required to set the h_classes field. everything else? optional. you may set h_flags, mod_init and mod_destroy if you need them. the framework handles all the other fields itself, so modules should refrain from manipulating them β hands off, bestie π. and using the C99 designated initialiser feature to set fields is encouraged. very demure, very mindful.
if you specify the mod_init function, the khelp framework runs it prior to completing the registration process. if mod_init returns a non-zero value, that aborts the registration process and the module fails to load. π
if you specify the mod_destroy function, the khelp framework runs it during the deregistration process β after the module has been deregistered by the khelp framework. and its return value is currently ignored. π
valid khelp classes are defined in <sys/khelp.h>. valid flags are defined in <sys/module_khelp.h>. if your khelp module needs persistent per-object data storage, you should set the HELPER_NEEDS_OSD flag in the h_flags field. and here's a real one: there is no programmatic way (yet) to check whether a khelp class provides the ability for khelp modules to associate persistent per-object data, so a manual check is required. iykyk.
the KHELP_DECLARE_MOD() and KHELP_DECLARE_MOD_UMA() macros are convenient wrappers around the DECLARE_MODULE(9) macro, and they're what you use to register a khelp module with the khelp framework. important: KHELP_DECLARE_MOD_UMA() should only be used by modules which require the use of persistent per-object storage β meaning modules which set the HELPER_NEEDS_OSD flag in their struct helper's h_flags field. don't be out here using it for no reason. π
the first four arguments are common to both macros, and they go like this:
- the
hnameargument specifies the uniqueascii(7)name for the khelp module. it should be no longer thanHELPER_NAME_MAXLEN-1characters in length. - the
hdataargument is a pointer to the module'sstruct helper. - the
hhooksargument points to a static array ofstruct hookinfostructures. that array should contain astruct hookinfofor eachhhook(9)point the module wishes to hook β even when using the same hook function multiple times for differenthhook(9)points. yes, even then. π - the
versionargument specifies a version number for the module which will be passed toMODULE_VERSION(9).
and the KHELP_DECLARE_MOD_UMA() macro takes the additional ctor and dtor arguments, which specify optional uma(9) constructor and destructor functions. where that functionality isn't required, pass NULL. π
the khelp_get_id() function returns the numeric identifier for the khelp module with name hname.
the khelp_get_osd() function is how you obtain the per-object data pointer for a specified khelp module. the hosd argument is a pointer to the underlying subsystem object's struct osd β and that's provided by the hhook(9) framework when it calls into a khelp module's hook function. the id argument specifies the numeric identifier for the khelp module you want to extract the data pointer from hosd for. you get that id from the khelp_get_id() function. β¨
the khelp_add_hhook() and khelp_remove_hhook() functions let a khelp module dynamically hook/unhook hhook(9) points at run time. the hki argument specifies a pointer to a struct hookinfo which encapsulates all the required info about the hhook(9) point and hook function being manipulated. and you may pass the HHOOK_WAITOK flag in via the flags argument of khelp_add_hhook() if malloc(9) is allowed to sleep waiting for memory to become available. π€
π¦ Integrating Khelp Into a Kernel Subsystem π¦
most of the work you'll do to let khelp modules actually do useful things is all about defining and instantiating suitable hhook(9) points for khelp modules to hook into. the only extra decision a subsystem has to make is whether it wants to allow khelp modules to associate persistent per-object data. supporting persistent data storage can let khelp modules perform more complex functionality, which may be desirable. π
so if a subsystem wants to let Khelp modules associate persistent per-object data with one of the subsystem's data structures, it needs to make these two key changes:
- Embed a
struct osdpointer in the structure definition for the object. - Add calls to
khelp_init_osd()andkhelp_destroy_osd()to the subsystem code paths which are responsible for respectively initialising and destroying the object.
the khelp_init_osd() function initialises the per-object data storage for all currently loaded khelp modules of appropriate classes which have set the HELPER_NEEDS_OSD flag in their h_flags field. the classes argument specifies a bitmask of khelp classes which this subsystem associates with β and if a khelp module matches any of the classes in that bitmask, that module gets associated with the object. the hosd argument specifies the pointer to the object's struct osd which will be used to provide the persistent storage for khelp modules to use. π«Ά
the khelp_destroy_osd() function frees all memory that was associated with an object's struct osd by a previous call to khelp_init_osd(). the hosd argument specifies the pointer to the object's struct osd which will be purged in preparation for destruction. bye bye memory π
π₯ IMPLEMENTATION NOTES π₯
khelp modules are protected from being prematurely unloaded by a reference count. the count gets incremented every time a subsystem calls khelp_init_osd(), which causes persistent storage to be allocated for the module β and it gets decremented for each corresponding call to khelp_destroy_osd(). only when a module's reference count has dropped to zero can the module be unloaded. not a single tick earlier. periodt. π
π RETURN VALUES π
- the
khelp_init_osd()function returns zero if no errors occurred. it returnsENOMEMif a khelp module which requires per-object storage fails to allocate the necessary memory. π - the
khelp_destroy_osd()function only returns zero to indicate that no errors occurred. - the
khelp_get_id()function returns the unique numeric identifier for the registered khelp module with namehname. it returns-1if no module with the specified name is currently registered. π - the
khelp_get_osd()function returns the pointer to the khelp module's persistent object storage memory. if the module identified byiddoes not have persistent object storage registered with the object'shosdstruct osd,NULLis returned. - the
khelp_add_hhook()function returns zero if no errors occurred. it returnsENOENTif it could not find the requestedhhook(9)point. it returnsENOMEMifmalloc(9)failed to allocate memory. it returnsEEXISTif attempting to register the same hook function more than once for the samehhook(9)point. π« - the
khelp_remove_hhook()function returns zero if no errors occurred. it returnsENOENTif it could not find the requestedhhook(9)point.
π EXAMPLES π
a well commented example Khelp module can be found at:
/usr/share/examples/kld/khelp/h_example.c
and the Enhanced Round Trip Time (ERTT) h_ertt(4) khelp module provides a more complex example of what is possible. go look, it's giving main character energy. β
π SEE ALSO π
π«Ά ACKNOWLEDGEMENTS π«Ά
development and testing of this software were made possible in part by grants from the FreeBSD Foundation and Cisco University Research Program Fund at Community Foundation Silicon Valley. legends, honestly.
π HISTORY π
the khelp kernel helper framework first appeared in FreeBSD 9.0.
the khelp framework was first released in 2010 by Lawrence Stewart whilst studying at Swinburne University of Technology's Centre for Advanced Internet Architectures, Melbourne, Australia. more details are available at:
http://caia.swin.edu.au/urp/newtcp/
π AUTHORS π
the khelp framework was written by Lawrence Stewart <lstewart@FreeBSD.org>.
this manual page was written by David Hayes <david.hayes@ieee.org> and Lawrence Stewart <lstewart@FreeBSD.org>.
okay that's the whole page bestie, you ate it π
β¨ this one's from the Debian edition, dated February 15, 2011 β so it's vintage, it's iconic, it's literally KHELP(9). now go read hhook(9) like i told you ππ¦
π¦ where this page comes from
- debian bookworm: freebsd-manpages 12.2-1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- debian trixie: freebsd-manpages 12.2-2 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu jammy: freebsd-manpages 12.2-1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu noble: freebsd-manpages 12.2-1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu questing: freebsd-manpages 12.2-2
- ubuntu resolute: freebsd-manpages 12.2-2build1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu stonking: freebsd-manpages 12.2-2build1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- Copyright (c) 2010-2011 The FreeBSD Foundation
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms