私はfork()のマニュアルページを読んで、「呼び出しプロセスで開かれているすべてのファイル記述子がコピーされました」のようなものです。
呼び出しプロセスがその時点で実行している実行可能バイナリのファイル記述子がそのステートメントに含まれているかどうかは100%明確ではありません。マニュアルページに「すべてのファイル記述子」と記載されていますが、open()
これを使用して2つのプロセスを同期するよりも、分岐されたプロセスに同じ実行可能バイナリを使用する方が簡単に見えるので、これを尋ねます。それでは、実際にもコピーされるとしたらなぜでしょうか?
答え1
実行中のバイナリにはファイル記述子がなく、メモリマップのみがあります。
ls -l /proc/self/fd
(たとえば、Linuxの場合を参照してくださいcat /proc/self/maps
。)
もちろん、メモリマップは同じファイルを指しますが、共有ライブラリでも同じです。デフォルトのプログラムファイルの場合、実行中のプロセスで使用されている間、Linuxでは書き込みは許可されません。 (過去に確認しましたが、共有ライブラリでは機能しません。)
答え2
実際に何をしたいのかはわかりませんが、Linux(および他のシステム)では、open("/proc/self/exe", ...)
ファイルが削除された場合やファイルシステムにまったく存在しない場合でも機能します。
/dev/tty
(常に呼び出しプロセスのコントロールttyが開かれる場合)と同様に、/proc/self/exe
呼び出しプロセスで現在実行中のファイルが常に開きます。どちらも、プロセスが参照した開いたファイルの説明を隠す「ステートメント」として機能し、通常のファイルのようにアクセスできるようにします。
これは、プロセスが持つ唯一の「隠し」/潜在的なファイル記述子ではありません。具体的には、次のようにファイルのメモリマップを作成できます。mmap(..., fd, ...)
閉じてもfd
マップは削除されず、プロセスはファイル記述子としてファイルへの参照を保持し続けます(Linuxではファイル記述子を開いて再送信できます/proc/self/map_files/<range>
)。
別の例には、ルートディレクトリと現在の作業ディレクトリ(/proc/self/{cwd,root}
)があります。ただし、開いているfdsを介して参照されるディレクトリでも、他のディレクトリと同様に、その意味は通常のファイルの意味とは異なります。特に、ディレクトリから生成ファイルを削除することはできません。ディレクトリにある場合は、まだ開いているファイル記述子を介して削除されたファイルにデータを書き込むことができます。