C:信号处理和信号量
C: Signal handling and semaphores
我正在尝试更好地理解信号量和所有爵士乐,为此我正在编写使用共享内存和信号量进行通信的服务器和客户端。它工作得很好,一切都很好,但我不确定我是否理解在这种情况下信号处理是如何正常工作的。这是来自我的服务器的一些示例代码。我意识到检查两者可能有点多余,但我有点想了解我遇到的奇怪行为:
sig_atomic_t running = 1;
while(running == 1) {
if (sem_wait(server) == -1) {
//exit and print error A
}
if(running == 0) {
//exit and print error B
}
/* do server stuff */
if (sem_post(client) == -1) {
//exit and print error
}
}
server 是服务器信号量名称,client 是客户端信号量名称(在这种情况下并不重要)。 运行(实际上是全局变量)是我在信号处理程序中使用的变量:
static void init_signalhandler() {
struct sigaction sa;
sa.sa_handler = terminate;
if(sigemptyset(&(sa.sa_mask)) == -1) {
bail_out(EXIT_FAILURE, "sigemptyset error");
}
if(sigaction(SIGINT, &sa, NULL) == -1) {
bail_out(EXIT_FAILURE, "sigaction1 error");
}
if(sigaction(SIGTERM, &sa, NULL) == -1) {
bail_out(EXIT_FAILURE, "sigaction2 error");
}
}
static void terminate(int e) {
running = 0;
sem_post(server);
}
其中 bail_out 是自定义错误 printing/exiting 函数。
基本上无论我做什么,每当我启动服务器时,它都会到达 sem_wait(server)
部分。如果我尝试通过发送 SIGINT 来终止它,有时它会打印错误 A,而其他时候它会打印错误 B。这似乎是完全随机的。不过,这有点迫使我使用 运行 变量,因为有时信号量会通过,而在其他时候则不会。
由于您没有处理来自 sem_wait(3)
的 EINTR
,因此行为完全符合预期。
例如,您在 sem_wait(server)
等候。您得到 SIGINT
并正确处理它。您的 sem_wait 函数将 return -1
并且您将退出。
你应该做什么:
if (sem_wait(s_server) == -1) {
if(errno == EINTR) continue;
bail_out(EXIT_FAILURE, "sem_wait(3) failed");
}
这将捕获由于 sem_wait 例程中的信号引起的错误,您可以在跳到循环开始时优雅地终止服务器,看到 运行 设置为 0 并跳过循环。
请参阅手册页 sem_wait(3),"Return Values" 了解有关可以处理哪些错误的更多详细信息。
我正在尝试更好地理解信号量和所有爵士乐,为此我正在编写使用共享内存和信号量进行通信的服务器和客户端。它工作得很好,一切都很好,但我不确定我是否理解在这种情况下信号处理是如何正常工作的。这是来自我的服务器的一些示例代码。我意识到检查两者可能有点多余,但我有点想了解我遇到的奇怪行为:
sig_atomic_t running = 1;
while(running == 1) {
if (sem_wait(server) == -1) {
//exit and print error A
}
if(running == 0) {
//exit and print error B
}
/* do server stuff */
if (sem_post(client) == -1) {
//exit and print error
}
}
server 是服务器信号量名称,client 是客户端信号量名称(在这种情况下并不重要)。 运行(实际上是全局变量)是我在信号处理程序中使用的变量:
static void init_signalhandler() {
struct sigaction sa;
sa.sa_handler = terminate;
if(sigemptyset(&(sa.sa_mask)) == -1) {
bail_out(EXIT_FAILURE, "sigemptyset error");
}
if(sigaction(SIGINT, &sa, NULL) == -1) {
bail_out(EXIT_FAILURE, "sigaction1 error");
}
if(sigaction(SIGTERM, &sa, NULL) == -1) {
bail_out(EXIT_FAILURE, "sigaction2 error");
}
}
static void terminate(int e) {
running = 0;
sem_post(server);
}
其中 bail_out 是自定义错误 printing/exiting 函数。
基本上无论我做什么,每当我启动服务器时,它都会到达 sem_wait(server)
部分。如果我尝试通过发送 SIGINT 来终止它,有时它会打印错误 A,而其他时候它会打印错误 B。这似乎是完全随机的。不过,这有点迫使我使用 运行 变量,因为有时信号量会通过,而在其他时候则不会。
由于您没有处理来自 sem_wait(3)
的 EINTR
,因此行为完全符合预期。
例如,您在 sem_wait(server)
等候。您得到 SIGINT
并正确处理它。您的 sem_wait 函数将 return -1
并且您将退出。
你应该做什么:
if (sem_wait(s_server) == -1) {
if(errno == EINTR) continue;
bail_out(EXIT_FAILURE, "sem_wait(3) failed");
}
这将捕获由于 sem_wait 例程中的信号引起的错误,您可以在跳到循环开始时优雅地终止服务器,看到 运行 设置为 0 并跳过循环。
请参阅手册页 sem_wait(3),"Return Values" 了解有关可以处理哪些错误的更多详细信息。