为线程库向C中的函数添加信号处理程序

为线程库向C中的函数添加信号处理程序,c,function-pointers,signals,C,Function Pointers,Signals,我正在编写一个基本的用户级线程库。创建线程的函数原型是 thr_create(启动函数指针,参数) { 创建上下文(上下文1,开始函数) } 启动函数将由用户定义,并可根据用户/程序进行更改 在创建线程之后,如果我开始使用 swapcontext(上下文1、上下文2) 函数start_func将开始运行。现在,如果有信号进来,我需要处理它。不幸的是,我只有start_func的句柄,因此我无法在start_func中真正定义信号操作 是否有一种方法可以在start_函数中添加一个信号处理结构

我正在编写一个基本的用户级线程库。创建线程的函数原型是

thr_create(启动函数指针,参数)
{
创建上下文(上下文1,开始函数)
}

启动函数将由用户定义,并可根据用户/程序进行更改

在创建线程之后,如果我开始使用
swapcontext(上下文1、上下文2)

函数start_func将开始运行。现在,如果有信号进来,我需要处理它。不幸的是,我只有start_func的句柄,因此我无法在start_func中真正定义信号操作

是否有一种方法可以在start_函数中添加一个信号处理结构,并将其指向我的代码。像这样的


thr_create(启动函数指针,参数)
{
start_func.add_signal_hanlding_Structure=my_signal_handler();
创建上下文(上下文1,开始函数)
}

有人知道posix是怎么做到的吗?

如果你说的是从你正在运行的实际操作系统中捕获真实信号,我相信你必须在整个应用程序范围内完成这项工作,然后将信号传递到每个线程中(稍后将对此进行详细介绍)。问题是,如果您的两个(或更多)线程试图使用使用
SIGALRM
alarm
——当真正的信号发生时,您可以捕捉到它,但是您将它传递给谁(一个或所有线程?)

如果您正在谈论使用库在程序中的线程之间发送和捕获信号,那么向线程发送信号将导致它被标记为准备运行,即使它之前正在等待其他内容,然后任何信号处理功能都将从线程恢复代码中调用。如果我还记得你之前的问题,你有一个名为
thread\u yield
的函数,它被调用以允许下一个线程运行。如果是这种情况,
thread\u yield
需要检查挂起信号的列表,并在返回调用
thread\u yield
的位置之前执行其操作(除非其中一个信号处理程序涉及终止当前线程,在这种情况下,您必须执行不同的操作)

至于如何实现信号处理程序的注册,在POSIX中,这是由主函数进行的系统调用(直接或间接)完成的。所以你可以:

static int foo_flag = 0;

static void foo_handle(int sig) {
     foo_flag = 1;
}

int start_func(void * arg) {
    thread_sig_register(SIGFOO, foo_handle);

    thread_pause();
    // this is a function that you could write that would cause the current thread
    // to mark itself as not ready to run and then call thread_yield, so that
    // thread_pause() will return only after something else (a signal) causes the
    // thread to become ready to run again.


    if (foo_flag) {
        printf("I got SIGFOO\n");
    } else {
        printf("I don't know what woke me up\n");
    }
    return 0;
}
现在,您可以从另一个线程向这个线程发送一个SIGFOO(这只是我为了演示而制作的一个信号)


您的每个线程控制块(或您调用它们的任何东西)都必须有一个信号处理程序表(或列表,或其他内容)和一个挂起的信号列表,或者有一种将信号标记为挂起的方法。将检查挂起的信号(可能以某种基于优先级的顺序)在返回到线程正常代码之前,处理程序会对每个挂起的信号执行操作。

如果您要从正在运行的实际操作系统捕获实际信号,我相信您必须在整个应用程序范围内执行此操作,然后将信号向下传递到每个线程(稍后将对此进行详细介绍)。问题是,如果您的两个(或更多)线程试图使用使用
SIGALRM
alarm
——当真正的信号发生时,您可以捕捉到它,但是您将它传递给谁(一个或所有线程?)

如果您正在谈论使用库在程序中的线程之间发送和捕获信号,那么向线程发送信号将导致它被标记为准备运行,即使它之前正在等待其他内容,然后任何信号处理功能都将从线程恢复代码中调用。如果我还记得你之前的问题,你有一个名为
thread\u yield
的函数,它被调用以允许下一个线程运行。如果是这种情况,
thread\u yield
需要检查挂起信号的列表,并在返回调用
thread\u yield
的位置之前执行其操作(除非其中一个信号处理程序涉及终止当前线程,在这种情况下,您必须执行不同的操作)

至于如何实现信号处理程序的注册,在POSIX中,这是由主函数进行的系统调用(直接或间接)完成的。所以你可以:

static int foo_flag = 0;

static void foo_handle(int sig) {
     foo_flag = 1;
}

int start_func(void * arg) {
    thread_sig_register(SIGFOO, foo_handle);

    thread_pause();
    // this is a function that you could write that would cause the current thread
    // to mark itself as not ready to run and then call thread_yield, so that
    // thread_pause() will return only after something else (a signal) causes the
    // thread to become ready to run again.


    if (foo_flag) {
        printf("I got SIGFOO\n");
    } else {
        printf("I don't know what woke me up\n");
    }
    return 0;
}
现在,您可以从另一个线程向这个线程发送一个SIGFOO(这只是我为了演示而制作的一个信号)


您的每个线程控制块(或您调用它们的任何东西)都必须有一个信号处理程序表(或列表,或其他内容)和一个挂起的信号列表,或者有一种将信号标记为挂起的方法。将检查挂起的信号(可能是基于优先级的顺序),并在返回到正常代码之前对每个挂起的信号执行处理程序操作。

谢谢,这就是我想知道的。我说的是捕捉定时器产生的真实信号。我看到您已经在start_func中注册了信号处理程序。我认为作为用户,我必须只定义函数而不编写处理程序,库应该负责其余的工作。例如,假设您的程序main()中有一个连续循环的函数。按Ctrl+C时,程序停止。既然您没有在main中定义任何处理程序,那么如何调用该处理程序来终止线程/进程呢?如果您使用库运行一个程序并向它发送一个SIGINT(Ctrl C),那么整个进程都会得到它,因为您的线程是用户空间线程,因此,您必须为要传递给线程的每个信号注册一个信号处理程序,并将它们传递给线程(将线程标记为已发出信号并准备运行)。然后,当该线程即将运行时,您可以查看必须为其挂起的线程执行的操作