ファイルディスクリプタとは

ファイル記述子は、コンピュータのオペレーティングシステムで開いているファイルを一意に識別する番号です。 データリソース、およびそのリソースへのアクセス方法について説明します。

プログラムがファイル(またはネットワークソケットなどの別のデータリソース)を開くように要求すると、オペレーティングシステムのカーネルがアクセスを許可し、グローバルファイルテーブルにエントリを作成し、そのエントリの場所をソフトウェアに提供します。

記述子は、 0、12 、または567などの固有の負でない整数によって識別されます。 システム上のオープンファイルごとに少なくとも1つのファイル記述子が存在します。

ファイル記述子はUnixで最初に使用され、そしてLinux、macOS X、およびBSDを含む最新のオペレーティングシステムによって使用されます。 Microsoft Windowsでは、ファイル記述子はファイルハンドルとして知られています。

  • 概要
  • 標準入力、標準出力、および標準エラー出力
  • ファイル記述子のリダイレクト

プロセスがファイルを開く要求に成功すると、カーネルはカーネルのグローバルファイルテーブル内のエントリを指すファイル記述子を返します 。 ファイルテーブルエントリには、ファイルのiノード、バイトオフセット、およびそのデータストリームのアクセス制限(読み取り専用、書き込み専用など)などの情報が含まれています。

標準入力、標準出力、および標準エラー出力

Unixライクなオペレーティングシステムでは、デフォルトで最初の3つのファイル記述子はSTDIN (標準入力)、 STDOUT (標準出力)、およびSTDERR (標準エラー)です。

ファイル記述子説明略語
標準入力0コマンドパイプラインなどでの入力用のデフォルトのデータストリーム。 端末では、これはデフォルトでユーザーからのキーボード入力になります。標準入力
標準出力1コマンドがテキストを印刷するときなどに、出力用のデフォルトのデータストリーム。 端末では、これはデフォルトでユーザーの画面になります。標準出力
標準誤差2発生しているエラーに関連する出力用のデフォルトのデータ・ストリーム。 端末では、これはデフォルトでユーザーの画面になります。stderr

ファイル記述子のリダイレクト

ファイル記述子は、 bash 、Linuxのデフォルトシェル、macOS X、およびLinux for Windows Subsystemを使用して直接アクセスできます。

たとえば、 findコマンドを使用すると、正常な出力はstdout (ファイル記述子1 )に送信され、エラーメッセージはstderr (ファイル記述子2 )に送信されます。 両方のストリームは端末出力として表示されます。

 検索/名前 '*何か*' 
 / usr / share / doc / something / usr / share / doc / something / examples / something_random find: `/ run / udisks2 ':許可されていませんfind:` / run / wpa_supplicant':許可されていない/ usr / share / something / usr /ゲーム/何か 

findが読み取り権限のないいくつかのシステムディレクトリを検索しようとしているため、エラーが発生しています。 "Permission denied"と書かれている行はすべて標準エラー出力に書き込まれ、他の行は標準出力に書き込まれます。

ファイルディスクリプタ2を/ dev / nullにリダイレクトすることでstderrを隠すことができます 。これはLinuxの特殊なデバイスで "どこにも行かない"ためのものです。

 find / -name '* something *' 2> / dev / null 
 / usr / share / doc / something / usr / share / doc / something / examples / something_random / usr / share / something / usr / games / something 

エラーは/ dev / nullに送信され、表示されません。

プログラムの出力を処理したい場合は、 stdoutstderrの違いを理解することが重要です。 たとえば、 findコマンドの出力をgrepしようとすると、標準出力だけがgrepにパイプされるため、エラーメッセージはフィルタされません。

 find / -name '* something *' | grep 'something' 
 / usr / share / doc / something / usr / share / doc / something / examples / something_random find: `/ run / udisks2 ':許可されていませんfind:` / run / wpa_supplicant':許可されていない/ usr / share / something / usr /ゲーム/何か 

しかし、標準エラーを標準出力にリダイレクトすれば、 grepは両方のテキストを処理します。

 検索/名前 '*何か*' 2>&1 | grep 'something' 
 / usr / share / doc / something / usr / share / doc / something / examples / something_random / usr / share / something / usr / games / something 

上記のコマンドでは、ターゲットファイル記述子( 1 )の前にアンパサンド( " ")が付いています。 データストリームのリダイレクトの詳細については、bashシェルのパイプラインを参照してください。

bashでファイル記述子を作成および使用する例については、exec組み込みコマンドの例を参照してください。

ファイルハンドル、オペレーティングシステムの用語