【问题标题】:Using a signal handler to process datas received from a fifo使用信号处理程序处理从 fifo 接收的数据
【发布时间】:2017-07-27 12:48:49
【问题描述】:

我正在编写一个与 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,则信号处理程序会被执行。

感谢您的帮助。

【问题讨论】:

    标签: c++ linux qt asynchronous signals


    【解决方案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 函数来处理处理程序内的请求。

    【讨论】:

    • 你是怎么找到这个答案的?手册页说 SIGIO 是默认生成的。
    • 已经有一段时间了,但我在反复试验后发现了这一点。 SIGIO 不是默认生成的,我没有进一步调查。它是一个旧的嵌入式 Linux 内核(3.10 或 3.14 记不清了)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-08
    相关资源
    最近更新 更多