gpt4 book ai didi

c++ - Linux 不尊重 SCHED_FIFO 优先级? (正常或 GDB 执行)

转载 作者:行者123 更新时间:2023-12-02 10:26:50 29 4
gpt4 key购买 nike

TL;DR
在多处理器/多核引擎上,可以在多个执行单元上调度多个 RT SCHED_FIFO 线程。因此优先级为 60 的线程和优先级为 40 的线程可以同时在 2 个不同的内核上运行。
这可能是违反直觉的,尤其是在模拟(通常像今天一样)在单核处理器上运行并依赖严格优先级执行的嵌入式系统时。
my other answer在这篇文章中进行总结

原问题描述
即使使用非常简单的代码来使 Linux 使用调度策略 SCHED_FIFO 尊重我的线程的优先级,我也遇到了困难。

  • 请参阅问题末尾的 MCVE。
  • 请参阅答案
  • 中修改后的 MCVE

    这种情况来自需要在 Linux PC 下模拟嵌入式代码以执行集成测试 main具有fifo优先级的线程 10将启动线程 divisorratio . divisor线程应该得到 priority 2使 ratio线程与 priority 1在 b 获得合适的值之前不会评估 a/b(这只是 MCVE 的完全假设场景,而不是带有信号量或条件变量的真实案例)。
    潜在先决条件: 您需要是 root 或更好的 设置上限 程序,以便可以更改调度策略和优先级 sudo setcap cap_sys_nice+ep main
    johndoe@VirtualBox:~/Code/gdb_sched_fifo$ getcap main
    main = cap_sys_nice+ep
  • 第一个实验是在具有 2 个 vCPU(gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0,GNU gdb (Ubuntu 8.1-0ubuntu3.2) 8.1.0.20180409-git)的 Virtualbox 环境下进行的,代码行为几乎是 OK正常执行但 NOK在 GDB 下。
  • Native Ubuntu 20.04 上的其他实验显示非常频繁 NOK即使在使用 I3-1005 2C/4T (gcc (Ubuntu 9.3.0-10ubuntu2) 9.3.0, GNU gdb (Ubuntu 9.1-0ubuntu1) 9.1) 正常执行时的行为

  • 基本编译:
    johndoe@VirtualBox:~/Code/gdb_sched_fifo$ g++ main.cc -o main -pthread
    正常执行有时可以,有时如果没有 root 或没有 setcap 则不行
    johndoe@VirtualBox:~/Code/gdb_sched_fifo$ ./main
    Problem with setschedparam: Operation not permitted(1) <<-- err msg if no root or setcap
    Result: 0.333333 or Result: Inf <<-- 1/3 or div by 0
    正常执行正常(例如使用 setcap )
    johndoe@VirtualBox:~/Code/gdb_sched_fifo$ ./main
    Result: 0.333333
    现在,如果您想调试此程序,您将再次收到错误消息。
    (gdb) run
    Starting program: /home/johndoe/Code/gdb_sched_fifo/main
    [Thread debugging using libthread_db enabled]
    Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
    [New Thread 0x7f929a6a9700 (LWP 2633)]
    Problem with setschedparam: Operation not permitted(1) <<--- ERROR MSG
    Result: inf <<--- DIV BY 0
    [New Thread 0x7f9299ea8700 (LWP 2634)]
    [Thread 0x7f929a6a9700 (LWP 2633) exited]
    [Thread 0x7f9299ea8700 (LWP 2634) exited]
    [Inferior 1 (process 2629) exited normally]
    这在这个问题 gdb appears to ignore executable capabilities 中有解释。 (几乎所有答案都可能是相关的)。
    所以就我而言,我做到了
  • sudo setcap cap_sys_nice+ep /usr/bin/gdb
  • set startup-with-shell off 创建一个 ~/.gdbinit

  • 结果我得到了:
    (gdb) run
    Starting program: /home/johndoe/Code/gdb_sched_fifo/main
    [Thread debugging using libthread_db enabled]
    Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
    [New Thread 0x7ffff6e85700 (LWP 2691)]
    Result: inf <<-- NO ERR MSG but DIV BY 0
    [New Thread 0x7ffff6684700 (LWP 2692)]
    [Thread 0x7ffff6e85700 (LWP 2691) exited]
    [Thread 0x7ffff6684700 (LWP 2692) exited]
    [Inferior 1 (process 2687) exited normally]
    (gdb)
    所以结论和问题
  • 我以为唯一的问题来自 GDB
  • 对另一个(非虚拟)目标的测试在正常执行下显示更糟糕的结果

  • 我看到其他与 RT SCHED_FIFO 相关的问题没有得到尊重,但我发现答案没有或不明确的结论。我的 MCVE 也更小,潜在的副作用更少
    Linux SCHED_FIFO not respecting thread priorities
    SCHED_FIFO higher priority thread is getting preempted by the SCHED_FIFO lower priority thread?
    评论带来了一些答案,但我仍然不相信......(......它应该像这样工作)
    MCVE:
    #include <iostream>
    #include <thread>
    #include <cstring>

    double a = 1.0F;
    double b = 0.0F;

    void ratio(void)
    {
    struct sched_param param;
    param.sched_priority = 1;
    int ret = pthread_setschedparam(pthread_self(),SCHED_FIFO,&param);
    if ( 0 != ret )
    std::cout << "Problem with setschedparam: " << std::strerror(errno) << '(' << errno << ')' << "\n" << std::flush;

    std::cout << "Result: " << a/b << "\n" << std::flush;
    }

    void divisor(void)
    {
    struct sched_param param;
    param.sched_priority = 2;
    pthread_setschedparam(pthread_self(),SCHED_FIFO,&param);

    b = 3.0F;

    std::this_thread::sleep_for(std::chrono::milliseconds(2000u));
    }


    int main(int argc, char * argv[])
    {
    struct sched_param param;
    param.sched_priority = 10;
    pthread_setschedparam(pthread_self(),SCHED_FIFO,&param);

    std::thread thr_ratio(ratio);
    std::thread thr_divisor(divisor);

    thr_ratio.join();
    thr_divisor.join();

    return 0;
    }

    最佳答案

    您的 MCVE 有一些明显错误的地方:

  • 您在 b 上存在数据竞争,即未定义的行为,所以任何事情都可能发生。
  • 您期望 divisor线程将完成pthread_setschedparamratio 之前调用线程开始计算比率。
    但是绝对不能保证第一个线程不会在第二个线程创建之前很久就运行完成。
    事实上,这就是在 GDB 下可能发生的事情:它必须捕获线程创建和销毁事件以跟踪所有线程,因此在 GDB 下创建线程比在它之外创建线程要慢得多。

  • 要解决第二个问题,添加一个计数信号量,并让两个线程在各自执行 pthread_setschedparam称呼。

    关于c++ - Linux 不尊重 SCHED_FIFO 优先级? (正常或 GDB 执行),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64061391/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com