Example 2-2 modifies Example 2-1 to use contigmalloc
and contigfree
instead of malloc
and free
. Example 2-2 should clarify any misunderstandings you may have about contigmalloc
and contigfree
.
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-2. echo_contig.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_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 = contigmalloc(sizeof(echo_t), M_ECHO, M_WAITOK | M_ZERO, 0, 0xffffffff, PAGE_SIZE, 1024 * 1024); 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); contigfree(echo_message, sizeof(echo_t), M_ECHO); uprintf("Echo driver unloaded. "); break; default: error = EOPNOTSUPP; break; } return (error); } DEV_MODULE(echo, echo_modevent, NULL);
Here, contigmalloc
allocates sizeof(echo_t)
bytes of zero-filled memory. This memory resides between physical address 0
and 0xffffffff
, is aligned on a PAGE_SIZE
boundary, and does not cross a 1MB address boundary.
The following output shows the results from vmstat -m
after loading Example 2-2:
$sudo kldload ./echo_contig.ko
Echo driver loaded. $vmstat -m | head -n 1 && vmstat -m | grep "echo_buffer"
Type InUse MemUse HighUse Requests Size(s) echo_buffer 1 4K - 1
Notice that Example 2-2 uses 4KB of memory, though sizeof(echo_t)
is only 260 bytes. This is because contigmalloc
allocates memory in PAGE_SIZE
blocks. Predictably, this example was run on an i386 machine, which uses a page size of 4KB.
18.118.20.156