我很快就会开始用头撞墙:
这真的很简单,我想测量一个任务在 2 个点之间花费的时间(在 Linux - 1 个核心 - 1 个 CPU 中)。在此期间,任务必须完全控制 CPU,并且不会被任何其他任务或硬件中断中断。
为了实现这一点,我创建了一个内核模块来确保满足上述标准。在这个内核模块中,我尝试:
首先,禁用 IRQ:
- 我使用了 spin_lock_irqsave()/spin_lock_irqrestore() - 我认为这是确保所有本地中断都被禁用并且我的任务在关键区域期间拥有自己的 cpu 的正确方法。
然后,
- 使用了 preempt_disable() -> 由于 current = my task,那么逻辑上内核应该继续运行我的任务,直到我重新启用抢占 -> 不起作用(my_task->nvcsw 和 my_task->nivcsw 显示发生了 csw ->我的任务被抢占了)
我试图通过将 my_task->prio 和 my_task->static_prio 更改为 1 -> 最高实时优先级(my_task->policy = SCHED_FIFO)来增加我的任务的优先级...
也没有工作(my_task->nvcsw 和 my_task->nivcsw 表明发生了 csw -> my-task 被抢占)并且 my_task->prio 得到了我认为的调度程序的新 prio (120)....
有什么方法可以确定地保证任务在 Linux 中不会被中断/抢占?有没有办法强制调度程序运行任务(短时间 50-500us)直到它完成?
这是我启用/禁用操作系统部分的代码(有问题的任务使用 procfs 在关键区域之前和之后发送启用/禁用命令并由此开关处理):
// Handle request
switch( enable ){
// Disable OS
case COS_OS_DISABLE:
// Disable preemption
preempt_disable()
// Save policy
last_policy = pTask->policy;
// Save task priorities
last_prio = pTask->prio;
last_static_prio = pTask->static_prio;
last_normal_prio = pTask->normal_prio;
last_rt_priority = pTask->rt_priority;
// Set priorities to highest real time prio
pTask->prio = 1;
pTask->static_prio = 1;
pTask->normal_prio = 1;
pTask->rt_priority = 1;
// Set scheduler policy to FIFO
pTask->policy = SCHED_FIFO;
// Lock kernel: It will disable interrupts _locally_, but the spinlock itself will guarantee the global lock, so it will guarantee that there is only one thread-of-control within the region(s) protected by that lock.
spin_lock_irqsave( &mr_lock , flags );
break;
// Default: Enable OS always
case COS_OS_ENABLE:
default:
// Reset task priorities
pTask->prio = last_prio;
pTask->static_prio = last_static_prio;
pTask->normal_prio = last_normal_prio;
pTask->rt_priority = last_rt_priority;
// Reset scheduler policy
pTask->policy = last_policy;
// Unlock kernel
spin_unlock_irqrestore( &mr_lock , flags );
// Enable preemption
preempt_enable();
break;
}