Linux鏈表操作全解析

Linux C語言鏈表深度解析與實戰技巧

    • 一、鏈表基礎概念與內核鏈表優勢
      • 1.1 為什么使用鏈表?
      • 1.2 Linux 內核鏈表與用戶態鏈表的區別
    • 二、內核鏈表結構與宏解析
      • 常用宏/函數
    • 三、內核鏈表的優點
    • 四、用戶態鏈表示例
    • 五、雙向循環鏈表在內核中的實現優勢
      • 5.1 插入效率
      • 5.2 安全遍歷刪除
    • 六、典型應用場景
    • 七、調試技巧與常見陷阱
      • 7.1 打印鏈表內容
      • 7.2 常見錯誤
    • 八、實戰案例:Linux 內核模塊中的鏈表使用
      • 8.1 模塊源碼
      • 8.2 Makefile 編譯模塊
      • 8.3 插入與卸載模塊
    • 九、總結:開發建議

本文系統講解 Linux 下 C 語言鏈表的使用原理、最佳實踐及內核模塊中的實戰示例,適合嵌入式開發者、驅動工程師和系統軟件開發者。


一、鏈表基礎概念與內核鏈表優勢

1.1 為什么使用鏈表?

  • 動態插入/刪除效率高(相比數組不需要整體移動元素)
  • 內存利用率高(按需分配)
  • 常用于隊列、任務調度、資源池、驅動設備列表等場景

1.2 Linux 內核鏈表與用戶態鏈表的區別

項目用戶態實現內核態實現
指針結構自定義指針結構使用 struct list_head
安全性程序員自行維護提供安全宏/內聯函數
插入/刪除API手動實現提供統一接口如 list_add
迭代方式手動循環宏如 list_for_each_entry

二、內核鏈表結構與宏解析

struct list_head {struct list_head *next, *prev;
};

常用宏/函數

  • INIT_LIST_HEAD(ptr)
  • list_add(new, head):頭插法
  • list_add_tail(new, head):尾插法
  • list_del(entry)
  • list_empty(head)
  • list_for_each_entry(pos, head, member)
  • list_for_each_entry_safe(pos, n, head, member)

三、內核鏈表的優點

  • 雙向循環結構:從任意節點出發都能遍歷完整鏈表
  • 插入刪除不涉及內容拷貝:僅修改指針
  • 接口統一、安全可靠:可結合 container_of 獲取真實結構體指針

四、用戶態鏈表示例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>typedef struct student {int id;char name[20];struct student *next;
} student_t;void add_student(student_t **head, int id, const char *name) {student_t *new_node = malloc(sizeof(student_t));new_node->id = id;strncpy(new_node->name, name, sizeof(new_node->name));new_node->next = *head;*head = new_node;
}void print_students(student_t *head) {while (head) {printf("ID: %d, Name: %s\n", head->id, head->name);head = head->next;}
}

五、雙向循環鏈表在內核中的實現優勢

5.1 插入效率

在頭部插入只需兩次指針操作:

list_add(&new_node->list, &head);

5.2 安全遍歷刪除

list_for_each_entry_safe(ptr, tmp, &head, list) {list_del(&ptr->list);kfree(ptr);
}

六、典型應用場景

場景描述
設備驅動管理管理設備結構體(如 net_device)
定時器鏈表內核定時器統一調度
slab 分配器鏈表管理對象緩存池
進程調度/等待隊列管理 PCB / wait queue
協議棧管理TCP/UDP 的 socket 鏈表

七、調試技巧與常見陷阱

7.1 打印鏈表內容

#define print_list(head) \list_for_each_entry(ptr, head, list) \printk(KERN_INFO "Node: %s\n", ptr->name);

7.2 常見錯誤

  • 忘記初始化 INIT_LIST_HEAD
  • 使用已釋放節點(UAF)
  • 非安全刪除遍歷(未使用 list_for_each_entry_safe

八、實戰案例:Linux 內核模塊中的鏈表使用

8.1 模塊源碼

// mylist_module.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/list.h>MODULE_LICENSE("GPL");struct student {int id;char name[20];struct list_head list;
};static LIST_HEAD(student_list);static int __init mylist_init(void)
{int i;struct student *stu;printk(KERN_INFO "Loading student list module...\n");for (i = 1; i <= 5; ++i) {stu = kmalloc(sizeof(*stu), GFP_KERNEL);stu->id = i;snprintf(stu->name, sizeof(stu->name), "Student%d", i);INIT_LIST_HEAD(&stu->list);list_add_tail(&stu->list, &student_list);}return 0;
}static void __exit mylist_exit(void)
{struct student *stu, *tmp;printk(KERN_INFO "Unloading student list module...\n");list_for_each_entry_safe(stu, tmp, &student_list, list) {list_del(&stu->list);kfree(stu);}
}module_init(mylist_init);
module_exit(mylist_exit);

8.2 Makefile 編譯模塊

obj-m += mylist_module.oall:make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modulesclean:make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

8.3 插入與卸載模塊

$ make
$ sudo insmod mylist_module.ko
$ dmesg | tail -n 10
$ sudo rmmod mylist_module
$ dmesg | tail -n 10

九、總結:開發建議

建議項內容
一定初始化鏈表頭使用 INIT_LIST_HEAD 初始化
刪除節點用安全宏list_for_each_entry_safe 防止遍歷時刪除崩潰
內存管理責任明確kmalloc/kfree 成對使用
多線程環境加鎖必要時配合 spinlock 或 mutex
定位 bug 用 printk輸出 prev, next, 數據字段調試鏈表結構

本文涵蓋了從用戶態鏈表構造到 Linux 內核模塊鏈表的實戰應用,幫助你在驅動開發和內核開發中熟練掌握鏈表的構造與使用。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/84335.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/84335.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/84335.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SQL進階之旅 Day 19:統計信息與優化器提示

【SQL進階之旅 Day 19】統計信息與優化器提示 文章簡述 在數據庫性能調優中&#xff0c;統計信息和優化器提示是兩個至關重要的工具。統計信息幫助數據庫優化器評估查詢成本并選擇最佳執行計劃&#xff0c;而優化器提示則允許開發人員對優化器的行為進行微調。本文深入探討了…

安寶特方案丨船舶智造AR+AI+作業標準化管理系統解決方案(維保)

船舶維保管理現狀&#xff1a;設備維保主要由維修人員負責&#xff0c;根據設備運行狀況和維護計劃進行定期保養和故障維修。維修人員憑借經驗判斷設備故障原因&#xff0c;制定維修方案。 一、痛點與需求 1 Arbigtec 人工經驗限制維修效率&#xff1a; 復雜設備故障的診斷和…

MFC內存泄露

1、泄露代碼示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 獲取 Ribbon Bar 指針// 創建自定義按鈕CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…

基于區塊鏈的供應鏈溯源系統:構建與實踐

前言 在當今全球化的經濟環境中&#xff0c;供應鏈的復雜性不斷增加&#xff0c;商品從原材料采購到最終交付給消費者的過程涉及多個環節和眾多參與者。如何確保供應鏈的透明度、可追溯性和安全性&#xff0c;成為企業和消費者關注的焦點。區塊鏈技術以其去中心化、不可篡改和透…

Web攻防-SQL注入數據格式參數類型JSONXML編碼加密符號閉合

知識點&#xff1a; 1、Web攻防-SQL注入-參數類型&參數格式 2、Web攻防-SQL注入-XML&JSON&BASE64等 3、Web攻防-SQL注入-數字字符搜索等符號繞過 案例說明&#xff1a; 在應用中&#xff0c;存在參數值為數字&#xff0c;字符時&#xff0c;符號的介入&#xff0c…

探秘鴻蒙 HarmonyOS NEXT:實戰用 CodeGenie 構建鴻蒙應用頁面

在開發鴻蒙應用時&#xff0c;你是否也曾為一個頁面的布局反復調整&#xff1f;是否還在為查 API、寫模板代碼而浪費大量時間&#xff1f;今天帶大家實戰體驗一下鴻蒙官方的 AI 編程助手——CodeGenie&#xff08;代碼精靈&#xff09; &#xff0c;如何從 0 到 1 快速構建一個…

DBAPI如何優雅的獲取單條數據

API如何優雅的獲取單條數據 案例一 對于查詢類API&#xff0c;查詢的是單條數據&#xff0c;比如根據主鍵ID查詢用戶信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默認返回的數據格式是多條的&#xff0c;如下&#xff1a; {&qu…

使用Whisper本地部署實現香港版粵語+英語混合語音轉文字方案

今天要一個非常好的朋友有個工作&#xff0c;就是要把醫院醫生診斷的說話記錄轉成文字&#xff0c;之前都是她本人一句一句的聽&#xff0c;然后記錄下來的&#xff0c;我想通過ai 來解決這個問題。 她的需求如下&#xff1a; 不能把數據傳到網上&#xff0c;隱私問題所以需要…

案例分享--汽車制動卡鉗DIC測量

制動系統是汽車的主要組成部分&#xff0c;是汽車的主要安全部件之一。隨著車輛性能的不斷提高&#xff0c;車速不斷提升&#xff0c;對車輛的制動系統也隨之提出了更高要求&#xff0c;因此了解車輛制動系統中每個部件的動態行為成為了制動系統優化的主要途徑&#xff0c;同時…

保姆級教程:在無網絡無顯卡的Windows電腦的vscode本地部署deepseek

文章目錄 1 前言2 部署流程2.1 準備工作2.2 Ollama2.2.1 使用有網絡的電腦下載Ollama2.2.2 安裝Ollama&#xff08;有網絡的電腦&#xff09;2.2.3 安裝Ollama&#xff08;無網絡的電腦&#xff09;2.2.4 安裝驗證2.2.5 修改大模型安裝位置2.2.6 下載Deepseek模型 2.3 將deepse…

【Redis技術進階之路】「原理分析系列開篇」分析客戶端和服務端網絡誦信交互實現(服務端執行命令請求的過程 - 初始化服務器)

服務端執行命令請求的過程 【專欄簡介】【技術大綱】【專欄目標】【目標人群】1. Redis愛好者與社區成員2. 后端開發和系統架構師3. 計算機專業的本科生及研究生 初始化服務器1. 初始化服務器狀態結構初始化RedisServer變量 2. 加載相關系統配置和用戶配置參數定制化配置參數案…

VB.net復制Ntag213卡寫入UID

本示例使用的發卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、讀取舊Ntag卡的UID和數據 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click輕松讀卡技術支持:網站:Dim i, j As IntegerDim cardidhex, …

SQL SERVER 數據庫遷移的三種方法!

要將SQL Server從研發環境的把數據庫結構(不含數據)遷移至生產環境,可通過以下幾種方法實現。以下是具體操作步驟及適用場景: ?? 一、使用SSMS圖形界面生成結構腳本(推薦新手) 通過SQL Server Management Studio的生成腳本向導,僅導出數據庫架構: ??連接測試庫??…

C# 快速檢測 PDF 是否加密,并驗證正確密碼

引言&#xff1a;為什么需要檢測PDF加密狀態&#xff1f; 在批量文檔處理系統&#xff08;如 OCR 文字識別、內容提取、格式轉換&#xff09;中&#xff0c;加密 PDF 無法直接操作。檢測加密狀態可提前篩選文件&#xff0c;避免流程因密碼驗證失敗而中斷。 本文使用 Free Spire…

(33)課54:3 張表的 join-on 連接舉例,多表查詢總結。數據庫編程補述及游標綜合例題。靜態 sqL與動態sqL(可帶參數)

&#xff08;112&#xff09;3 張表的 join-on 連接舉例 &#xff1a; &#xff08;113&#xff09; 多表查詢總結 &#xff1a; &#xff08;114&#xff09;數據庫編程補述 &#xff1a; 綜合例題 &#xff1a; 以上沒有動手練習&#xff0c;不知道這樣的語法是否…

再見 Navicat!一款開源的 Web 數據庫管理工具!

大家好&#xff0c;我是 Java陳序員。 在日常的開發工作中&#xff0c;常常需要與各種數據庫打交道。而為了提高工作效率&#xff0c;常常會使用一些可視化工具進行操作數據庫。 今天&#xff0c;給大家介紹一款開源的數據庫管理工具&#xff0c;無需下載安裝軟件&#xff0c…

OkHttp 中實現斷點續傳 demo

在 OkHttp 中實現斷點續傳主要通過以下步驟完成&#xff0c;核心是利用 HTTP 協議的 Range 請求頭指定下載范圍&#xff1a; 實現原理 Range 請求頭&#xff1a;向服務器請求文件的特定字節范圍&#xff08;如 Range: bytes1024-&#xff09; 本地文件記錄&#xff1a;保存已…

函數中的Callable

在編程中&#xff0c;?Callable&#xff08;可調用對象&#xff09;?? 是指任何可以通過 () 操作符調用的對象。在函數和類設計的上下文中&#xff0c;Callable 通常指代可以被調用的實體&#xff0c;例如函數、方法、Lambda表達式或實現了 __call__ 方法的對象。以下是詳細…

MySQL學習之觸發器

文章目錄 前言什么是觸發器&#xff08;Trigger&#xff09;&#xff1f;觸發器的特點 MySQL中觸發器的用法創建NEW 與 OLD舉例其他操作 注意事項后續內容參考目錄 前言 閱讀本文前請注意最后編輯時間&#xff0c;文章內容可能與目前最新的技術發展情況相去甚遠。歡迎各位評論…

AIGC 基礎篇 Python基礎 04 for循環與while循環

今天&#xff0c;我們來講Python里面的循環部分 1.for循環 for i in range(1,10,2):print(i) 這是一個簡單但是完整的for循環&#xff0c;里面包含了for循環的所有結構 首先注意格式是“for 變量 in range(取得到的起始值&#xff0c;取不到的終點值&#xff0c;步長)” …