我很快就会开始用头撞墙:

这真的很简单,我想测量一个任务在 2 个点之间花费的时间(在 Linux 中 - 1 个核心 - 1 个 CPU)。 在此期间,任务必须完全控制 CPU,并且不会被任何其他任务或硬件中断打断。

为此,我创建了一个内核模块以确保满足上述标准。 在这个内核模块中,我试图:

首先,禁用 IRQ:

  • 我使用了 spin_lock_irqsave()/spin_lock_irqrestore() - 我认为这是确保所有本地中断都被禁用并且我的任务在关键区域期间拥有自己的 cpu 的正确方法。

然后,

  • 使用 preempt_disable() -> 因为 current = 我的任务,那么逻辑上内核应该继续运行我的任务直到我重新启用抢占 -> 不起作用(my_task->nvcsw 和 my_task->nivcsw 显示 csw 有发生了 -> 我的任务被抢占了)

我试图通过将 my_task->prio 和 my_task->static_prio 更改为 1 -> highest real-time prio (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; 
} 

请您参考如下方法:

仅允许在内核代码中禁用中断,并且只能在短时间内使用。 使用标准内核,不可能让用户空间任务完全控制 CPU。

如果您只想测量用户空间任务使用的时间,您可以正常运行任务并使用 u modifer of perf忽略中断;但是,这不会阻止中断处理程序的任何缓存效果。


评论关闭
IT序号网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!