2011年02月17日

exitと_exitの違い/tmpfileの削除のしくみ

Linuxでのプロセスの終了処理について少し調べました。

今まであまり意識していなかったexitと_exitの違いも理解できました。



昔C言語で小さなマイコンのプログラムをしていた頃は、一度main関数を実行すると、そこから抜けることはなかったので、main関数を抜けた後のことはあまり意識することはありませんでした。

しかし、Linuxなどプロセス単位で動かす場合には、main関数を抜けた後の終了処理も理解しておく必要があると思います。

main関数とexitの関係

main関数はスタートアップルーチンから呼び出されますが、mainから戻った後にmain関数の戻り値を引数としてexitが呼び出されます。

つまり、

    exit(main(argc, argv, env));

(ちなみに、mainという名前の関数はCコンパイラで特別扱いされていて、return文が無い場合にはコンパイラによって自動的に return 0; が付加されます。)

プログラムの中から直接exitを呼び出して終了させることもできます。

exitは呼び出したら、そこから戻ってくることはありません。

exitと_exitの関係

簡単に言うと、_exitはすぐにシステムコールを呼んでそのプロセスをその場で終了させます。exitはatexitで登録された関数を全て呼び出して、その後に_exitを呼び出します。

C++のグローバルクラスやスタティッククラスのデストラクタはexitの中で呼び出されます。

プログラムの中でexitで終了させているところを代わりに_exitを呼ぶとこれらの終了処理が実行されないことになります。

_exitの実際のソース

UbuntuのeglibcとAndroidのbionicのソースを調べたのですが、bionicの方がより単刀直入にシステムコールを呼び出していました。

_exit:
    .save   {r4, r7}
    stmfd   sp!, {r4, r7}
    ldr     r7, =__NR_exit_group
    swi     #0
    ldmfd   sp!, {r4, r7}
    movs    r0, r0
    bxpl    lr
    b       __set_syscall_errno
    .fnend

exitでなくexit_groupというシステムコールを呼び出しています。exit_groupはプロセスのThread groupの全てのスレッドを終了させます。カーネルのソースを見ると、do_group_exitは最後にdo_exitを呼んでいます。

ファイルのクローズはどこで行われる?

Linuxの場合はカーネルの中で行われます。

kernel/exit.c: close_file

そのプロセスで開いていたファイルが全てクローズされることは保証されています。

tmpfileの削除はどこで行われる?

exitをmanコマンドで調べると、標準ライブラリのtmpfile関数で作成したファイルは削除されると書いてあります。

しかし、標準ライブラリのtmpfileのソースを見ても終了時にそのファイルを削除するための関数をatexitで登録しているところが見当たりません。

さらにtmpfileのソースを調べてみると、ランダムなファイル名でファイルをopenしてfdを取得した後に、そのファイルをunlinkで削除していました。この場合、そのfdをcloseした時に実際にそのファイルが削除されます。前述の通り、プロセス終了時にはカーネルが必ずクローズしてくれるので、これをもってtmpfileは削除されるわけです。

unlinkを呼ぶにはファイル名が必要ですが、これだとファイル名をどこかに覚えておく必要もありません。うまくできていると思いました。



トラックバックURL

コメントする

名前
URL
 
  絵文字
 
 
記事検索
最新コメント
アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

QRコード
QRコード