Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Learn Kernel Data Structures for Drivers | Kernel Memory and Data Handling
C Device Drivers Basics

bookKernel Data Structures for Drivers

When writing device drivers in C, you will often need to manage collections of data, keep track of device states, and ensure efficient access to this information inside the kernel. The Linux kernel provides its own set of data structures for these purposes, with linked lists being one of the most fundamental. Unlike user space, where you might use standard library containers, kernel code relies on its own implementations for safety, performance, and flexibility. The most common structure for linked lists in the kernel is the list_head, which allows you to create doubly-linked lists that can be embedded within your own structures. This makes it easy to keep track of multiple devices, buffers, or requests in a clean and organized way.

kernel_list_example.c

kernel_list_example.c

copy
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
#include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/list.h> struct my_device { int id; struct list_head list; }; static LIST_HEAD(device_list); static int __init list_example_init(void) { struct my_device *dev1, *dev2; dev1 = kmalloc(sizeof(*dev1), GFP_KERNEL); dev2 = kmalloc(sizeof(*dev2), GFP_KERNEL); dev1->id = 1; dev2->id = 2; INIT_LIST_HEAD(&dev1->list); INIT_LIST_HEAD(&dev2->list); list_add(&dev1->list, &device_list); list_add(&dev2->list, &device_list); printk(KERN_INFO "Devices added to list\n"); return 0; } static void __exit list_example_exit(void) { struct my_device *dev, *tmp; list_for_each_entry_safe(dev, tmp, &device_list, list) { list_del(&dev->list); kfree(dev); } printk(KERN_INFO "Devices removed from list\n"); } module_init(list_example_init); module_exit(list_example_exit); MODULE_LICENSE("GPL");

Linked lists, as seen in the example above, are extremely useful for device drivers because they allow you to dynamically add, remove, and traverse device-specific data structures without worrying about fixed array sizes or memory fragmentation. By embedding a list_head in your own structure, you can easily maintain a list of all active devices, pending I/O requests, or any similar collection. The kernel provides helper macros and functions to safely add, remove, and iterate over these lists, making your code more robust and maintainable.

kernel_list_iteration.c

kernel_list_iteration.c

copy
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
#include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/list.h> struct my_device { int id; struct list_head list; }; static LIST_HEAD(device_list); static int __init list_iter_example_init(void) { struct my_device *dev1, *dev2, *dev; dev1 = kmalloc(sizeof(*dev1), GFP_KERNEL); dev2 = kmalloc(sizeof(*dev2), GFP_KERNEL); dev1->id = 10; dev2->id = 20; INIT_LIST_HEAD(&dev1->list); INIT_LIST_HEAD(&dev2->list); list_add(&dev1->list, &device_list); list_add(&dev2->list, &device_list); list_for_each_entry(dev, &device_list, list) { printk(KERN_INFO "Device ID: %d\n", dev->id); } return 0; } static void __exit list_iter_example_exit(void) { struct my_device *dev, *tmp; list_for_each_entry_safe(dev, tmp, &device_list, list) { list_del(&dev->list); kfree(dev); } } module_init(list_iter_example_init); module_exit(list_iter_example_exit); MODULE_LICENSE("GPL");
question mark

Which kernel structure is commonly used to implement linked lists in device drivers?

Select the correct answer

Everything was clear?

How can we improve it?

Thanks for your feedback!

SectionΒ 3. ChapterΒ 2

Ask AI

expand

Ask AI

ChatGPT

Ask anything or try one of the suggested questions to begin our chat

Suggested prompts:

Can you show me an example of how to define and use a `list_head` in a device driver?

What are some common helper macros for working with linked lists in the Linux kernel?

How do I safely add or remove elements from a kernel linked list?

bookKernel Data Structures for Drivers

Swipe to show menu

When writing device drivers in C, you will often need to manage collections of data, keep track of device states, and ensure efficient access to this information inside the kernel. The Linux kernel provides its own set of data structures for these purposes, with linked lists being one of the most fundamental. Unlike user space, where you might use standard library containers, kernel code relies on its own implementations for safety, performance, and flexibility. The most common structure for linked lists in the kernel is the list_head, which allows you to create doubly-linked lists that can be embedded within your own structures. This makes it easy to keep track of multiple devices, buffers, or requests in a clean and organized way.

kernel_list_example.c

kernel_list_example.c

copy
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
#include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/list.h> struct my_device { int id; struct list_head list; }; static LIST_HEAD(device_list); static int __init list_example_init(void) { struct my_device *dev1, *dev2; dev1 = kmalloc(sizeof(*dev1), GFP_KERNEL); dev2 = kmalloc(sizeof(*dev2), GFP_KERNEL); dev1->id = 1; dev2->id = 2; INIT_LIST_HEAD(&dev1->list); INIT_LIST_HEAD(&dev2->list); list_add(&dev1->list, &device_list); list_add(&dev2->list, &device_list); printk(KERN_INFO "Devices added to list\n"); return 0; } static void __exit list_example_exit(void) { struct my_device *dev, *tmp; list_for_each_entry_safe(dev, tmp, &device_list, list) { list_del(&dev->list); kfree(dev); } printk(KERN_INFO "Devices removed from list\n"); } module_init(list_example_init); module_exit(list_example_exit); MODULE_LICENSE("GPL");

Linked lists, as seen in the example above, are extremely useful for device drivers because they allow you to dynamically add, remove, and traverse device-specific data structures without worrying about fixed array sizes or memory fragmentation. By embedding a list_head in your own structure, you can easily maintain a list of all active devices, pending I/O requests, or any similar collection. The kernel provides helper macros and functions to safely add, remove, and iterate over these lists, making your code more robust and maintainable.

kernel_list_iteration.c

kernel_list_iteration.c

copy
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
#include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/list.h> struct my_device { int id; struct list_head list; }; static LIST_HEAD(device_list); static int __init list_iter_example_init(void) { struct my_device *dev1, *dev2, *dev; dev1 = kmalloc(sizeof(*dev1), GFP_KERNEL); dev2 = kmalloc(sizeof(*dev2), GFP_KERNEL); dev1->id = 10; dev2->id = 20; INIT_LIST_HEAD(&dev1->list); INIT_LIST_HEAD(&dev2->list); list_add(&dev1->list, &device_list); list_add(&dev2->list, &device_list); list_for_each_entry(dev, &device_list, list) { printk(KERN_INFO "Device ID: %d\n", dev->id); } return 0; } static void __exit list_iter_example_exit(void) { struct my_device *dev, *tmp; list_for_each_entry_safe(dev, tmp, &device_list, list) { list_del(&dev->list); kfree(dev); } } module_init(list_iter_example_init); module_exit(list_iter_example_exit); MODULE_LICENSE("GPL");
question mark

Which kernel structure is commonly used to implement linked lists in device drivers?

Select the correct answer

Everything was clear?

How can we improve it?

Thanks for your feedback!

SectionΒ 3. ChapterΒ 2
some-alt