do_ni_syscall

本文探讨了一段kernel log中的未处理系统调用(syscall 133446)。详细介绍了do_ni_syscall函数如何处理内核无法识别的系统调用,并展示了具体的寄存器状态和上下文信息。

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

最近查一个问题,看到一份kernellog里有这么一段:

unionpay.kalefu[29653]: syscall  133446

Code:  e0861001    e2833002   e3a02000    ef000000   (e1a00008)

CPU :   6  PID:  29653  Comm:  unionpay.kalefu   Tainted:  P            W     O   3.10.84-perf-g06f6aec#1

task :    ffffffc093073ac0     ti:    ffffffc0e06fc000    task.ti: ffffffc0e06fc000

PC  is at  0xf2ce90c8

LR  is at  0xf62d607c

pc :  [<00000000f2ce90c8>]  lr :  [<00000000f62d607c>]  pstate:  400e0010

sp :  00000000ffc3da7c

x12:  00000000f6d965dc

x11:  000000000000004d  x10 :  00000000f2d3e364

x9 :  0000000000030664  x8  :  00000000f2cc8008

x7 :  0000000000020664  x6  :  00000000f2c73a68

x5 :  00000000f2c943fe  x4  :  00000000f62db678

x3 :  00000000000f0002  x2  :  0000000000000000

x1 :  00000000f2ca411c  x0  :  00000000f2c73a68

一开始以为是段错误,后来仔细一看没有BUG,也没有打出backtrace,看到有syscall,知道应该跟系统调用有关系,搜索code发现这段log是由do_ni_syscall打印出来的,如下:

asmlinkage long do_ni_syscall(struct pt_regs *regs)
{
#ifdef CONFIG_COMPAT
long ret;
if (is_compat_task()) {
ret = compat_arm_syscall(regs);
if (ret != -ENOSYS)
return ret;
}
#endif


if (show_unhandled_signals && printk_ratelimit()) {
pr_info("%s[%d]: syscall %d\n", current->comm,
task_pid_nr(current), (int)regs->syscallno);
dump_instr("", regs);
if (user_mode(regs))
__show_regs(regs);
}


return sys_ni_syscall();

是中arch/arm64/kernel里的traps.c中定义的,do_ni_syscall函数是当遇到内核无法处理的系统调用时会统一由do_ni_syscall来处理,会把本次无法处理的系统调用发起的进程PID,进程名(comm),系统调用号,以及系统寄存器打出来。从上面的log可以看出这次调用的syscallno是133446,系统式无法处理的。

### 关于 `configMAX_SYSCALL_INTERRUPT_PRIORITY` 和 `configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY` #### 参数定义与作用 `configMAX_SYSCALL_INTERRUPT_PRIORITY` 是 FreeRTOS 的一个重要配置参数,用于定义能够调用 FreeRTOS API 函数的最高中断优先级。这意味着任何高于此优先级的中断都不能安全地调用 FreeRTOS 提供的功能函数,因为这可能导致竞态条件或其他同步问题[^2]。 ```c #define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY >> 3) ``` 在此基础上,`configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY` 则是一个更底层的配置项,通常由硬件平台决定。它表示系统中可分配给中断服务程序的最大优先级值。例如,在 ARM Cortex-M 架构下,中断优先级是以位数来划分的(如常见的 4 位或 8 位),因此需要通过移位操作将其转换为适合 FreeRTOS 使用的形式[^1]。 #### 配置建议 对于具体的取值范围,可以根据目标处理器架构以及实际应用需求设定: - 如果使用的是 ARM Cortex-M 系列微控制器,默认情况下可以选择较低的有效优先级作为 `configMAX_SYSCALL_INTERRUPT_PRIORITY` 值。比如在一个支持 8 位优先级编码器的情况下,推荐设置如下: ```c #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 6 #define configMAX_SYSCALL_INTERRUPT_PRIORITY ((6UL) << (8 - configPRIO_BITS)) ``` 这里假设 `configPRIO_BITS=3` 表示有效优先级宽度,则最终计算得出的结果适用于大多数场景下的中断管理逻辑[^1]。 另外需要注意的一点是关于 `configKERNEL_INTERRUPT_PRIORITY` 的配置,这是为了保障 RTOS 核心功能运行稳定而专门预留的一个极低级别中断源位置;一般而言应设得比所有用户自定义外设驱动所涉及到的各类事件触发机制都要更低一些以便让后者有机会及时响应而不受前者干扰[^2]。 #### 示例代码展示 下面给出一段完整的初始化样例代码片段以帮助理解如何正确完成上述几个关键宏定义之间的关系构建过程: ```c // Assume a priority group of 3 bits for preemption and 5 bits for sub-priority on an ARM Cortex-M device. #define configPRIO_BITS 3 // Maximum system call interrupt priority, should be set according to your application needs. #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 6 // Convert the maximum syscall interrupt priority into a form usable by the kernel. #define configMAX_SYSCALL_INTERRUPT_PRIORITY ((configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY) << (8 - configPRIO_BITS)) // Kernel interrupt priority must always be lower than any other interrupts that may use RTOS APIs. #define configKERNEL_INTERRUPT_PRIORITY 0xFF /* Lowest possible value */ ``` 以上展示了基于典型嵌入式开发环境中的合理实践方法论之一种实现方式说明文档.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值