kernel/init_8259a.c

本文详细介绍了初始化8259A中断控制器的函数实现过程,包括主片和从片的ICW配置、OCW设置及中断处理函数表初始化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Code:
  1. /*  
  2.     By Marcus Xing  
  3.     kernel/init_8259a.c  
  4.     初始化8259A的函数  
  5. */  
  6.   
  7. #include "type.h"   
  8. #include "const.h"   
  9. #include "ipc.h"   
  10. #include "console.h"   
  11. #include "tty.h"   
  12. #include "protect.h"   
  13. #include "proc.h"   
  14. #include "proto.h"   
  15. #include "global.h"   
  16.   
  17. void Init_8259A()   
  18. {   
  19.     /* 8259A 主片和从片,ICW1 */  
  20.     Out_Byte(INT_MASTER_CTL,0x11);   
  21.     Out_Byte(INT_SLAVE_CTL,0x11);   
  22.            
  23.     /* 8259A 主片和从片,ICW2 */  
  24.     Out_Byte(INT_MASTER_CTLMSK,INT_VECTOR_IRQ0);   
  25.     Out_Byte(INT_SLAVE_CTLMSK,INT_VECTOR_IRQ8);   
  26.            
  27.     /* 8259A 主片和从片,ICW3 */  
  28.     Out_Byte(INT_MASTER_CTLMSK,4);   
  29.     Out_Byte(INT_SLAVE_CTLMSK,2);   
  30.            
  31.     /* 8259A 主片和从片,ICW4 */  
  32.     Out_Byte(INT_MASTER_CTLMSK,1);   
  33.     Out_Byte(INT_SLAVE_CTLMSK,1);   
  34.            
  35.     /* 8259A 主片和从片,OCW1,起屏蔽外中断作用 */  
  36.     Out_Byte(INT_MASTER_CTLMSK,0xff);          
  37.     Out_Byte(INT_SLAVE_CTLMSK,0xff);   
  38.            
  39.     /* 初始化外中断函数表 */  
  40.     /* 全部先初始化为没特点的处理函数 */  
  41.     int i;   
  42.     for(i = 0;i < IRQ_NUM;i++)   
  43.     {   
  44.         IRQ_Handler_Table[i] = Hard_Int_Handler;   
  45.     }   
  46. }   

 

make -C /lib/modules/3.10.0-1160.119.1.el7.x86_64/build M=/home/user/1/core_test_folder modules make[1]: Entering directory '/usr/src/kernels/3.10.0-1160.119.1.el7.x86_64' CC [M] /home/user/1/core_test_folder/icmp_ping_monitor.o In file included from include/linux/cache.h:4:0, from include/linux/time.h:4, from include/linux/stat.h:18, from include/linux/module.h:10, from /home/user/1/core_test_folder/icmp_ping_monitor.c:1: /home/user/1/core_test_folder/icmp_ping_monitor.c: 在函数‘ping_stat_show’中: include/linux/kernel.h:792:17: 警告:比较不相关的指针时缺少类型转换 [默认启用] (void) (&_min1 == &_min2); \ ^ /home/user/1/core_test_folder/icmp_ping_monitor.c:83:21: 附注:in expansion of macro ‘min’ for (i = 0; i < min(stats.count, MAX_ENTRIES); i++) { ^ /home/user/1/core_test_folder/icmp_ping_monitor.c: 在文件作用域: /home/user/1/core_test_folder/icmp_ping_monitor.c:100:21: 错误:变量‘ping_stat_fops’有初始值设定但类型不完全 static const struct proc_ops ping_stat_fops = { ^ /home/user/1/core_test_folder/icmp_ping_monitor.c:101:5: 错误:初始值设定项里有未知的字段‘proc_open’ .proc_open = ping_stat_open, ^ /home/user/1/core_test_folder/icmp_ping_monitor.c:101:5: 警告:结构初始值设定项中有多余元素 [默认启用] /home/user/1/core_test_folder/icmp_ping_monitor.c:101:5: 警告:(在‘ping_stat_fops’的初始化附近) [默认启用] /home/user/1/core_test_folder/icmp_ping_monitor.c:102:5: 错误:初始值设定项里有未知的字段‘proc_read’ .proc_read = seq_read, ^ /home/user/1/core_test_folder/icmp_ping_monitor.c:102:5: 警告:结构初始值设定项中有多余元素 [默认启用] /home/user/1/core_test_folder/icmp_ping_monitor.c:102:5: 警告:(在‘ping_stat_fops’的初始化附近) [默认启用] /home/user/1/core_test_folder/icmp_ping_monitor.c:103:5: 错误:初始值设定项里有未知的字段‘proc_lseek’ .proc_lseek = seq_lseek, ^ /home/user/1/core_test_folder/icmp_ping_monitor.c:103:5: 警告:结构初始值设定项中有多余元素 [默认启用] /home/user/1/core_test_folder/icmp_ping_monitor.c:103:5: 警告:(在‘ping_stat_fops’的初始化附近) [默认启用] /home/user/1/core_test_folder/icmp_ping_monitor.c:104:5: 错误:初始值设定项里有未知的字段‘proc_release’ .proc_release = single_release, ^ /home/user/1/core_test_folder/icmp_ping_monitor.c:104:5: 警告:结构初始值设定项中有多余元素 [默认启用] /home/user/1/core_test_folder/icmp_ping_monitor.c:104:5: 警告:(在‘ping_stat_fops’的初始化附近) [默认启用] /home/user/1/core_test_folder/icmp_ping_monitor.c: 在函数‘ping_stat_init’中: /home/user/1/core_test_folder/icmp_ping_monitor.c:121:15: 警告:从不兼容的指针类型赋值 [默认启用] nfho.hook = ping_hook; ^ /home/user/1/core_test_folder/icmp_ping_monitor.c:125:5: 错误:隐式声明函数‘nf_register_net_hook’ [-Werror=implicit-function-declaration] nf_register_net_hook(&init_net, &nfho); ^ /home/user/1/core_test_folder/icmp_ping_monitor.c:128:5: 警告:传递‘proc_create’的第 4 个参数时在不兼容的指针类型间转换 [默认启用] proc_entry = proc_create("ping_stats", 0, NULL, &ping_stat_fops); ^ In file included from /home/user/1/core_test_folder/icmp_ping_monitor.c:3:0: include/linux/proc_fs.h:30:38: 附注:需要类型‘const struct file_operations *’,但实参的类型为‘const struct proc_ops *’ static inline struct proc_dir_entry *proc_create( ^ /home/user/1/core_test_folder/icmp_ping_monitor.c:130:9: 错误:隐式声明函数‘nf_unregister_net_hook’ [-Werror=implicit-function-declaration] nf_unregister_net_hook(&init_net, &nfho); ^ cc1: some warnings being treated as errors scripts/Makefile.build:339: recipe for target '/home/user/1/core_test_folder/icmp_ping_monitor.o' failed make[2]: *** [/home/user/1/core_test_folder/icmp_ping_monitor.o] Error 1 Makefile:1316: recipe for target '_module_/home/user/1/core_test_folder' failed make[1]: *** [_module_/home/user/1/core_test_folder] Error 2 make[1]: Leaving directory '/usr/src/kernels/3.10.0-1160.119.1.el7.x86_64' Makefile:7: recipe for target 'default' failed make: *** [default] Error 2
08-12
<think>我们遇到了一个内核模块编译错误,主要问题集中在代码中的几个方面: 1. 使用了不兼容的`proc_ops`结构体(在较旧内核中可能不存在) 2. 网络钩子注册函数`nf_register_net_hook`可能未声明(需要包含正确的头文件) 3. 指针类型不匹配(如`nfho.hook`赋值和`proc_create`参数传递) 4. 警告被当作错误处理(由于`-Werror`编译选项) 具体分析: - 错误:`struct proc_ops`类型不完全,且出现未知字段(如`.proc_open`)。这是因为在较新的内核版本(5.6+)中引入了`proc_ops`结构体替代了旧的`file_operations`,但在旧内核(如3.10)中不存在。 - 错误:`nf_register_net_hook`和`nf_unregister_net_hook`隐式声明,说明未包含必要的头文件(如`#include <linux/netfilter.h>`)。 - 警告:`min`宏比较不相关的指针(可能是由于类型不匹配,但这里可能不是致命问题,但被`-Werror`升级为错误) - 错误:`proc_create`期望的是`file_operations`结构体,但传递的是`proc_ops`(在旧内核中,我们应使用`file_operations`) 解决方案: 步骤1:针对proc文件系统接口的修改 在Linux 3.10中,我们应使用`file_operations`结构体,而不是`proc_ops`。修改相关代码如下: 原代码(新内核): static const struct proc_ops ping_stat_fops = { .proc_open = ping_stat_open, .proc_read = seq_read, .proc_lseek = seq_lseek, .proc_release = single_release, }; 修改为(旧内核): static const struct file_operations ping_stat_fops = { .owner = THIS_MODULE, .open = ping_stat_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; 步骤2:包含必要的头文件 在文件开头添加: #include <linux/netfilter.h> // 用于nf_register_net_hook等 #include <linux/netfilter_ipv4.h> // 用于NF_INET_* 钩子点 步骤3:修复钩子函数指针类型 错误:`nfho.hook = ping_hook;` 有警告,因为`nfho.hook`的类型与`ping_hook`类型不匹配。 在旧内核中,钩子函数应该定义为: unsigned int ping_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) 注意:在旧版本内核(如3.10)中,钩子函数的签名可能不同。实际上,在3.10中,钩子函数签名是: unsigned int (*hook)(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)); 但是,从错误信息中我们无法确定原函数的签名。因此,需要根据内核版本调整钩子函数签名。 如果原代码使用的是新内核的钩子函数签名(如4.1+),则需改为旧签名。例如: 原代码(新内核): static unsigned int ping_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) 修改为(3.10内核): static unsigned int ping_hook(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) 同时,在函数内部,如果需要获取网络命名空间等信息,需要通过其他方式(如`dev_net(in)`)获取。 步骤4:调整`proc_create`调用 在旧内核中,`proc_create`的第四个参数是`const struct file_operations *`,我们已经修改了`ping_stat_fops`的类型,所以直接传递即可。 步骤5:处理`min`宏警告 这个警告是因为比较两个不同类型的指针(可能是`stats.count`和`MAX_ENTRIES`类型不一致)。确保`stats.count`是`size_t`或`int`类型,`MAX_ENTRIES`是整型。或者显式转换: for (i = 0; i < min((size_t)stats.count, (size_t)MAX_ENTRIES); i++) { 但注意:`min`宏要求两个参数类型相同,所以转换一下即可。 步骤6:消除隐式声明错误 我们已经通过包含头文件解决了`nf_register_net_hook`的隐式声明问题。 步骤7:如果仍然有警告被当作错误,可以临时去掉`-Werror`(不推荐),但最好修复所有警告。 修改后的关键代码示例: 1. 包含头文件: #include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> 2. 修改钩子函数签名(根据3.10内核): static unsigned int ping_hook(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { // 函数体 } 3. 修改`file_operations`结构体(注意:旧内核没有`proc_ops`): static const struct file_operations ping_stat_fops = { .owner = THIS_MODULE, .open = ping_stat_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; 4. 在`ping_stat_init`中,注册钩子: struct nf_hook_ops nfho = { .hook = ping_hook, .pf = NFPROTO_IPV4, .hooknum = NF_INET_PRE_ROUTING, // 根据实际需要选择钩子点 .priority = NF_IP_PRI_FIRST, // 优先级 }; nf_register_hook(&nfho); // 注意:在旧内核(3.10)中,可能使用`nf_register_hook`而不是`nf_register_net_hook` 注意:在3.10内核中,注册钩子的函数是`nf_register_hook`(全局钩子)或`nf_register_hooks`(多个钩子),而不是`nf_register_net_hook`。`nf_register_net_hook`是新版本(4.x+)的函数。 因此,我们需要将注册和注销函数改为: int ret = nf_register_hook(&nfho); // 返回0表示成功 // 错误处理 注销时: nf_unregister_hook(&nfho); 5. 修改`proc_create`调用(注意:旧内核中,第三个参数是`struct proc_dir_entry *`,这里用`NULL`表示在`/proc`根目录): proc_entry = proc_create("ping_stats", 0, NULL, &ping_stat_fops); 6. 修复`min`宏警告: 检查`stats.count`和`MAX_ENTRIES`的类型,确保它们都是整数类型,并且类型一致。或者进行强制类型转换。 总结:主要问题是代码针对的是较新内核(5.6+),而编译环境是旧内核(3.10)。需要根据内核版本调整代码。 如果以上修改后仍有问题,请检查内核头文件版本,并参考对应版本的示例代码。 由于内核API变化较大,建议参考内核源码中相同版本的类似模块的写法。 §§相关问题§§ 1. 在Linux内核开发中,如何编写兼容多个内核版本的模块代码(例如同时支持3.10和5.10内核)?请列举常用的版本适配技巧。 2. 当使用`proc_create`创建/proc文件时,新内核(5.6+)引入的`proc_ops`结构体相比旧的`file_operations`有哪些改进?这种变更有何技术背景? 3. Linux内核网络过滤框架从3.10到5.15版本经历了哪些重大API变更(重点说明`nf_hook_ops`结构体、注册函数和钩子函数签名的变化)? 4. 在内核模块编译过程中,如何通过修改Makefile参数来临时禁用`-Werror`编译选项?这种操作在生产环境中有何风险? 5. 对于需要支持旧版Linux内核(如2.6.32)的模块开发,在获取内核头文件时有哪些特殊注意事项?如何解决头文件缺失或版本冲突问题?</think>### 内核模块编译错误分析与解决方案 #### 核心问题诊断 1. **内核版本兼容性问题** - 错误 `struct proc_ops` 未定义:该结构在 Linux 5.6+ 引入,而您使用的是 3.10 内核 - 函数 `nf_register_net_hook` 未声明:该 API 在 4.1+ 内核引入 2. **类型不匹配警告** - `min()` 宏中的指针类型不兼容 - `proc_create()` 参数类型不匹配(期望 `file_operations`) 3. **函数签名变更** - Netfilter 钩子函数签名在 3.10 与新版内核不同 - 注册函数从 `nf_register_hook()` 变更为 `nf_register_net_hook()` --- ### 完整修复方案 #### 1. 解决 `proc_ops` 兼容性问题(回退到 `file_operations`) ```c // 替换 proc_ops 为 file_operations static const struct file_operations ping_stat_fops = { .owner = THIS_MODULE, .open = ping_stat_open, // 注意字段名变更 .read = seq_read, .llseek = seq_lseek, .release = single_release, }; // proc_create() 调用保持不变 proc_entry = proc_create("ping_stats", 0, NULL, &ping_stat_fops); ``` #### 2. 修复 Netfilter 钩子兼容性 ```c #include <linux/netfilter_ipv4.h> // 添加头文件 // 使用 3.10 内核的钩子函数签名 static unsigned int ping_hook( unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *) ) { // 函数实现 } // 注册钩子(使用旧版 API) struct nf_hook_ops nfho = { .hook = ping_hook, .pf = NFPROTO_IPV4, .hooknum = NF_INET_PRE_ROUTING, // 根据实际需求选择钩子点 .priority = NF_IP_PRI_FIRST, }; // 替换注册函数 nf_register_hook(&nfho); // 注册 nf_unregister_hook(&nfho); // 注销 ``` #### 3. 修复类型不匹配警告 ```c // 修复 min() 宏的类型问题 for (i = 0; i < min_t(size_t, stats.count, MAX_ENTRIES); i++); // 添加类型转换消除 proc_create() 警告 proc_entry = (struct proc_dir_entry *)proc_create(...); ``` #### 4. 头文件补充(关键) ```c #include <linux/netfilter.h> // 基本 Netfilter API #include <linux/netfilter_ipv4.h> // IPv4 特定钩子 #include <linux/seq_file.h> // seq_file 操作 #include <linux/proc_fs.h> // proc 文件系统 ``` --- ### 内核版本适配参考表 | 功能 | 3.10 内核方案 | 5.6+ 内核方案 | |----------------|----------------------------|--------------------------| | proc 操作 | `file_operations` | `proc_ops` | | Netfilter 注册 | `nf_register_hook()` | `nf_register_net_hook()` | | 钩子函数签名 | 5 参数版本 | 4 参数版本 | | 模块初始化 | `module_init()` | `fs_initcall()` | --- ### 编译验证步骤 1. 保存修改后的代码 2. 清理编译环境: ```bash make clean ``` 3. 重新编译: ```bash make -C /lib/modules/$(uname -r)/build M=$PWD modules ``` 4. 验证输出: ``` LD [M] /path/to/your_module.ko ``` #### 技术说明 - **内核版本检测宏**(可选): ```c #include <linux/version.h> #if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0) // 使用旧版 API #endif ``` - **签名变更详情**: ```mermaid graph LR A[3.10 内核] --> B[5 参数钩子函数] C[4.1 内核] --> D[nf_register_net_hook] E[5.6 内核] --> F[proc_ops 结构体] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值