c - sleep 时信号处理比旋转时慢?

标签 c linux signals real-time scheduling

我试图理解为什么当主进程旋转(while(1))时信号的处理速度比 sleep 时更快。

我使用下面的代码创建了一个 500us 的一次性计时器 (基于How to implement highly accurate timers in Linux Userspace?):

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>

#define NSEC_PER_SEC 1000000000L

#define timerdiff(a,b) (((a)->tv_sec - (b)->tv_sec) * NSEC_PER_SEC + \
(((a)->tv_nsec - (b)->tv_nsec)))

struct timespec prev;

void handler( int signo )
{
    struct timespec now;
    unsigned long diff;

    clock_gettime(CLOCK_MONOTONIC, &now);
    diff = timerdiff(&now, &prev);

    printf("%lu\n", diff);

    exit(0);
}

int main(int argc, char *argv[])
{
    int i = 0;
    timer_t t_id;

    struct itimerspec tim_spec = {.it_interval= {.tv_sec=0,.tv_nsec=0},
                    .it_value = {.tv_sec=0,.tv_nsec=500000}};

    struct sigaction act;
    sigset_t set;

    sigemptyset( &set );
    sigaddset( &set, SIGALRM );

    act.sa_flags = 0;
    act.sa_mask = set;
    act.sa_handler = &handler;

    sigaction( SIGALRM, &act, NULL );

    if (timer_create(CLOCK_MONOTONIC, NULL, &t_id))
        perror("timer_create");

    clock_gettime(CLOCK_MONOTONIC, &prev);

    if (timer_settime(t_id, 0, &tim_spec, NULL))
        perror("timer_settime");

#ifdef SLEEP
    while(1)
        sleep(1);
#else
    while(1);
#endif

    return 0;
}

如果代码在定义 SLEEP 的情况下执行,则执行 10 次会得到:

596940
549098
535758
606020
556990
528634
592051
545047
531079
541067
552520

如果未定义 SLEEP,代码将旋转并且我得到这些计时:

512641
510337
509778
510406
510057
507193
511245
511245
511384
509638
510127

这样真的好多了。

谁能给我解释一下吗?退出 sleep 比中断旋转循环慢?

它在 Intel 平台(8 核)上的 Linux 4.9 PREEMPT_RT 修补内核上尝试了此代码,系统处于空闲状态。

谢谢!

奥雷利安

最佳答案

当旋转时,内核不需要准备进程来运行,因为当信号到达时进程已经在运行。它只需更改指令指针即可进入信号处理程序。

如果进程休眠,则必须将其放入任务队列,必须恢复上下文(寄存器、内存映射)以及大量其他准备步骤,直到进程真正运行。

这会产生很小的差异,但如果您查看总数,就会发现总共只有大约 10 - 100 µs。

关于c - sleep 时信号处理比旋转时慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59372436/

相关文章:

c - Linux 3.0 x86_64 : When is SIGSTKFLT raised?

c - void* 作为 C 中的泛型,安全吗?

linux - matlab从linux命令行执行脚本

linux - 我可以在不重新登录的情况下应用 gsettings 吗?

linux - 带文件路径参数的 Windows 10 Bash 和 Google Chrome

c - pthreads:如何处理创建其他线程的主线程中的信号? (具体代码显示)

c - 如何让 ROP 小工具让 shell 工作?

c - 如何在使用 mingw32 构建 llvm 时禁用 llvm-c-test

c - Sem_post() 无法正常工作,既不会增加信号量的值,也不会解锁附加到该信号量的进程

macos - 在 shell 脚本中抑制信号输出,如 "Abort trap: 6",用于应该崩溃的测试