15

私は出口で値を返さなければならない大学の演習を行っていましたが、その値は実際には何かのカウントでした。これは 255 を超える可能性があります (exit() では処理できません) が、教師は、カウントがその値を超えることのないテスト データを使用することを提案しました。

このすべての後、このカウント値、終了ステータスを処理する必要がありました。この値は、waitpid() を使用してメイン プロセスで取得しました。驚いたことに、子プロセスが 1 を返した場合、メイン プロセスの「実際の」値は 256、2 は 512 などでした...

この値を出力する必要があったので、単純に 256 で割りました。ただし、WEXITSTATUS() マクロを使用すると、この値も思い通りに取得できます...

Cソースコードを調べたところ、次のことがわかりました。

#define __WEXITSTATUS(status) (((status) & 0xff00) >> 8)

ここで何が起こっているか理解しています。たとえば、2 進数の 512 は 10 0000 0000 です。8 を右にシフトすると 00 0000 0010 になり、10 進数では 2 になります。このマクロで私が理解できないのは、& 演算子と、0xff00 が乱数のように見えるという事実です (おそらくそうではありませんが、どこから来たのでしょうか?)。これは正確には何をしますか?マクロに「& 0xff00」があるのはなぜですか? それがなければうまくいきませんか?

そして、このトピックの真の疑問は、コードでこのマクロを 256 で割ることと同じことを呼び出すことでしょうか?

4

4 に答える 4

23

そして、このトピックの本当の質問は、私のコードでこのマクロを 256 で割ることと同じことですか?

子プロセスが正常に終了する場合 (つまり、セグメンテーション違反やアサーションの失敗などではなく、exit() を呼び出すことによって) は、おそらく常に機能します。

によって保存されるステータスwaitpid()は、子プロセスが終了した理由と終了コードの両方をエンコードします。理由は最下位バイト ( によって取得status & 0xff) に格納され、終了コードは次のバイトに格納されます ( によってマスクstatus & 0xff00および抽出されWEXITSTATUS()ます)。プロセスが正常に終了した場合、理由は 0 であるためWEXITSTATUS、8 だけシフトする (または 256 で割る) ことと同じです。ただし、プロセスがシグナル (SIGSEGV など) によって強制終了された場合、終了コードはなくWTERMSIG、理由バイトからシグナル番号を抽出するために使用する必要があります。

于 2009-04-30T20:50:58.570 に答える
3

Single Unix Spec をチェックしてわかる限り、あなたのシステムはたまたま右端から 2 番目のオクテットに終了ステータスを保存していますが、標準ではそうではないと思います。したがって、少なくともいくつかの理由でマクロを使用する必要があります。

  • 彼らは正しいです。負の数をビットシフトすると、異なるプラットフォームで異なる処理が行われます。それはあなたが望むように機能しますか?知らない。
  • それらは単純です。何ができるかはすぐにわかりWEXITSTATUSます。他のアプローチではそうではありません。手巻きバージョンの を見たらWIFSIGNALED、それがわかりますか? よりもどれくらい時間がかかりますかWIFSIGNALED
  • ポータブルです。仕様でそれを行うように指示されているため、すべてのシステムで動作します (少なくともほとんどすべての Unix ライクなシステム)。
于 2012-02-03T22:45:25.757 に答える
3

「int」が 32 ビット量であるマシンでステータス変数が符号付き 16 ビット整数 (「short」) であり、終了ステータスが 128..255 の範囲にある場合、WEXITSTATUS() は引き続き256 で除算するか、単に右にシフトすると正しくない値が得られますが、正しい値が得られます。

これは、short が 32 ビットに符号拡張され、マスキングによって符号拡張が取り消され、結果に正しい (正の) 値が残るためです。

マシンが 16 ビット整数を使用している場合、WEXITSTATUS() のコードはおそらくシフトしてからマスクし、同様の動作を保証します。

#define WEXITSTATUS(status) (((status)>>8) & 0xFF)

WEXITSTATUS() マクロを使用する必要があるのは、実装がそのような詳細を処理するためです。

于 2009-05-01T01:06:33.290 に答える
2

ここで 0xff00 はバイナリ マスク (リンク テキスト) です。値との AND 演算により、2 番目のバイト (右から数えて) を除くすべてのビットがゼロに設定されます。

WEXITSTATUS正常に終了したことがわかっているプロセスでのみ使用してください。この情報は、WIFEXITEDマクロによって提供されます。

そして、このトピックの本当の質問は、私のコードでこのマクロを 256 で割ることと同じことですか?

このマクロにより、コードが読みやすくなり、Posix 準拠の実装で動作することが保証されます。私の知る限り、Posix はステータスの形式を指定していないため、コードがどこでも機能することは期待できません。

于 2009-04-30T19:29:36.907 に答える