Linux中的內(nèi)核鏈表實(shí)例詳解
Linux中的內(nèi)核鏈表實(shí)例詳解
鏈表中一般都要進(jìn)行初始化、插入、刪除、顯示、釋放鏈表,尋找節(jié)點(diǎn)這幾個操作,下面我對這幾個操作進(jìn)行簡單的介紹,因?yàn)槲业哪芰Σ蛔悖赡苡行〇|西理解的不夠深入,造成一定的錯誤,請各位博友指出。
A、Linux內(nèi)核鏈表中的幾個主要函數(shù)(下面是內(nèi)核中的源碼拿出來給大家分析一下)
1)初始化:
#define INIT_LIST_HEAD(ptr) do { \ (ptr)->next = (ptr); (ptr)->prev = (ptr); \ } while (0) // ptr為struct list_head,其中包括兩個指針next和prev,這里已經(jīng)可以看出內(nèi)核鏈表是雙向循環(huán)鏈表
2)尾部插入:
static inline void list_add_tail(struct list_head *new, struct list_head *head) { __list_add(new, head->prev, head); } //尾部插入,傳入的參數(shù)是新節(jié)點(diǎn)中的兩個指針和頭結(jié)點(diǎn)中的兩個指針
3)頭部插入函數(shù)
static inline void list_add(struct list_head *new, struct list_head *head) { __list_add(new, head, head->next); } //頭插入函數(shù),傳入的參數(shù)是新節(jié)點(diǎn)中的兩個指針和頭結(jié)點(diǎn)中的兩個指針
4)刪除節(jié)點(diǎn)函數(shù)
static inline void list_del(struct list_head *entry) //傳入要刪除節(jié)點(diǎn)中的指針域 { __list_del(entry->prev, entry->next);//兩個參數(shù)分別為所刪除節(jié)點(diǎn)前一個節(jié)點(diǎn)和后一個節(jié)點(diǎn) entry->next = (void *) 0;//刪除節(jié)點(diǎn)后置為空 entry->prev = (void *) 0; }
5)顯示函數(shù)(如果要打印出鏈表中的信息的話要自己寫成打印的函數(shù),比如printf,因?yàn)檫@個其實(shí)是一個遍歷的函數(shù),沒有顯示的功能)
#define list_for_each_entry(pos, head, member) \ for (pos = list_entry((head)->next, typeof(*pos), member); \ &pos->member != (head); \ pos = list_entry(pos->member.next, typeof(*pos), member)) /* 這個函數(shù)用于遍歷鏈表 pos為節(jié)點(diǎn)指針, head是頭結(jié)點(diǎn)中的兩個指針的地址 member為各節(jié)點(diǎn)中的指針域 */
6)刪除鏈表
#define list_for_each_safe(pos, n, head) \ for (pos = (head)->next, n = pos->next; pos != (head); \ pos = n, n = pos->next) //這里面的pos和n都是list_head指針,n指針是用于在刪除時不讓鏈表斷鏈
7)尋找節(jié)點(diǎn)(這也是用的內(nèi)核中的遍歷函數(shù))
#define list_for_each_entry(pos, head, member) \ for (pos = list_entry((head)->next, typeof(*pos), member); \ &pos->member != (head); \ pos = list_entry(pos->member.next, typeof(*pos), member))
B.下面來段代碼給大家看看具體的運(yùn)用方法
#include"kernel.h" #include<errno.h> #include<stdio.h> #include<stdlib.h> typedef struct list_node { int data; struct list_head list;//節(jié)點(diǎn)的指針域是被封裝在struct list_head這個結(jié)構(gòu)體內(nèi) //這個結(jié)構(gòu)體中包括struct list_head *next,*prev }*node,node1; node init_head(node head)//初始化空鏈表 { head = (node)malloc(sizeof(node1));//為節(jié)點(diǎn)分配空間 if(head == NULL) { perror("head"); return NULL; } INIT_LIST_HEAD(&(head->list));//#define INIT_LIST_HEAD(ptr) do { \ (ptr)->next = (ptr); (ptr)->prev = (ptr); \ } while (0)//調(diào)用內(nèi)核中的初始化函數(shù),傳入的參數(shù)是 //節(jié)點(diǎn)的中兩個指針,即struct list_head結(jié)構(gòu)體中的兩個指針 return head; } node insert_tail(node head,int data)//尾部插入函數(shù) { node new = (node)malloc(sizeof(node1));//為新節(jié)點(diǎn)分配空間 if(new == NULL)//判斷一下分配空間是否成功 { perror("new:"); return NULL; } new->data = data; list_add_tail(&(new->list),&(head->list));//調(diào)用內(nèi)核中的從尾部插入的函數(shù),傳入的參數(shù)為新節(jié)點(diǎn)中的兩個指針 //和頭結(jié)點(diǎn)中的兩個指針 return 0; } head_insert_node(node head,int data)//頭插入函數(shù) { node new;//創(chuàng)建一個新節(jié)點(diǎn) new = (node)malloc(sizeof(node1));//為新節(jié)點(diǎn)分配空間 if(new == NULL)//判斷一下分配空間是否成功 { perror("new:"); return 0; } new->data = data; list_add(&(new->list),&(head->list));//調(diào)用內(nèi)核中從頭插入的函數(shù),傳入的參數(shù)為新節(jié)點(diǎn)的兩個指針和頭結(jié)點(diǎn)的兩個指針 return 0; } node search_node(node head,int data)//尋找節(jié)點(diǎn)函數(shù) { node p = NULL; list_for_each_entry(p,&(head->list),list) //內(nèi)核中的遍歷函數(shù) { if(p->data == data) //p即為需要找的節(jié)點(diǎn) { printf("found the data:%d\n",p->data); goto OK; } } puts("not found the data!"); return NULL; OK: return p; } int show_node(node tmp) { if(tmp == NULL) { puts("tmp is NULL!"); return -1; } printf("the data is %d\n",tmp->data); return 0; } int delete_node(node head,int data) { node p = NULL; list_for_each_entry(p,&(head->list),list) { if(p->data == data) { printf("found the data which you want to delete!\n"); goto f; } } f: list_del(&(p->list)); free(p); return 0; } int show_list(node head) { node p = NULL; list_for_each_entry(p,&(head->list),list) { printf("data:%d\n",p->data); } return 0; } int delete_list(node head)//刪除鏈表函數(shù) { node p,q; list_for_each_entry_safe(p,q,&(head->list),list)//這是內(nèi)核中的安全刪除函數(shù) { list_del(&(p->list)); free(p); } list_del(&(head->list)); free(head); return 0; } int main(int argc,char **argv) { node head; node tmp; head = init_head(head);//初始化空鏈表函數(shù) insert_tail(head,45);//從末尾插入函數(shù) insert_tail(head,55); insert_tail(head,65); head_insert_node(head,75);//從頭插入函數(shù) show_list(head); //顯示鏈表函數(shù) tmp = search_node(head,55);//尋找結(jié)點(diǎn)函數(shù) show_node(head); delete_node(head,55); //show_list(head); delete_list(head);//刪除鏈表函數(shù) return 0; }
以上就是Linux中的內(nèi)核鏈表實(shí)例詳解的實(shí)例如有疑問請留言或者到本站社區(qū)交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
- Linux 內(nèi)核通用鏈表學(xué)習(xí)小結(jié)
- Linux內(nèi)核鏈表實(shí)現(xiàn)過程
- Linux內(nèi)核設(shè)備驅(qū)動之proc文件系統(tǒng)筆記整理
- Linux內(nèi)核設(shè)備驅(qū)動之高級字符設(shè)備驅(qū)動筆記整理
- Linux內(nèi)核設(shè)備驅(qū)動之Linux內(nèi)核模塊加載機(jī)制筆記整理
- Linux內(nèi)核設(shè)備驅(qū)動地址映射筆記整理
- Linux內(nèi)核設(shè)備驅(qū)動之Linux內(nèi)核基礎(chǔ)筆記整理
- 增強(qiáng)Linux內(nèi)核中訪問控制安全的方法
- Linux 內(nèi)核空間與用戶空間實(shí)現(xiàn)與分析
- 詳解Linux內(nèi)核進(jìn)程調(diào)度函數(shù)schedule()的觸發(fā)和執(zhí)行時機(jī)
- Linux內(nèi)核設(shè)備驅(qū)動之內(nèi)核中鏈表的使用筆記整理
相關(guān)文章
ubuntu 解決libsqlite3-0依賴的問題(推薦)
下面小編就為大家?guī)硪黄猽buntu 解決libsqlite3-0依賴的問題(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-05-05Shell腳本導(dǎo)入導(dǎo)出數(shù)據(jù)的項目示例
在工作中,很多場景都會涉及到數(shù)據(jù)的導(dǎo)入導(dǎo)出,本文就介紹一下使用Shell腳本導(dǎo)入導(dǎo)出數(shù)據(jù)的項目示例,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-04-04Linux中shell腳本獲取當(dāng)前工作目錄的方法
今天小編就為大家分享一篇Linux中shell腳本獲取當(dāng)前工作目錄的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-06-06shell編程中for循環(huán)語句的實(shí)現(xiàn)過程及案例
Bash?Shell中主要提供了三種循環(huán)方式:for、while和until,下面這篇文章主要給大家介紹了關(guān)于shell編程中for循環(huán)語句的實(shí)現(xiàn)過程及案例,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-04-04shell通過sed上下兩行合并成一行的實(shí)現(xiàn)
本文主要介紹了shell通過sed上下兩行合并成一行的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03