【发布时间】:2017-06-14 11:29:53
【问题描述】:
我发现 GNU 库中记录了 SIGIO 信号。据说只要我有输入(特别是在套接字中),系统就有可能发送信号。 根据创建此类信号的文档,我应该将 O_ASYNC 标志设置为相应的文件描述符。 我的问题是我的 GNU 版本(gcc 6.3.0)无法识别这样的关键字:
错误:'O_ASYNC' 未声明(在此函数中首次使用)
我使用以下块设置标志:
/* Set socket status async */
int status = fcntl(sockfd, F_SETFL, O_ASYNC);;
if (status < 0) error("Can't set async mode");
else printf("Async is set for signal %d\n", SIGIO);
我使用 Cigwin GCC 6.3.0
代码如下:
static void OnTimer(int sig)
{
/* write request to socket BIO */
}
static void OnTick(int sig)
{
char read[BUFSIZE] = {};
int received;
received = SSL_read(ssl, read, sizeof(read));
/* Handle errors here */
/* print the server's reply */
printf("%s\n\n", read);
}
void connectSSL()
{
/* do all socket set-up and connection */
/* Establish handler for I/O signal */
saction.sa_flags = 0;
saction.sa_handler = OnTick;
sigemptyset(&saction.sa_mask);
sigaddset(&saction.sa_mask, SIGALRM);
if (sigaction(SIGIO, &saction, NULL) == -1) error("sigaction");
else printf("OnTick handler created\n");
/* Set socket status async */
int status = fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL, 0) | FASYNC);
if (status < 0) error("Can't set async mode");
else printf("Async is set for signal %d\n", SIGIO);
/* Select the process to receive the signal */
int process = fcntl(sockfd, F_SETOWN, getpid());
if (process < 0) error("Can't set address process");
else printf("Process %d is set\n", getpid());
/* do the rest SSL staff here */
}
int main(int argc, char argv[])
{
sigset_t mask, oldmask;
/* Wait for OnTimer event*/
sigemptyset(&oldmask);
sigaddset(&oldmask, SIGALRM);
sigemptyset(&mask);
sigaddset(&mask, SIGALRM);
sigaddset(&mask, SIGIO);
sigprocmask(SIG_BLOCK, &mask, &oldmask);
connectSSL();
createTimer(500000000);
while(1)
{
printf("\nWaiting OnTimer %d\n", count + 1);
sigsuspend(&oldmask);
}
return 0;
}
【问题讨论】:
-
除了我在下面的实际答案之外:根据我的经验,信号控制 I/O 带来的问题比它实际解决的问题要多。一旦您通过信号处理程序了解了您可能实际做什么(为您的操作系统查找“异步安全功能”),您可能希望将您的设计恢复为
select之类的东西。 -
也许你是对的。我还是想试试。目前我根本无法设置此信号。
-
我对 select 不完全满意的一个原因是 select 在 socket 中有真正的输入消息之前被调用了 4 次。我想 select 会不断轮询所有 I/O 描述符,并在所有其他 fd 准备好时恢复 1。我需要更快的解决方案。