/proc/pid/stat 中的 Linux 任务状态与计划事件的 Ftrace 输出不同

/proc/pid/stat 中的 Linux 任务状态与计划事件的 Ftrace 输出不同

我试图跟踪一段代码的流程,只是为了了解任务进入 D/S/R 状态(不可中断/可中断/运行)的点。我确实理解每个状态的含义,但是进行练习显示出令人困惑的结果,直到现在我才弄清楚原因。

我正在运行的代码片段:

void foo() {

    pthread_setname_np(pthread_self(), "lock_func/1");

    while(quit == false)
    {
        for(int64_t idx=0; idx<10000000;idx++)
            (void)idx;
        flag = true;
        cv1.notify_all();
    }
}

void bar() {

    pthread_setname_np(pthread_self(), "lock_func/2");
    std::mutex mutex1;
    std::unique_lock<std::mutex> lock(mutex1);
    while(!flag)
        cv1.wait(lock);
    flag = false;
}

int main(int argc, char *argv[]) {

    ...
    std::thread t1 = std::thread(foo);
    std::thread t2 = std::thread(bar);
    ...
    if (mlockall( MCL_CURRENT | MCL_FUTURE ) < 0) { 
        perror("mlockall") 
    }
    ....   
}

设置标志时我故意不使用互斥锁,因为我不希望 foo 线程被阻塞。所以我不在乎 bar 是否错过了一些唤醒,无论如何它都会由于循环而不时被唤醒。这里的目标只是查看以下状态富和酒吧任务,现在更关注酒吧。如果我在 ftrace 中跟踪 sched_switch 事件,我会得到以下信息:

      <idle>-0     [007] d...       335998: sched_switch: prev_comm=swapper/7 prev_pid=0 prev_prio=120 prev_state=S ==> next_comm=lock_func/1 next_pid=30296 next_prio=120
 lock_func/1-30296 [007] d...       335999: sched_switch: prev_comm=lock_func/1 prev_pid=30296 prev_prio=120 prev_state=D ==> next_comm=swapper/7 next_pid=0 next_prio=120
      <idle>-0     [007] d...       336000: sched_switch: prev_comm=swapper/7 prev_pid=0 prev_prio=120 prev_state=S ==> next_comm=lock_func/1 next_pid=30296 next_prio=120
 lock_func/1-30296 [007] d...       336001: sched_switch: prev_comm=lock_func/1 prev_pid=30296 prev_prio=120 prev_state=D ==> next_comm=swapper/7 next_pid=0 next_prio=120
      <idle>-0     [007] d...       336002: sched_switch: prev_comm=swapper/7 prev_pid=0 prev_prio=120 prev_state=S ==> next_comm=lock_func/1 next_pid=30296 next_prio=120
 lock_func/1-30296 [007] d...       336003: sched_switch: prev_comm=lock_func/1 prev_pid=30296 prev_prio=120 prev_state=D ==> next_comm=swapper/7 next_pid=0 next_prio=120
      <idle>-0     [007] d...       336004: sched_switch: prev_comm=swapper/7 prev_pid=0 prev_prio=120 prev_state=S ==> next_comm=lock_func/1 next_pid=30296 next_prio=120
 lock_func/1-30296 [007] d...       336005: sched_switch: prev_comm=lock_func/1 prev_pid=30296 prev_prio=120 prev_state=D ==> next_comm=swapper/7 next_pid=0 next_prio=120
      <idle>-0     [007] d...       336006: sched_switch: prev_comm=swapper/7 prev_pid=0 prev_prio=120 prev_state=S ==> next_comm=lock_func/1 next_pid=30296 next_prio=120
 lock_func/1-30296 [007] d...       336007: sched_switch: prev_comm=lock_func/1 prev_pid=30296 prev_prio=120 prev_state=D ==> next_comm=swapper/7 next_pid=0 next_prio=120
      <idle>-0     [007] d...       336008: sched_switch: prev_comm=swapper/7 prev_pid=0 prev_prio=120 prev_state=S ==> next_comm=lock_func/1 next_pid=30296 next_prio=120
 lock_func/1-30296 [007] d...       336009: sched_switch: prev_comm=lock_func/1 prev_pid=30296 prev_prio=120 prev_state=D ==> next_comm=swapper/7 next_pid=0 next_prio=120
      <idle>-0     [000] d...       336010: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=S ==> next_comm=lock_func/1 next_pid=30296 next_prio=120
 lock_func/1-30296 [000] d...       336011: sched_switch: prev_comm=lock_func/1 prev_pid=30296 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
      <idle>-0     [000] d...       336012: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=S ==> next_comm=lock_func/1 next_pid=30296 next_prio=120

观察我的 lock_func1 (bar) 的 prev_state 始终如何D(不间断)。查看代码,上下文切换只能在条件变量 sleep 时发生,或者当时间片完成时(在 CFS 调度程序中运行)

cat /proc/30295/task/30296/wchan
futex_wait_queue_me

根据文档,这是一个可中断的函数。多次检查 proc 中的任务状态始终显示S:

cat /proc/30295/task/30296/stat
30295 (lock_func/1) S ...

所以统计显示S-可中断状态,futex_wait_queue_me是可中断的,但是 ftrace 总是在上下文切换时显示上一个状态=D。运行此代码并使用 ftrace 记录几秒钟仅显示上一个状态=D对于我的lock_func/1(条)。我从来没有得到过S-中断。

有人可以解释为什么吗?调度程序是否在两者之间进行一些状态更改?

谢谢。

相关内容