使用信号处理程序处理从fifo接收的数据

时间:2017-07-27 12:48:50

标签: c++ linux qt asynchronous signals

我正在用fifo编写一个简单的客户端/服务器通信,但我仍然坚持使用信号处理程序来处理客户端请求。

服务器以只读和非阻塞模式打开fifo,读取接收的数据并将一些数据写回客户端fifo。

当服务器端没有信号处理程序时,这实际上工作正常。这是双方的主要代码。

服务器:

int main(int argc, char *argv[])
{
    // install handler
    struct sigaction action;

    action.sa_handler = requestHandler;

    sigemptyset(&(action.sa_mask));

    action.sa_flags = SA_RESETHAND | SA_RESTART;

    sigaction(SIGIO, &action, NULL);

    if(!makeFifo(FIFO_READ, 0644))
        exit(1);

    int rd_fifo = openFifo(FIFO_READ, O_RDONLY | O_NONBLOCK); // non blocking

    if(rd_fifo == -1)
        exit(1);

    // wait for request and answer
    while (1) {
        qWarning() << "waiting client...";
        sleep(1);
        QString msg = readFifo(rd_fifo);

        qWarning() << "msg = " << msg;

        if(msg == "ReqMode") {
            int wr_fifo = openFifo(FIFO_WRITE, O_WRONLY); // blocking
            writeFifo(wr_fifo, QString("mode"));
            break;
        } else
            qWarning() << "unknow request ..";
    }

    close(rd_fifo);
    unlink(FIFO_READ);

    return 0;
}

客户:

int main(int argc, char *argv[])
{
    int wr_fifo = openFifo(FIFO_WRITE, O_WRONLY);

    if(wr_fifo == -1)
        exit(1);

    // create a fifo to read server answer
    if(!makeFifo(FIFO_READ, 0644))
        exit(1);

    // ask the server his mode
    writeFifo(wr_fifo, QString("ReqMode"));

    // read his answer and print it
    int rd_fifo = openFifo(FIFO_READ, O_RDONLY); // blocking
    qWarning() << "server is in mode : " << readFifo(rd_fifo);

    close(rd_fifo);
    unlink(FIFO_READ);

    return 0;
}

一切都按预期工作(即使没有正确处理所有错误,这只是一个示例代码,以证明这是可能的。)

问题在于,当客户端将数据写入fifo时,处理程序(此处未显示,但只在终端上打印带有接收信号的消息)从不被调用。此外,我已经检查过,如果我从bash(或其他地方)向服务器发送kill -SIGIO,则执行信号处理程序。

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

实际上,我错过了服务器端的以下3行:

fcntl(rd_fifo, F_SETOWN, getpid()); // set PID of the receiving process

 fcntl(rd_fifo, F_SETFL, fcntl(rd_fifo, F_GETFL) | O_ASYNC); // enable asynchronous beahviour

 fcntl(rd_fifo, F_SETSIG, SIGIO); // set the signal that is sent when the kernel tell us that there is a read/write on the fifo.

最后一点很重要,因为在我的情况下发送的默认信号是0,所以我必须将它明确地设置为SIGIO以使事情有效。这是服务器端的输出:

waiting client... 
nb_read =  0 
msg =  "" 
unknow request .. 
waiting client... 
signal  29 
SIGPOLL 
nb_read =  7 
msg =  "ReqMode" 

现在,我想通过将while循环中的内容移动到requestHandler函数中来处理处理程序内的请求是可能的。