c - 如何使用 swapcontext() 恢复函数的执行(而不是再次启动)?

标签 c multithreading signals scheduler context-switch

我正在构建一个抢占式用户空间线程调度程序,它使用计时器来中断线程并根据优先级在线程之间切换。然而,一旦一个线程被中断,我似乎就不能让它完成;只能重新开始。我所要求的甚至可以使用 swapcontext 吗?该代码的结果应该允许 itake5seconds() 完成,只是一遍又一遍地循环“Hello”消息。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <ucontext.h>

static ucontext_t mainc, newthread;

void itake5seconds()
{
    puts("Hello. I take 5 seconds to run.");
    sleep(5);
    puts("And I'm done! Wasn't that nice?");
}

void timer_handler(int signum)
{
    puts("Doing some scheduler stuff.");
    swapcontext(&mainc, &newthread);
}

int main(int argc, char* argv[])
{
    struct sigaction sa;

    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = &timer_handler;
    sigaction(SIGALRM, &sa, NULL);

    getcontext(&newthread);
    newthread.uc_stack.ss_sp = malloc(5000);
    newthread.uc_stack.ss_size = 5000;
    newthread.uc_link = &mainc;
    makecontext(&newthread, &itake5seconds, 0);

    struct itimerval timer;
    timer.it_value.tv_sec = 0;
    timer.it_value.tv_usec = 500000;
    timer.it_interval.tv_sec = 0;
    timer.it_interval.tv_usec = 500000;

    setitimer(ITIMER_REAL, &timer, NULL);

    while(1);

    return 0;
}

最佳答案

您的代码正在信号处理程序 (swapcontext) 中调用“不安全”函数。因此,您的程序的行为是“未定义的”。

来自man 7 signal :

A signal handler function must be very careful, since processing elsewhere may be interrupted at some arbitrary point in the execution of the program. POSIX has the concept of "safe function". If a signal interrupts the execution of an unsafe function, and handler calls an unsafe function, then the behavior of the program is undefined.

请参阅 Complete Context Control 中的“SVID 上下文处理示例”部分。有关如何使用信号处理程序进行此操作的示例。但基本上,您会使用 volatile int 全局变量来标记您的信号处理程序已被调用,并从普通代码(即不是从内部运行的代码)执行 swapcontext 调用信号处理的上下文)。

关于c - 如何使用 swapcontext() 恢复函数的执行(而不是再次启动)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42310478/

相关文章:

c++ - 如何使用 PKCS 11 创建证书对象

c# - 如何判断线程是否成功退出?

java - Hibernate:在不同线程中查找刚刚持久化的对象

c# - 分析 .net 多线程应用程序 (Visual Studio 2008)

从 bash 脚本运行时,Perl 无法杀死 self pid

c - 如何用C有效编写文本文件,文件大小为5GB

c - 了解代码示例是受 CPU 限制还是受内存限制

c - 当 parent 将数据写入与 fork 的 child 共享的管道并且两者都在读取数据时,如何防止 parent 在 child 之前读取数据?

python - 返回与指针赋值之间的 c_char_p 行为不一致

c - Linux 3.0 x86_64 : When is SIGSTKFLT raised?