FIFO、パイプ、UnixドメインソケットはLinuxカーネルでも同じですか?


30

FIFOは名前付きパイプだと聞きました。そして、それらはまったく同じセマンティクスを持っています。一方、Unixドメインソケットはパイプに非常に似ていると思います(使用したことはありませんが)。だから、彼らはすべてLinuxカーネルの同じ実装を参照しているのだろうか。何か案が?


以下の回答から、私の質問は曖昧なものであり、答えるのが難しいことに気付きました。(カーネル開発者でさえも)カーネルの実装に関する詳細をこれほど多く知ることはできないでしょう。Unixドメインソケット、パイプ、およびFIFOがすべてLinuxで共有メモリに送信されるデータをバッファリングすることを確認できれば、私の質問は解決します。まあ...部分的に解決しました。
ジャスティン

FIFO =名前付きパイプ!=パイプ。FIFOは、ソケットペアのように双方向にすることができます。通常のパイプは単方向です。すべてにファイルインターフェイスとファイルセマンティクスがあります。なぜ実装が重要なのですか?
PSkocik

パイプは循環バッファであり、STREAMSシステムではこれらが実装を共有できることを知っていますが、LinuxはデフォルトではSTREAMSを使用しません。LinuxはこれらのIPCチャネルをハードコードすると信じています。ただし、チェックする気はありません。:Dどうして?コードは公開されています。
PSkocik

それらがすべて同じ実装を共有する場合、それらの効率は互いに近いはずです。そして、私にとって、カーネルコードは理解するのが難しすぎます。
ジャスティン

回答:


35

UNIXドメインソケットとFIFOは実装の一部を共有する場合がありますが、概念的には非常に異なります。FIFOは非常に低いレベルで機能します。1つのプロセスがバイトをパイプに書き込み、別のプロセスがパイプから読み取ります。UNIXドメインソケットは、TCP / IPソケットと同じ動作をします。

ソケットは双方向であり、多くのプロセスで同時に使用できます。プロセスは、同じソケットで多くの接続を受け入れ、同時に複数のクライアントに参加できます。カーネルは毎回新しいファイル記述子を配信するconnect(2)accept(2)、ソケットで呼び出されます。パケットは常に正しいプロセスに送られます。
FIFOでは、これは不可能です。双方向通信の場合、2つのFIFOが必要であり、クライアントごとに1組のFIFOが必要です。選択的な方法で書き込みまたは読み取りを行う方法はありません。通信するためのはるかに原始的な方法だからです。

匿名パイプとFIFOは非常に似ています。違いは、匿名パイプがファイルシステム上にファイルとして存在しないため、プロセスで処理できないopen(2)ことです。別の方法で共有するプロセスで使用されます。プロセスがFIFOを開いてから、たとえばaを実行するとfork(2)、その子はファイル記述子と、その中でもパイプを継承します。

UNIXドメインソケット、匿名パイプ、およびFIFOは、共有メモリセグメントを使用するという点で類似しています。実装の詳細は、システムによって異なりかもしれませんが、アイデアは常に同じです:二つの異なるプロセスのメモリマッピングでメモリの同じ部分を添付して、彼らがデータを共有しているために
編集: 1つの明白な方法は、それを実装するだろうが、それはありますLinuxで実際に行われる方法ではなく、単純にバッファーにカーネルメモリを使用します。以下の@ tjb63による回答を参照してください)。
カーネルはシステムコールを処理し、メカニズムを抽象化します。


「UNIXドメインソケットとFIFOは実装の一部を共有する可能性があります」...ポイントは「一部」です...私の質問はちょっと曖昧で、答えるのが難しいことに気付きました。カーネル内でどの部分を共有しているかの詳細を誰も知ることができないでしょう(カーネル開発者でさえも)。それにもかかわらず...誰もがUnixドメインソケット、パイプ、およびFIFOがLinuxの下で共有メモリに送信されているデータをバッファリングすることを確認できますか?それが確認されれば、私の質問は解決されます。まあ...部分的に解決しました。
ジャスティン

ええ、はい、カーネルが管理するバッファーがあります。たとえば、FIFOを使用すると、yoouはライターを殺すことができ、リーダーはライターの死の前にパイプに送信されたものを引き続き使用できます。ソケットでは、接続されたプロトコルで機能するため、もう少し複雑です。しかし、たとえば、ソケットにintを送信し、スコープから外れてintが送信側スタックからクリアされる場合、受信側はそれを読み取ることができます。そのため、明らかにどこかにバッファがあります。
lgeorget

コメントを読み直して、ここで明確かどうかわからない...まだ不明な点があれば教えてください。
lgeorget

あなたのコメントは私には明らかです。
ジャスティン

7

これに関する非常に良い議論がここにあります:http : //www.slideshare.net/divyekapoor/linux-kernel-implementation-of-pipes-and-fifos

私が見る限り、プレゼンテーションスライドとソース@ http://lxr.free-electrons.com/source/fs/pipe.cの両方から-fifoはパイプのラッパーとして実装されており、パイプ自体はpipefs仮想ファイルシステムを介して実装されます。

@lgeorget-パイプはリーダーとライター間のバッファにカーネルメモリを使用しているように見えます-それらは「共有メモリ」を使用せず、ユーザーとカーネルアドレススペース間でメモリをコピーします(たとえば、pipe_readcalls pipe_iov_copy_to_user、which __copy_to_user_inatomic(またはcopy_to_user)) 。__copy_to_user_inatomic呼び出しcopy_user_generic、これはいくつかのASM実装の1つです。


4

「FIFO」と「名前付きパイプ」は同じものです。ただし、シェルがコマンドラインの2つのコマンド間の「パイプ」(|)を処理する方法とはまったく異なります。

名前付きパイプ(FIFO)は、2つのプログラムによって共有される単一の「ファイル」です。1つは書き込みを行い、もう1つは読み取りを行います...一方、ソケットは2つの「ファイル」間の「接続」です。ネットワークを使用し、別のコンピューター上にある-1つのプログラムが1つの「ファイル」に対して読み取り/書き込みを行い、別のプログラムがもう1つのファイルに対して読み取り/書き込みを行う...似ているとは思わない...一方では両方ソケットと名前付きパイプ-ファイル、デバイス、シンボリックリンク-はすべてiノードを使用し、それらはすべていくつかの一般的な機能(読み取りや書き込みなど)を実装します。


1
はい、Unixドメインソケットは一種のソケットであるため、APIはTCPやUDPなどの他のソケットAPIと類似しています。ただし、Unixドメインソケットは「ローカル」IPCとしてのみ使用できます。そして、データを転送する方法は、先入れ先出し法であり、FIFOとパイプによく似ています。したがって、UnixドメインソケットのAPIは、同一の実装の単なる別のカプセル化である可能性があるため、ソケットであるかのように使用します。カーネル内のすべてが同じ内部を共有している可能性があると思います...それが本当かどうかを確認したいと思います。
ジャスティン

1

私はそうは思いませんジャスティン。間違っていないなら、おそらくそうかもしれませんが、FIFOはディスク上のファイルを使用し、Unixドメインソケットはカーネルメモリを使用すると思います。

また、Unixドメインソケットは双方向であると述べた上記のポスターへの追加として、SOCK_STREAMソケットを使用する場合にのみそうです。SOCK_DGRAM Unixドメインソケットは、実際には単方向であり、connect()を呼び出したコードからbind()を呼び出したコードにのみsend()できます。

もちろん、connect()を呼び出したコードはbind()を呼び出して独自のエンドポイントを作成する必要がありますが、それは質問とは関係ありません。


3
StackExchangeへようこそ。投稿していただきありがとうございます。いくつかの発言... 1)「かなりの可能性がある」と間違えた場合は、回答する前に再確認する必要があります。このサイトはフォーラムでもチャットでもありません。2)データグラム指向のソケットの精度に感謝します3)質問に「何もしない」ものを投稿する必要はありません。:)
lgeorget

1

私の2セント... FIFOとUNIXソケットはどちらも双方向(類似)ですが、ソケットはスタートポロジを持ち、FIFOは単なるキューです(したがって互いに交換することはできません)、それらの実装は内部でコードを共有できます。

**

char * myfifo = "/tmp/myfifo";
mkfifo(myfifo, 0666);
fd = open(myfifo, O_RDWR);   //so that you can read/write to it
 ...
write(fd, buff1, sizeof(buff1));  
getchar();//wait till some one reds this and writes something else
int sz=read(fd, buff1, sizeof(buff1));  //read that something**

FIFOは双方向ですか?
jhfrontz
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.