我是C语言的新手,所以问题可能很愚蠢。
我正在写套接字服务器,它操作从客户端发送的数据。获取连接后,它将创建将与请求配合使用的线程。
它还定义了信号处理程序。收到SIGUSR1时,它将调试信息打印到日志文件中。问题是:运行信号处理功能时线程将如何处理?
如果线程继续运行其作业,是否可以在调试处理程序运行时冻结它们?
我试图在手册页中找到pthreads(7)的答案,但此刻还不了解。抱歉,您可能会使用错误的术语。
signal(7)
)信号的配置是每个进程的属性:在多线程应用程序中,特定信号的配置对于所有线程都是相同的。
过程控制信号:过程控制信号是针对整个过程的信号(因此待定)。可以将过程控制的信号传递到当前未阻塞信号的任何一个线程。如果多个线程的信号畅通无阻,则内核选择一个任意线程来将信号传递到该线程。
线程定向信号:线程定向信号是针对特定线程的信号。该集合将由未决的过程控制信号集合和调用线程的未决信号集合的并集组成。
您可以配置程序以告诉您如何处理信号。您可以忽略它们(很少会被忽略),注册一个信号处理程序,该信号处理程序将在收到特定信号时被调用(asynchronous
),或者阻塞它以便稍后处理(synchronous
)。
谈到你的情况,
“问题是:当信号处理功能运行时线程会发生什么?”
信号一次传递到配置为接收该信号的任何线程。异步处理信号的线程将停止正在执行的操作,并跳转到已配置的信号处理程序。其余线程中的执行流程不受影响。
如果线程继续运行其作业,是否可以在调试处理程序运行时冻结它们?
没有标准的方法可以做到这一点。您需要构建自己的机制来启用此功能。
为了进一步研究,需要对调试处理程序的执行位置有一定的了解。在每个线程中main()
还是在特定线程中?
假定main()
实现了日志记录功能,下面将尝试实现相同的基本最低要求。添加了注释,使您可以遍历代码并了解实现。
#define THREAD_MAX_COUNT 100
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <sys/signalfd.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int debug;
sigset_t debug_mask;
pthread_t main_tid;
void* thread_func(void* th_data)
{
/* .... */
for ( ; ; ) {
if (debug) { // If debug procedure starts
printf("Freezing %d\n", *((int*) th_data));
pthread_kill(main_tid, SIGRTMIN); // Notify the main thread about the thread's freeze.
int signo;
sigwait(&debug_mask, &signo); // Wait till logging is done. main() will signal once it is done.
printf("Resuming %d\n", *((int*) th_data));
}
/* ... */
}
return NULL;
}
int main() {
/* Block SIGINT SIGRTMIN*/
sigset_t sigmask;
sigemptyset(&sigmask);
sigaddset(&sigmask, SIGINT);
sigaddset(&sigmask, SIGRTMIN);
pthread_sigmask(SIG_BLOCK, &sigmask, NULL);
/* Set debug variables */
debug = 0;
sigemptyset(&debug_mask);
sigaddset(&debug_mask, SIGRTMIN);
main_tid = pthread_self();
/* Get signalfd for SIGINT */
int sigfd = signalfd(-1, &sigmask, 0);
struct signalfd_siginfo sigbuf;
/* Select variable initializations */
fd_set rd_set, tr_set;
FD_ZERO(&rd_set);
FD_SET(sigfd, &rd_set);
int td_count = 0;
pthread_t tids[THREAD_MAX_COUNT];
for ( ; ; ) {
/* Wait for signal */
tr_set = rd_set;
select(sigfd + 1, &tr_set, NULL, NULL, NULL);
if (FD_ISSET(sigfd, &tr_set)) {
/* Read the pending signal */
read(sigfd, &sigbuf, sizeof(sigbuf));
/* Start logging */
debug = 1;
int signo;
for (int count = 0; count < td_count; count++) {
/* Wait for all threads to freeze */
sigwait(&debug_mask, &signo);
}
printf("Logging...\n");
sleep(3);
/* End logging and resume threads */
debug = 0;
for (int count = 0; count < td_count; count++)
pthread_kill(tids[count], SIGRTMIN);
/* Note below code is for testing purpose; Creates new thread on each interruption */
int* td_data = malloc(sizeof(int));
*td_data = td_count;
pthread_create(tids + td_count, NULL, thread_func, td_data);
td_count++;
}
}
return 0;
}
终端会议:
$ gcc SO.c -lpthread
$ ./a.out
^CLogging...
^CFreezing 0
Logging...
Resuming 0
^CFreezing 0
Freezing 1
Logging...
Resuming 0
Resuming 1
^CFreezing 0
Freezing 1
Freezing 2
Logging...
Resuming 1
Resuming 0
Resuming 2
^CFreezing 2
Freezing 3
Freezing 1
Freezing 0
Logging...
Resuming 1
Resuming 3
Resuming 2
Resuming 0
^CFreezing 1
Freezing 4
Freezing 3
Freezing 0
Freezing 2
Logging...
Resuming 1
Resuming 2
Resuming 0
Resuming 4
Resuming 3
^CFreezing 3
Freezing 0
Freezing 4
Freezing 2
Freezing 5
Freezing 1
Logging...
Resuming 0
Resuming 1
Resuming 2
Resuming 5
Resuming 3
Resuming 4
^\Quit (core dumped)
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句