首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Linux 內核通知鏈機制原理與內核模塊實戰代碼詳解

     編輯:Java 綜合教學

一、核心概念

內核子系統相互獨立,但常需跨子系統事件通知。通知鏈提供了一種內核態的「觀察者模式」:通知鏈本質是函數指針鏈表,每個節點註冊一個回調函數。事件發生時,遍歷鏈表依次調用。僅限內核子系統間使用,不可跨越用戶態。

二、四種類型與數據結構

類型鎖機制上下文阻塞頭結構
原子通知鏈spinlock中斷上下文不允許atomic_notifier_head
可阻塞通知鏈rw_semaphore進程上下文允許blocking_notifier_head
原始通知鏈無(調用者自管)無限制視調用者raw_notifier_head
SRCU 通知鏈mutex + SRCU進程上下文允許srcu_notifier_head

核心節點結構:

struct notifier_block {
    int (*notifier_call)(struct notifier_block *, unsigned long, void *);
    struct notifier_block *next;
    int priority;  // 優先級高者排前
};

三、運作機制三步走

  1. 通知者 定義鏈表頭
  2. 被通知者 調用 notifier_chain_register() 按優先級插入回調
  3. 事件觸發時,通知者調用 notifier_call_chain() 遍歷執行

回調返回值控制流程:NOTIFY_DONE(不關心)、NOTIFY_OK(成功)、NOTIFY_STOP_MASK(停止後續傳遞)。

四、完整內核模塊實戰(三文件 + Makefile)

1. buildchain.c — 定義鏈頭與註冊/通知導出函數

static RAW_NOTIFIER_HEAD(test_chain);
int register_test_notifier(struct notifier_block *nb) { return raw_notifier_chain_register(&test_chain, nb); }
int unregister_test_notifier(struct notifier_block *nb) { return raw_notifier_chain_unregister(&test_chain, nb); }
int test_notifier_call_chain(unsigned long val, void *v) { return raw_notifier_call_chain(&test_chain, val, v); }
EXPORT_SYMBOL(register_test_notifier);
EXPORT_SYMBOL(unregister_test_notifier);
EXPORT_SYMBOL(test_notifier_call_chain);

2. regchain.c — 註冊三個測試節點

static int test_event1(struct notifier_block *this, unsigned long event, void *ptr) { printk("Event 1: %ld\n", event); return 0; }
static int test_event2(...) { printk("Event 2: %ld\n", event); return 0; }
static int test_event3(...) { printk("Event 3: %ld\n", event); return 0; }

static struct notifier_block test_notifier1 = { .notifier_call = test_event1 };
static struct notifier_block test_notifier2 = { .notifier_call = test_event2 };
static struct notifier_block test_notifier3 = { .notifier_call = test_event3 };

static int __init reg_notifier(void) {
    register_test_notifier(&test_notifier1);
    register_test_notifier(&test_notifier2);
    register_test_notifier(&test_notifier3);
    return 0;
}

3. notify.c — 發送通知觸發鏈

extern int test_notifier_call_chain(unsigned long val, void *v);
static int __init call_notifier(void) {
    test_notifier_call_chain(1, NULL);  // 觸發所有註冊回調
    return 0;
}

4. Makefile 編譯與加載

obj-m := buildchain.o regchain.o notify.o
KERNELDIR := /usr/src/linux-headers-$(shell uname -r)
all: make -C $(KERNELDIR) M=$(shell pwd) modules
clean: make -C $(KERNELDIR) M=$(shell pwd) clean

編譯加載:
make && insmod buildchain.ko && insmod regchain.ko && insmod notify.ko

內核日誌輸出:
Event 1: 1
Event 2: 1
Event 3: 1

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved