#include <linux/module.h>
#include <linux/types.h>
#include <linux/list.h>
#include <linux/slab.h>
struct my_struct {
int data;
struct list_head list;
};
static int __init hello_init(void)
{
pr_info("Hello world init\n");
LIST_HEAD(my_list_head); // 빈 리스트의 센티넬 노드를 선언합니다.
struct my_struct *first_item = kmalloc(sizeof(*first_item), GFP_KERNEL);
if (!first_item)
return -ENOMEM;
first_item->data = 5;
INIT_LIST_HEAD(&first_item->list);
list_add(&first_item->list, &my_list_head); // 첫 번째 원소를 리스트에 추가합니다
printk(KERN_INFO "Item add : [%d]",first_item->data);
struct my_struct *second_item = kmalloc(sizeof(*second_item), GFP_KERNEL);
if (!second_item)
return -ENOMEM;
second_item->data = 10;
INIT_LIST_HEAD(&second_item->list);
list_add(&second_item->list, &my_list_head); // 두 번째 원소를 리스트에 추가합니다.
printk(KERN_INFO "Item add : [%d]",second_item->data);
struct list_head *pos, *q;
/* 리스트 뒤에서부터 를 안전하게 순회합니다. - stack*/
//list_for_each_safe(pos, q, &my_list_head) {
/* 리스트 앞에서부터 를 안전하게 순회합니다. - queue */
list_for_each_prev_safe(pos, q, &my_list_head) {
struct my_struct *item = list_entry(pos, struct my_struct, list);
printk(KERN_INFO "Item data: [%d], pos adress : [%x], q adress : [%x]\n", item->data, pos, q);
list_del(pos); // 리스트에서 이 원소를 삭제합니다.
kfree(item); // 동적으로 할당된 원소를 해제합니다.
}
return 0;
}
static void __exit hello_exit(void)
{
pr_info("Hello world exit\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
LIST_HEAD(name) - linked list의 head를 선언
INIT_LIST_HEAD(struct list_head *list) - linked list를 사용하기전에 초기화 작업
list_add(struct list_head *new, struct list_head *head) - linked list를 추가
list_del(struct list_head *entry) - linked list를 제거
list_entry(ptr, type, member) - linked list 를 담고있는 struct를 찾기위해 사용 ( container_of() )
list_for_each(pos, head) - linked list를 순회할 때 사용
list_for_each_safe(pos, n, head) - linked list에서 뒤에서 부터 순회(stack) 하며 node를 수정, 삭제를 할때 사용( 동기화 기능이 있음 )
list_for_each_prev_safe - linked list에서 앞에서 부터 순회(qeueu) 하며 node를 수정, 삭제를 할때 사용( 동기화 기능이 있음 )
list_for_each_safe 는 아래 그림에서 next를 따라 순회
[ 930.900112] Item add : [5]
[ 930.900117] Item add : [10]
[ 930.900130] Item data: [10], pos adress : [b5add2c4], q adress : [b5add204]
[ 930.900142] Item data: [5], pos adress : [b5add204], q adress : [8f5bfd6c]
list_for_each_prev_safe 는 아래 그림에서 prev를 따라 순회
[ 3061.171749] Item add : [5]
[ 3061.171754] Item add : [10]
[ 3061.171767] Item data: [5], pos adress : [b5ae0ac4], q adress : [b5ae0704]
[ 3061.171779] Item data: [10], pos adress : [b5ae0704], q adress : [ba559d6c]
https://linux-kernel-labs.github.io/refs/heads/master/so2/lab2-kernel-api.html
SO2 Lab 02 - Kernel API — The Linux Kernel documentation
Overview Inside the current lab we present a set of concepts and basic functions required for starting Linux kernel programming. It is important to note that kernel programming differs greatly from user space programming. The kernel is a stand-alone entity
linux-kernel-labs.github.io
'device driver' 카테고리의 다른 글
charter device driver - 9. expander device moudle 만들기 (0) | 2023.06.19 |
---|---|
gpio contorl 전반적인 내용 (0) | 2023.06.15 |
Waiting queues (0) | 2023.06.01 |
charter device driver - 8. interrupt platform driver 만들기 (0) | 2023.05.30 |
charter device driver - 7. i2c platform driver 만들기 (0) | 2023.05.28 |
댓글