1. struct list_head 를 갖는 struct 를 하나 선언한다.
struct A_data {
enum A_command cmd;
u8 offset;
u8 data;
struct completion complete;
bool use_completion;
int *ret;
struct list_head list;
};
2. list 를 선언한다.
/* global value */
LIST_HEAD(&A_data_list);
or
struct temp_struct {
struct list_head B_data_list;
}
3. data 를 저장한 struct 를 list 에 넣는다.
struct A_data *A_cmd;
A_cmd = kzalloc(sizeof(struct A_data), GFP_KERNEL);
if (!A_cmd) {
pr_err("[ERROR] fail\n");
return -ENOMEM;
}
A_cmd->cmd = command;
A_cmd->offset = offset;
A_cmd->data = data;
A_cmd->use_completion = false;
INIT_LIST_HEAD(&A_data_list);
list_add_tail(&A_cmd->list, &A_data_list);
or
struct temp_struct __temp_struct;
INIT_LIST_HEAD(&__temp_struct->B_data_list);
list_add_tail(&A_cmd->list, &__temp_struct->B_data_list);
4. 하나씩 꺼내다 쓴다.
struct A_data *data, *next;
list_for_each_entry_safe(data, next, &A_data_list, list) {
...
printk("%d", data->cmd);
}
TODO : list_for_each_entry 와 list_for_each_entry_safe 의 차이점?
5. 처리된 list 를 지우고 alloc 을 했다면 free 한다.
list_del(&data->list);
kfree(data);
list_entry 함수에 대해서..
동작 : 아래 list 의 point 를 가지고 todo_struct 전체를 return 해준다.
struct todo_struct {
struct list_head list; int priority; /* driver specific */ /* ... add other driver-specific fields */ };
struct list_head todo_list; INIT_LIST_HEAD(&todo_list);
void todo_add_entry(struct todo_struct *new)
{ struct list_head *ptr; struct todo_struct *entry; for (ptr = todo_list.next; ptr != &todo_list; ptr = ptr->next) {
entry = list_entry(ptr, struct todo_struct, list); if (entry->priority < new->priority) { list_add_tail(&new->list, ptr); return; } } list_add_tail(&new->list, &todo_struct) }
list_add function.
head 바로뒤에 new entry 를 붙인다.
A(head) -> B(head->next) 가 있었다면..
A(head) -> new entry(head->next) -> B(new entry->next)
가 되는 것임.
/**
* list_add - add a new entry
* @new: new entry to be added
* @head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
list_del
A -> B -> C -> ..
인데 list_del(B) 를 호출하면..
A.next = C;
C.prev = A;
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = (void *)0xDEADBEEF;
entry->prev = (void *)0xBEEFDEAD;
}
static inline void __list_del(struct list_head *prev, struct list_head *next)
{
next->prev = prev;
prev->next = next;
}
아래 링크에 여러 list 함수에 대한 사용 예가 잘 나와있다.
http://www.makelinux.net/ldd3/chp-11-sect-5
'Programming > Linux_Kernel' 카테고리의 다른 글
arm 에서의 linux process 와 thread (0) | 2013.10.23 |
---|---|
linux process memory usage (0) | 2013.10.22 |
down() / down_interruptible() / down_trylock() (0) | 2013.08.29 |
linux kernel basic APIs (0) | 2013.08.08 |
Android Terminal Emulator 을 이용한 linux kernel debugging 기법 (0) | 2013.07.26 |