C 以不同方式处理信号

C 以不同方式处理信号,c,sockets,signals,signal-handling,C,Sockets,Signals,Signal Handling,有人能帮我理解以下三种处理信号的方法之间的区别吗?我在C语言的客户机/服务器上运行 编辑:我知道第一个例子是错误的,现在我想知道哪一个更好/可能,第二个还是第三个?我也在网上读到有人在他们之间进行混合,使用“sigeEmptySet”和“sigaddset”中的“struct sigaction sig”,而不使用任何sigprocmask。这比我的两种解决方案都好吗 处理程序: void closeSig(){ close(socketAccept); close(socket

有人能帮我理解以下三种处理信号的方法之间的区别吗?我在C语言的客户机/服务器上运行

编辑:我知道第一个例子是错误的,现在我想知道哪一个更好/可能,第二个还是第三个?我也在网上读到有人在他们之间进行混合,使用“sigeEmptySet”和“sigaddset”中的“struct sigaction sig”,而不使用任何sigprocmask。这比我的两种解决方案都好吗

处理程序:

void closeSig(){
    close(socketAccept);
    close(socket);
    exit(1);
}
第一个例子:

signal(SIGINT, closeSig);
第二个例子:

sigset_t set;
struct sigaction sig;
sigemptyset(&set);
sigaddset(&set, SIGINT);
sig.sa_sigaction = &closeSig;
sig.sa_flags = SA_SIGINFO;
sig.sa_mask = set;
sigaction(SIGINT, &sig, NULL);
sigprocmask(SIG_UNBLOCK, &set, NULL);
struct sigaction sig;
sig.sa_sigaction = &closeSig;
sig.sa_flags = SA_SIGINFO;
sigaction(SIGINT, &sig, NULL);
sigset_t set;
struct sigaction sig;
sigemptyset(&set);
sigaddset(&set, SIGINT);
sig.sa_sigaction = &closeSig;
sig.sa_flags = SA_SIGINFO;
sig.sa_mask = set;
sigaction(SIGINT, &sig, NULL);
sigprocmask(SIG_UNBLOCK, &set, NULL);
第三个例子:

sigset_t set;
struct sigaction sig;
sigemptyset(&set);
sigaddset(&set, SIGINT);
sig.sa_sigaction = &closeSig;
sig.sa_flags = SA_SIGINFO;
sig.sa_mask = set;
sigaction(SIGINT, &sig, NULL);
sigprocmask(SIG_UNBLOCK, &set, NULL);
struct sigaction sig;
sig.sa_sigaction = &closeSig;
sig.sa_flags = SA_SIGINFO;
sigaction(SIGINT, &sig, NULL);
sigset_t set;
struct sigaction sig;
sigemptyset(&set);
sigaddset(&set, SIGINT);
sig.sa_sigaction = &closeSig;
sig.sa_flags = SA_SIGINFO;
sig.sa_mask = set;
sigaction(SIGINT, &sig, NULL);
sigprocmask(SIG_UNBLOCK, &set, NULL);
根据POSIX,函数
closeSig()
严格来说并不适合信号回调。应该是:

void closeSig(int signum);
struct sigaction sig;
sig.sa_sigaction = &closeSig;
sig.sa_flags = SA_SIGINFO;
sigemptyset(&sig.sa_mask);
sigaction(SIGINT, &sig, NULL);
对于常规回调,但当您使用
SA_SIGINFO
时,它需要:

void closeSig(int signum, siginfo_t *info, void *context);
您还需要查看的POSIX规范

让我们看第二个例子:

sigset_t set;
struct sigaction sig;
sigemptyset(&set);
sigaddset(&set, SIGINT);
sig.sa_sigaction = &closeSig;
sig.sa_flags = SA_SIGINFO;
sig.sa_mask = set;
sigaction(SIGINT, &sig, NULL);
sigprocmask(SIG_UNBLOCK, &set, NULL);
struct sigaction sig;
sig.sa_sigaction = &closeSig;
sig.sa_flags = SA_SIGINFO;
sigaction(SIGINT, &sig, NULL);
sigset_t set;
struct sigaction sig;
sigemptyset(&set);
sigaddset(&set, SIGINT);
sig.sa_sigaction = &closeSig;
sig.sa_flags = SA_SIGINFO;
sig.sa_mask = set;
sigaction(SIGINT, &sig, NULL);
sigprocmask(SIG_UNBLOCK, &set, NULL);
&closeSig
上的
是不必要的,但无害的。但是,问题中显示的
closeSig()
类型是错误的。
sigset\u t
表示调用中断处理程序时,
SIGINT
(仅)将被阻止,但无论如何都会发生,因为标志不包括
SA\u NODEFER
。因此,代码处理
set
对于
sigaction()
是多余的

调用
sigprocmask()
可以解除中断(
SIGINT
)。不清楚为什么叫它;必须先调用
sigprocmask()
,阻止中断,才能发挥作用。但是,在此之后,如果向进程发送了中断,则将使用它不期望的参数调用
closeSig()
函数

第三个例子是:

struct sigaction sig;
sig.sa_sigaction = &closeSig;
sig.sa_flags = SA_SIGINFO;
sigaction(SIGINT, &sig, NULL);
这相当接近于剖析和简化第二个示例中描述的最小操作。主要问题是
sig.sa_mask
设置为不确定值。代码应为:

void closeSig(int signum);
struct sigaction sig;
sig.sa_sigaction = &closeSig;
sig.sa_flags = SA_SIGINFO;
sigemptyset(&sig.sa_mask);
sigaction(SIGINT, &sig, NULL);

这现在相当于第二个示例。

在询问之前是否搜索过?你有没有注意到你丢失了什么信息?你为什么不说你看过它?@JonathanLeffler是的,很抱歉这是一个打字错误。我已经搜索过了,但没有找到你的帖子,这篇帖子非常清楚sigaction()和signal()之间的区别。但仍有一种情况:使用sigaction与sigset+sig_解锁或不使用sigset之间的区别是什么/您在问题中显示,但在您的评论中提及及其相关内容(
sigrelse()
sigold()
sigpaise()
signore()
)。还有。通常不应使用
sigset()
系列-它们标记为“过时”,新代码不应使用它们。你真正感兴趣的是什么?我觉得从信号处理程序调用
exit()
不是个好主意。@JonathanLeffler我在大学学习,我被要求创建一个服务器/客户端并处理信号,以便于学习,这就是为什么我想了解第二个示例和第三个示例之间的区别。根据我将得到的结果,如果我使用第二个例子或第三个例子,结果将是一样的?谢谢你的耐心,现在事情变得更清楚了。现在,让我们假设我还要处理其他信号,比如sigalman。处理sigalarm后,它将重新启用“sigaction(sigalarm,&signAlarm,NULL);”,然后将控件返回到函数“fun()”。如果我们看第二个例子,使用sigset_t set,并将sigprocmask unblock放在fun()的开头,它是有意义的,因为这样可以再次处理所有信号,对吗?在这种情况下,sigset_t可以被认为是有用的,因为我可以向其中添加我想要的所有信号,并使用sigprocmask调用解除它们的阻塞,对吗?当我编写“it re enebles”时,我的意思是在处理程序中放入代码,然后是“fun();”。再次感谢!