錯誤信息分析
/root/clock.c:20: error: implicit declaration of function 'cli'
/root/clock.c:21: error: 'xtime' undeclared
/root/clock.c:22: error: implicit declaration of function 'sti'
/root/clock.c:36: error: unknown field 'owner' specified in initializer
/root/clock.c:50: error: 'proc_root' undeclared
API 遷移對照表(2.4 → 2.6+)
| 2.4 內核 | 2.6+ 內核 | 說明 |
cli() / sti() | local_irq_save() / local_irq_restore() | 中斷控制,支持嵌套、多 CPU |
xtime | ktime_get_real() / getnstimeofday() | 高精度時間,納秒級 |
proc_root | 移除,使用 proc_mkdir() 創建目錄 | /proc 根目錄不再導出符號 |
struct proc_dir_entry 靜態初始化 | proc_create() / proc_create_data() | 動態創建,自動管理字段 |
owner 字段 | 自動設置為 THIS_MODULE | 無需手動指定 |
修正後的 clock.c 完整代碼
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/time.h>
#include <linux/ktime.h>
#define PROC_NAME "clock"
static struct proc_dir_entry *proc_entry;
static ssize_t clock_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos) {
struct timespec64 ts;
ktime_get_real_ts64(&ts); // 獲取當前時間 (秒 + 納秒)
char kbuf[64];
int len = snprintf(kbuf, sizeof(kbuf), "%lld %ld\n",
(long long)ts.tv_sec, ts.tv_nsec / 1000); // 微秒
return simple_read_from_buffer(buf, count, ppos, kbuf, len);
}
static const struct proc_ops clock_proc_ops = {
.proc_read = clock_read,
};
static int __init clock_init(void) {
// 動態創建 /proc/clock
proc_entry = proc_create(PROC_NAME, 0444, NULL, &clock_proc_ops);
if (!proc_entry) {
pr_err("Failed to create /proc/%s\n", PROC_NAME);
return -ENOMEM;
}
pr_info("/proc/%s created\n", PROC_NAME);
return 0;
}
static void __exit clock_exit(void) {
proc_remove(proc_entry);
pr_info("/proc/%s removed\n", PROC_NAME);
}
module_init(clock_init);
module_exit(clock_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Developer");
MODULE_DESCRIPTION("Simple /proc clock module for Linux 2.6+");
Makefile 現代化
obj-m += clock.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
install:
insmod clock.ko
uninstall:
rmmod clock
編譯與測試
# 編譯
make
# 加載
sudo insmod clock.ko
dmesg | tail # 查看內核日誌
# 測試
cat /proc/clock
# 輸出示例:1701234567 123456
# 卸載
sudo rmmod clock
關鍵遷移要點總結
- 中斷控制:
local_irq_save(flags) 返回保存的標誌,local_irq_restore(flags) 恢復,必須成對使用
- 時間獲取:
ktime_get_real_ts64() 替代 xtime,提供 64 位秒 + 納秒
- /proc 文件系統:使用
proc_create() + proc_ops (2.6.30+) 或 file_operations (舊版)
- 模塊導出符號:避免依賴內核未導出符號(如
proc_root)
- 內核版本宏:
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) 做版本兼容
參考資源