Linuxで誰かがPty(擬似末端)の奴隷側を開いたときにどのように検出できますか?
-
28-09-2019 - |
質問
シリアルデバイス(/dev/ttyxx)から複数のプロセスを読み取ることで、両方のプロセスがすべてのデータを取得できないようにするため、データは何らかの方法でそれらの間で分割されます。シリアルデバイスから読み取り、いくつかのマスター/スレーブPTYペアを作成し、シリアルデバイスから読み取られたプログラムがPTYSから読み取り、すべての読み取りプロセスがデータを受信できるようにするプログラムを作成したいと思います。シリアルデバイスから、PtysがPTYから読み始めたときに最新のデータのみを取得するという意味で、Ptysにシリアルデバイスのように動作させます。言い換えれば、読み始める前に書かれたデータを取得することはできません(これが /dev /ttyxxデバイスの動作、または少なくとも私が読んでいるRS-232アンモメーターであるというのは私の経験です)。名前のパイプは、Sigpipeをトラップして読者がいないことを判断することでこれらのセマンティクスを模倣でき、したがって、その特定の名前のパイプに書き込まないことを選択できます。ただし、ターミナルを使用するために書かれた一部のバイナリは、名前が付けられたパイプと話すときに失敗する可能性があります。これは、tcsetattr()のような呼び出しのerrno条件のチェックが故障状態を引き起こす可能性があるためです。ここで重要なのは、端末用に書かれた既存のバイナリを使用できることです。
したがって、Ptyの奴隷側が読書のために開かれた時期を検出できる場合、名前付きパイプケースにSigpipeがないのとほぼ同じセマンティクスが得られるはずです。 HP-uxには、私が望むことを正確に行うように見えるIOCTL()コマンドとしてTIOCTRAPがあることに気づきましたが、残念ながらLinuxでは使用できません。
私は何日も参照を読んできましたが、このタイプのもののオプションの数は驚異的です。答えは、端末設定、ブロッキング/非ブロッキング動作、どこかでバッファサイズの設定、Poll()/Select()から報告された条件、または組み合わせにある場合があります。しかし、私は何も見つからないようです。私は自分のデバイスドライバーを書く必要がある可能性があるのだろうかと思っていますが、そこまで行かなくこれを行うことができるはずです。
だから、説明のために:
- 問題は、Linuxで誰かがPty(擬似末端)の奴隷側を開いたときにどのように検出できますか?
- 読者がPTYの奴隷側を開くと、読者がPTYを開いた後に厳密に記述されたデータを受信するために読者が望んでいます(私のマルチライティングプロセスが読者が奴隷側を開く前にしばらくデータを書き込んだ場合、データはバッファーし、データがバッファーします最終的に作家はブロックされ、奴隷の読者は開いたときにすべてのバッファーデータを取得します - これは、すぐに時間的付近で生成されたデータのみを取得したいので望ましくありません)
- それ しなければならない 既存のバイナリが機能するように、ISATTY()およびTCSETATTR()などとして、名前付きパイプ、ソケットなどではなく、名前が付けられたパイプ、ソケットなどではありません。
解決
これを見つけることができない理由は、それを許可するために特別に文書化されたインターフェイスがないためです。ただし、それを可能にするトリックがあります。擬似末端マスターを開いた後(ここではファイル記述子であると想定されています ptm
)、あなたは奴隷側を開いてすぐに閉じます:
close(open(ptsname(ptm), O_RDWR | O_NOCTTY));
これにより、TTYマスターにHUPフラグが設定されます。あなたは今、HUPフラグを定期的に投票します poll()
(たとえば、データソースからデータが入るたびに):
struct pollfd pfd = { .fd = ptm, .events = POLLHUP };
poll(&pfd, 1, 10 /* or other small timeout */);
if (!(pfd.revents & POLLHUP))
{
/* There is now a reader on the slave side */
}
読者が消えた場合、 POLLHUP
再び設定されます。
あなたの場合、あなたはおそらく、あるループから次のループまで覚えておく必要さえありません。 read()
データソースでは、データが利用可能な場合、同時に poll()
すべてのマスターTTYSとデータを持っていないそれらのいずれかに送信します POLLHUP
セットする。
他のヒント
奴隷PtyにInotify Watchを追加し、それについて投票してください。 OpenでInoTifyイベントを取得できます。その後、Inotifyファイル記述子とMaster PTYファイル記述子でポーリングできます。 Open(IN_OPEN)のためにInoTifyイベントを取得できます。これにより、奴隷側が開かれたときに投票が解除されます。