2010-09-27 3 views
1

Я пишу базовую библиотеку потоков пользовательского уровня. Прототип функции для создания потока является thr_create (start_func_pointer,arg) { make_context(context_1,start_func) } Добавление обработчика сигнала к функции в C для библиотеки потоков

start_func будет определяется пользователем и может меняться в зависимости от пользователя/программы

сразу после создания потока, если начать выполнение его с помощью swapcontext(context_1,context_2)

функция start_func начнет работать. Теперь, если приходит сигнал, мне нужно его обработать. К сожалению, у меня просто есть дескриптор start_func, поэтому я не могу определить действие сигнала внутри start_func

есть способ, которым я могу добавить структуру обработки сигнала внутри start_function и указать его на мой код. что-то вроде этого

thr_create (start_func_pointer,arg) { start_func.add_signal_hanlding_Structure = my_signal_handler(); make_context(context_1,start_func) } Кто-нибудь знает, как это делает posix?

ответ

1

Если вы говорите об улавливании реальных сигналов из реальной операционной системы, на которой вы работаете, я считаю, что вам нужно будет делать это приложение в широком диапазоне, а затем передавать сигналы вниз в каждый поток (подробнее об этом позже) , Проблема в том, что это осложняется, если два (или более) из ваших потоков пытаются использовать alarm, который использует SIGALRM - когда возникает реальный сигнал, вы можете его поймать, но затем, кому вы его доставляете (один или все) потоков?).

Если вы говорите о передаче и улавливании сигналов только среди потоков внутри программы, используя вашу библиотеку, тогда отправка сигнала в поток заставит его быть отмеченным готовым к запуску, даже если он ждал чего-то еще ранее, и тогда любая функция обработки сигнала будет вызвана из вашего кода возобновления потока. Если я помню из ваших предыдущих вопросов, у вас была функция с именем thread_yield, которая была вызвана, чтобы разрешить запуск следующего потока. Если это так, то thread_yield необходимо проверить список ожидающих сигналов и выполнить предварительные операции перед возвратом туда, где был вызван thread_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 (который только сигнал, который я сделал для демонстрационных целей).

Каждый из ваших блоков управления потоком (или как бы вы их вызываете) должен иметь таблицу обработчика сигналов (или список или что-то еще) и список ожидающих сигналов или способ маркировать сигналы как ожидающие. Ожидающие сигналы будут проверяться (возможно, в некотором порядке на основе приоритета), и действие обработчика выполняется для каждого ожидающего сигнала перед возвратом к нормальному коду потоков.

+0

спасибо, это то, что я хотел знать. Я говорю об улавливании реальных сигналов, генерируемых таймерами. Поэтому я вижу, что вы зарегистрировали обработчик сигнала в start_func. Я думал как пользователь, мне нужно было бы определить только функцию без написания обработчика, и библиотека должна позаботиться об остальном. Скажем, например, у вас есть функция в вашей основной программе(), которая непрерывно петляет. Когда вы нажимаете Ctrl + C, программа останавливается. Поскольку вы не определили какой-либо обработчик в основном, как это сделать, чтобы вызвать обработчик для уничтожения потока/процесса? – cyrux

+0

Если вы запускаете программу, используя вашу библиотеку, и отправляете ее SIGINT (Ctrl C), тогда весь процесс получает это, потому что ваша потоковая передача - это потоковая передача в пользовательском пространстве, поэтому вам придется регистрировать обработчик сигналов для каждого сигнала, который вам интересен передавая вниз ваши потоки и передавая их вниз (отметьте поток как сигнализированный и готовый к запуску). Затем, когда этот поток вот-вот запустится, вы посмотрите на действия, которые должны выполняться для его ожидающих сигналов. Для SIGINT действие по умолчанию - это уничтожение процесса (в этом случае поток). – nategoose

+0

@cyrux: Я понял, что вы, возможно, говорили о том, как расположение сигнала первоначально настроено в POSIX. Во время вилки они остаются неизменными, но во время вызова exec каждый проверяется на специальные распоряжения (игнорировать, выходить, по умолчанию), и если он установлен в один из них, он остается один, иначе он установлен по умолчанию для этого сигнала , – nategoose

Смежные вопросы