Example 2-1 is a revision of Example 1-2 that uses its own malloc_type
structure instead of the kernel-defined M_TEMP
.[2] Example 2-1 should clarify any misunderstandings you may have about MALLOC_DEFINE
and MALLOC_DECLARE
.
To save space, the functions echo_open
, echo_close
, echo_write
, and echo_read
aren’t listed here, as they haven’t been changed.
Example 2-1. echo-2.0.c
#include <sys/param.h> #include <sys/module.h> #include <sys/kernel.h> #include <sys/systm.h> #include <sys/conf.h> #include <sys/uio.h> #include <sys/malloc.h> #define BUFFER_SIZE 256 MALLOC_DECLARE(M_ECHO); MALLOC_DEFINE(M_ECHO, "echo_buffer", "buffer for echo driver"); static d_open_t echo_open; static d_close_t echo_close; static d_read_t echo_read; static d_write_t echo_write; static struct cdevsw echo_cdevsw = { .d_version = D_VERSION, .d_open = echo_open, .d_close = echo_close, .d_read = echo_read, .d_write = echo_write, .d_name = "echo" }; typedef struct echo { char buffer[BUFFER_SIZE]; int length; } echo_t; static echo_t *echo_message; static struct cdev *echo_dev; static int echo_open(struct cdev *dev, int oflags, int devtype, struct thread *td) { ... } static int echo_close(struct cdev *dev, int fflag, int devtype, struct thread *td) { ... } static int echo_write(struct cdev *dev, struct uio *uio, int ioflag) { ... } static int echo_read(struct cdev *dev, struct uio *uio, int ioflag) { ... } static int echo_modevent(module_t mod __unused, int event, void *arg __unused) { int error = 0; switch (event) { case MOD_LOAD: echo_message = malloc(sizeof(echo_t), M_ECHO, M_WAITOK); echo_dev = make_dev(&echo_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "echo"); uprintf("Echo driver loaded. "); break; case MOD_UNLOAD: destroy_dev(echo_dev); free(echo_message, M_ECHO); uprintf("Echo driver unloaded. "); break; default: error = EOPNOTSUPP; break; } return (error); } DEV_MODULE(echo, echo_modevent, NULL);
This driver declares and defines a new malloc_type
structure named M_ECHO
. To use this malloc_type
structure, malloc
and free
are adjusted accordingly.
Because M_ECHO
is used only locally, MALLOC_DECLARE
is unnecessary—it’s only included here for demonstration purposes.
Now that Example 2-1 uses a unique malloc_type
structure, we can easily profile its dynamic memory usage, like so:
$sudo kldload ./echo-2.0.ko
Echo driver loaded. $vmstat -m | head -n 1 && vmstat -m | grep "echo_buffer"
Type InUse MemUse HighUse Requests Size(s) echo_buffer 1 1K - 1 512
Notice that Example 2-1 requests 512 bytes, though sizeof(echo_t)
is only 260 bytes. This is because malloc
rounds up to the nearest power of two when allocating memory. Additionally, note that the second argument to MALLOC_DEFINE
(echo_buffer
in this example) is used in the output of vmstat
(instead of the first argument).
18.191.176.194