本文介绍了Sigaction将SIGINT传递给系统调用,但不传递信号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我有一个处理accept(2)
调用的循环。我希望在向程序发送SIGINT
时能够执行一些清理。我的第一个想法是使用signal
函数。
void signal_handler(int signal) {
printf("Caught signal
");
}
int main() {
signal(SIGINT, &signal_handler);
// ...
int accept_fd = accept(sock, NULL, NULL);
if (accept_fd == -1) {
close(sock);
perror("accept");
return 1;
}
// ...
}
但是,这只是打印";捕获信号&,然后程序继续运行。
如果我将main
修改为使用sigaction
,程序将按预期运行。
int main() {
struct sigaction sa;
sa.sa_handler = &signal_handler;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sigaction(SIGINT, &sa, NULL);
// ...
int accept_fd = accept(sock, NULL, NULL);
if (accept_fd == -1) {
close(sock);
perror("accept");
return 1;
}
// ...
}
发送SIGINT后,我得到Caught Signal
,然后是accept: Interrupted system call
。从accept(2)
我知道sigaction
更现代,我应该比signal
使用它,但我很好奇为什么它在功能上有这样的区别。
下面我为每种情况都包括了一个完整的可用的示例程序。
带信号(2)的示例
#include <netdb.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define BUFFER_SIZE 32
void signal_handler(int signal) {
printf("Caught signal
");
}
int main() {
signal(SIGINT, &signal_handler);
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
struct addrinfo *addr_info;
int info_result = getaddrinfo("localhost", "8080", &hints, &addr_info);
if (info_result != 0) {
printf("Getting address failed
");
return 1;
}
int sock = socket(addr_info->ai_family, addr_info->ai_socktype, addr_info->ai_protocol);
if (sock == -1) {
printf("Socket Failed
");
return 1;
}
int bind_result = bind(sock, addr_info->ai_addr, addr_info->ai_addrlen);
if (bind_result == -1) {
close(sock);
printf("Bind Failed
");
return 1;
}
int listen_result = listen(sock, 8);
if (listen_result == -1) {
close(sock);
printf("Listen Failed
");
return 1;
}
printf("Waiting...
");
int accept_fd = accept(sock, NULL, NULL);
if (accept_fd == -1) {
close(sock);
perror("accept");
return 1;
}
printf("Got fd %d
", accept_fd);
char *buffer = malloc(BUFFER_SIZE * sizeof(char));
int n;
while ((n = read(accept_fd, buffer, BUFFER_SIZE)) > 0) {
printf("%.*s
", n, buffer);
}
close(sock);
}
带sigaction(2)的示例
#include <netdb.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define BUFFER_SIZE 32
void signal_handler(int signal) {
printf("Caught signal
");
}
int main() {
struct sigaction sa;
sa.sa_handler = &signal_handler;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sigaction(SIGINT, &sa, NULL);
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
struct addrinfo *addr_info;
int info_result = getaddrinfo("localhost", "8080", &hints, &addr_info);
if (info_result != 0) {
printf("Getting address failed
");
return 1;
}
int sock = socket(addr_info->ai_family, addr_info->ai_socktype, addr_info->ai_protocol);
if (sock == -1) {
printf("Socket Failed
");
return 1;
}
int bind_result = bind(sock, addr_info->ai_addr, addr_info->ai_addrlen);
if (bind_result == -1) {
close(sock);
printf("Bind Failed
");
return 1;
}
int listen_result = listen(sock, 8);
if (listen_result == -1) {
close(sock);
printf("Listen Failed
");
return 1;
}
printf("Waiting...
");
int accept_fd = accept(sock, NULL, NULL);
if (accept_fd == -1) {
close(sock);
perror("accept");
return 1;
}
printf("Got fd %d
", accept_fd);
char *buffer = malloc(BUFFER_SIZE * sizeof(char));
int n;
while ((n = read(accept_fd, buffer, BUFFER_SIZE)) > 0) {
printf("%.*s
", n, buffer);
}
close(sock);
}
推荐答案
在bsd和linux上,signal()
相当于sigaction()
,sa_flags
设置为SA_RESTART
。如果您在sigaction()
代码中设置了该标志,它的行为将与您的代码相同。如果这不是您想要的,则只能使用sigaction()
。
Linux man page(也适用于BSD和OS X)的说明:
sa.sa_flags = SA_RESTART;
这篇关于Sigaction将SIGINT传递给系统调用,但不传递信号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!