본문 바로가기
device driver

kernel linked list api 사용법

by jsh91 2023. 6. 1.
#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

 

댓글