ポートを読んでいる間、猫はどのように一時停止しますか?

ポートを読んでいる間、猫はどのように一時停止しますか?

catテキストファイルの内容を調整すると、すべての内容が印刷され、コマンドが終了します。ただし、これを行うcat /dev/ttyS0と、コマンドが中断され、新しいデータが到着するのを待ちます。

このように一時停止するのはなぜですか?

答え1

cat端末での実験

catより多くのデータを待つ理由は次のとおりです。クエンムと言う。入力が端末になるように入力してcat押しても同じことが発生します。Enter端末で動作を簡単に試すことができますcat。まず、実行方法は次のとおりです。

端末にCtrl+を入力すると、D端末はリテラルCtrl+D文字をプログラムに送信しません。これを行うには、Ctrl+を入力してV次の制御文字を文字通り処理する必要があることを端末に通知し、Ctrl+を入力する必要がありますD。代わりに:

  • 入力バッファにテキストがある場合(つまり、まだプログラムに送信されていないテキストを入力した場合)、バッファはフラッシュされます。これは、そのテキストがプログラムに送信されたことを意味します。プログラムは、次回を読むとそれを受け取ります。
  • 入力バッファにテキストがない場合、端末はプログラムへの入力の終わりを示し、その結果、プログラムは次の読み取り操作でファイル終了条件に直面します。これは実際には(下記参照)です。現在のこの場合、読み取り操作はすでにcat読み取り中であるためです。

Enter指示を除外する改行文字返品Ctrl+を押さなくてもバッファはフラッシュされますD。したがって、あなたは以下を観察するでしょう:

  • テキストを入力してEnterまたはCtrl+を押すと、同じテキストが端末に書き込まれDます。をcat使用すると、Enter改行 cat文字も作成されます。

  • Enter行の先頭で押すかCtrl+を押して、D改行文字を送ってcat 書き込みます。

  • 行の先頭で+を押すかCtrl+を押して(つまり、2回連続して)入力を終了します。DCtrlD

    cat最後の入力ソースから読み取ることがないことを確認すると(「cat」は「catenate」または「concatenate」を意味し、これは複数のファイル名引数を受け取ったときに機能する方法です)終了します。

制御端末からの読み込みが完了するまで入力を待つのと同様にcat、読み込みを指示すると、他のファイルやデバイス(シリアル端末を含む)からの追加入力を待ちます。

CtrlD+と関連する特別な動作により、Enter入力がに送信されますcatあなたの端末、代わりにcat。特に、catそれ自体は改行文字を特に扱いません。

待機プロセスの状態

cat入力を待っている間は、他の端末でステータスを確認してください。

ほとんどのUnixファミリーオペレーティングシステムでは、またはpidof catを実行して実行中のすべてのcatプロセスのプロセスIDを見つけることができますpgrep -x cat。少なくとも一つ一般的にサポートされています。または、実行中の同じ端末で+を押して一時Ctrl停止します。Zcat実際にプロセスを一時停止してから実行してpsPIDを見つけ、それを実行して再起動しますfg。または、tty最初の端末で実行して端末装置のパス名を表示します。 GNU/Linux では次のようになります。/dev/tty2または/dev/pts/4--then run cat、 2番目の端末で実行、交換ps -t ttyttytty最初の端末の出力です。

2番目の端末で交換した場所を実行してください。ps pidpidcatプロセスの実際のプロセスIDを使用します。ステータスを表示する列を含むプロセスが一覧表示されます。 (上記のコードを実行しても、tty -t以前にステータス列が含まれていなかったGNU / Linuxを含む一部のシステムではこれが必要です。)

たとえば、GNU/Linux システムでは、次のようにします。

ek@Io:~$ ps 30196
  PID TTY      STAT   TIME COMMAND
30196 pts/4    S+     0:00 cat

あなたの外観は異なって見えるかもしれません。 STATまたはS列の下に表示されるプロセスステータスコードを実行して検索することをお勧めしますman ps。これらのコードはシステムごとに少し異なります。その GNU/Linux システムでは参考(1)表示プロセスの状態は次のように報告されました。

               S    interruptible sleep (waiting for an event to complete)

               +    is in the foreground process group

そのGNU / Linuxシステムで上記のように+をcat使用して実行し、一時停止するとCtrl次のように変更されます。ZS+T

               T    stopped by job control signal

睡眠は邪魔になる可能性があるためノンストップ睡眠?例:

               D    uninterruptible sleep (usually IO)

これは通常、プロセスがカーネルがキャンセルを許可しないIO操作を実行したときに発生します。中断せずに省電力状態のプロセスは終了できません。またはを使用すると、ジョブが完了するとTERMまたはKILL信号をそれぞれ受信します。kill pidkill -9 pid

追跡プロセス

gdb通常、プログラムをデバッグするには、またはなどのデバッガでプログラムを開きますlldb。ただし、GNU/Linux を含む一部のシステムには、strace次のプログラムがあります。システムコールプロセスが進行中です。端末で入力を待つプロセスを実行するには、端末のプロセスにさらに入力が送信されるまで実行をブロックするstrace各呼び出しを表示できます。readFedora、CentOS、Debian、UbuntuなどのGNU / Linuxシステムがある場合(これらは例にすぎず、他のシステムもたくさんあります)、次のコマンドを実行してみてください。

strace cat

一連のシステムコールを表示できます。まず、プロセスを実行する呼び出し(execveプログラムが共有ライブラリを使用している場合は、ファイル名に関連するさまざまな呼び出しが続きます。これはほぼ確実です)とほとんどのプログラムで実行される呼び出しです。そして...をld.so含むCライブラリ関数が機能するようにし、最終的には読みます。mmapbrk標準入力:

read(0,

これは構文ですstrace。プロセスcatは次のとおりです。いいえ文字通りパラメータを渡す過程でread(構文は以前に使用していなかったCプログラマと似ているように見えるかもしれないのでstrace)。代わりにreadシステムコールを実行します。まだ返されていません。。データが読み込まれたか、入力の終わりに達すると返されます。

たとえば、と入力してfooを押しますEnter。これにより、次の内容が表示されます。

"foo\n", 131072)                = 4
write(1, "foo\n", 4foo
)                    = 4
read(0,

それはどういう意味ですか?終了しcatCtrl行の先頭に+追加または任意の場所に+追加)、リダイレクトして出力を抑制しながら再実行すると、見やすくなります。DCtrlC/dev/null

strace cat >/dev/null

strace作成したとおりに出力を表示できます。標準エラーそしてあなたはリダイレクトだけしました。標準出力。ただし、現在のcat出力fooとユーザーが提供した改行文字は表示されません。入力して押したfoo後に表示される内容はEnter次のとおりです。

"foo\n", 131072)                = 4
write(1, "foo\n", 4)                    = 4
read(0,

つまり、read呼び出しが完了して読み取りfooの後に表示される改行文字が続きます\ncatその後、呼び出しはwrite同じ文字列を出力に書き込みます。 Cコードには呼び出しがない可能性がありますcatwrite代わりに、Cライブラリ関数(またはfprintf )を使用して書き込みを実行できます。これはシステムコールではなく、最終的にシステムコールを使用して機能するため、fputs出力には表示されません。が渡され、カーネルに4バイトを書く必要があることを伝えます。stracewrite4writef o o \n

入力を読み続けるには、thisを呼び出してからwriteもう一度cat呼び出します。read引き続き入力を与え、callを確認してwriteからread再度呼び出すことができます。たとえば、次のように入力してタップしabracadabraますEnter

"abracadabra\n", 131072)        = 12
write(1, "abracadabra\n", 12)           = 12
read(0,

完了したら、最後の項目を入力してEnter(または+)を押し、次にCtrl+を押します。入力が終了すると終了し、以下が表示されます。DCtrlDcatstrace

read(0, "", 131072)                     = 0
munmap(0x7f856a591000, 139264)          = 0
close(0)                                = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

関連情報