FIFOはパイプと呼ばれていると聞きました。そして、それらはまったく同じセマンティクスを持っています。一方、Unixドメインソケットはパイプに非常に似ていると思います(ただし、これを使用したことはありません)。したがって、それらすべてがLinuxカーネルの同じ実装を参照しているのだろうか。何か案が?
UNIXドメインソケットとFIFOは、実装の一部を共有する場合がありますが、概念的には非常に異なります。FIFO非常に低レベルの関数です。1つのプロセスがバイトを書き込みますパイプとパイプからの読み取りUNIXドメインソケットの動作は、TCP/IPソケットと同じです。
ソケットは双方向であり、多くのプロセスで同時に使用できます。プロセスは同じソケットで多くの接続を受け入れ、同時に複数のクライアントに参加できます。カーネルは、ソケットでconnect(2)
またはaccept(2)
が呼び出されるたびに新しいファイル記述子を配信します。パケットは常に正しいプロセスに送られます。
FIFOでは、これは不可能です。双方向通信の場合、2つのFIFOが必要であり、クライアントごとに1組のFIFOが必要です。それらはコミュニケーションのはるかに原始的な方法であるため、選択的な方法で書き込みまたは読み取りする方法はありません。
匿名パイプとFIFOは非常によく似ています。違いは、匿名パイプはファイルシステム上のファイルとして存在しないため、プロセスがそれをopen(2)
できないことです。それらは、別の方法で共有するプロセスによって使用されます。プロセスがFIFOを開いてから、たとえばfork(2)
を実行すると、その子はファイル記述子を継承し、それらの間でパイプを継承します。
UNIXドメインソケット、匿名パイプ、およびFIFOは、共有メモリセグメントを使用するという点で似ています。実装の詳細はシステムによって異なる場合がありますが、考え方は常に同じです。 2つの異なるプロセスのメモリマッピングでメモリの同じ部分を接続して、データを共有させる
(編集: それはそれを実装する明白な方法の1つですが、それはLinuxで実際に行われる方法ではなく、単にバッファにカーネルメモリを使用するだけです。下記の@ tjb63による回答を参照してください)。
次に、カーネルはシステムコールを処理し、メカニズムを抽象化します。
これについてはかなり良い議論があります: 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_read
呼び出しpipe_iov_copy_to_user
は__copy_to_user_inatomic
(またはcopy_to_user
)を呼び出します。__copy_to_user_inatomic
はcopy_user_generic
を呼び出します。これはいくつかのASM実装の1つです。
"FIFO"と "named pipe"は同じものですが、シェルがコマンドラインの2つのコマンド間の "パイプ"(|)を処理する方法とはかなり異なります。
名前付きパイプ(FIFO)は、2つのプログラムによって共有される単一の「ファイル」であり、1つは書き込み、もう1つはファイルから読み取られます。一方、ソケットは2つの「ファイル」間の「接続」です。ネットワークを使用して、別々のコンピューター上にいる-1つのプログラムが1つの「ファイル」に読み取り/書き込みを行い、別のプログラムが別の「ファイル」に読み取り/書き込みを行う...それほど似ているとは思わない...一方、両方ソケットと名前付きパイプ(およびファイル、デバイス、シンボリックリンク)はすべてiノードを使用し、それらはすべていくつかの一般的な機能(読み取りや書き込みなど)を実装しています。
私の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はディスク上のファイルを使用し、Unixドメインソケットはカーネルメモリを使用すると思います。
また、Unixドメインソケットが双方向であることを述べた上記のポスターへの追加として、これはSOCK_STREAMソケットを使用する場合にのみ当てはまります。 SOCK_DGRAM Unixドメインソケットは、実際には単方向であり、connect()を呼び出したコードからbind()を呼び出したコードにのみsend()を送信できます。
もちろん、connect()を呼び出したコードは、独自のエンドポイントを作成するためにbind()も呼び出す必要がありますが、これは質問とは関係ありません。