Device Driver Tutorial

Allocating and Freeing Kernel Memory

One of the new members of the device state structure supports memory allocation and deallocation. The qotd_cookie member receives a value from the ddi_umem_alloc(9F) function. The qotd_cookie value is then used by the ddi_umem_free(9F) function to free the memory.

Version 3 of the Quote Of The Day driver allocates kernel memory in three places:

The qotd_attach() routine allocates memory after the minor node is created. Memory must be allocated to enable the user to modify the quotation. The qotd_attach() routine calls the ddi_umem_alloc(9F) function with the DDI_UMEM_NOSLEEP flag so that the ddi_umem_alloc(9F) function will return immediately. If the requested amount of memory is not available, ddi_umem_alloc(9F) returns NULL immediately and does not wait for memory to become available. If no memory is allocated, qotd_attach() calls qotd_detach() and returns an error. If memory is allocated, qotd_attach() sets the QOTD_DIDALLOC flag so that this memory will be freed by qotd_detach() later.

The second place the driver allocates memory is in the QOTDIOCSSZ case of the qotd_ioctl() entry point. The QOTDIOCSSZ case sets a new size for the device. A new size is set when the user runs the qotdctl command with the -s option. See Exercising the Driver's I/O Controls for more information about the qotdctl command. This time, the ddi_umem_alloc(9F) function is called with the DDI_UMEM_SLEEP flag so that ddi_umem_alloc(9F) will wait for the requested amount of memory to be available. When the ddi_umem_alloc(9F) function returns, the requested memory has been allocated.

Note that you cannot always use the DDI_UMEM_SLEEP flag. See the CONTEXT sections of the ddi_umem_alloc(9F), kmem_alloc(9F), and kmem_zalloc(9F) man pages. Also note the behavioral differences among these three functions. The kmem_zalloc(9F) function is more efficient for small amounts of memory. The ddi_umem_alloc(9F) function is faster and better for large allocations. The ddi_umem_alloc(9F) function is used in this qotd_3 driver because ddi_umem_alloc(9F) allocates whole pages of memory. The kmem_zalloc(9F) function might save memory because it might allocate smaller chunks of memory. This qotd_3 driver demonstrates a ramdisk device. In a production ramdisk device, you would use ddi_umem_alloc(9F) to allocate page-aligned memory.

After the current quotation is copied to the new space, the qotd_ioctl() routine calls the ddi_umem_free(9F) function to free the memory that was previously allocated.

The third place the driver allocates memory is in the QOTDIOCDISCARD case of the qotd_ioctl() entry point. The QOTDIOCDISCARD case is called from the qotdctl command. The qotdctl command with the -r option sets the quotation back to its initial value. If the number of bytes allocated for the current quotation is different from the initial number of bytes, then new memory is allocated to reinitialize the quotation. Again, the DDI_UMEM_SLEEP flag is used so that when the ddi_umem_alloc(9F) function returns, the requested memory has been allocated. The qotd_ioctl() routine then calls the ddi_umem_free(9F) function to free the memory that was previously allocated.