私はfifoとの単純なクライアント/サーバ通信を作成していますが、シグナルハンドラを使用してクライアント要求を処理しています。シグナルハンドラを使用して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
を送信すると、シグナルハンドラが実行されることを確認しています。
ありがとうございました。デフォルトの信号が私の場合は0だっ送られ、そう私はSIGIOに明示的に設定する必要がありましたので、最後の点が重要だった
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.
: