Apakah FIFO, pipe & Unix domain socket hal yang sama di kernel Linux?

30

Saya mendengar bahwa FIFO dinamai pipa. Dan mereka memiliki semantik yang persis sama. Di sisi lain, saya pikir soket domain Unix sangat mirip dengan pipa (walaupun saya tidak pernah memanfaatkannya). Jadi saya bertanya-tanya apakah mereka semua merujuk pada implementasi yang sama di kernel Linux. Ada ide?

Justin
sumber
Dari jawaban di bawah saya menyadari pertanyaan saya agak ambigu dan sulit dijawab. Kemungkinan tidak ada yang bisa mengetahui begitu banyak detail dari hal-hal implementasi dalam kernel (bahkan untuk pengembang kernel). Jika seseorang dapat mengkonfirmasi bahwa soket domain Unix, pipa dan FIFO mereka semua buffer data yang dikirim dalam memori bersama di Linux, pertanyaan saya terpecahkan. Yah ... sebagian terpecahkan.
Justin
FIFO = pipa bernama! = Pipa. FIFO dapat dua arah seperti sepasang soket. Pipa biasa adalah searah. Semua memiliki antarmuka file dan semantik file. Mengapa implementasi penting bagi Anda?
PSkocik
Saya tahu pipa adalah buffer bundar, dan bahwa dengan sistem STREAMS, ini dapat berbagi implementasi, namun Linux tidak menggunakan STREAMS secara default. Saya percaya Linux menyandikan saluran-saluran IPC ini. Tapi aku tidak ingin memeriksanya. : D Kenapa tidak? Kode tersedia untuk umum.
PSkocik
Jika mereka semua berbagi implementasi yang sama, efisiensinya harus dekat satu sama lain. Dan, bagi saya, kode kernel terlalu sulit untuk dipahami.
Justin

Jawaban:

35

Soket domain UNIX dan FIFO dapat berbagi sebagian dari implementasinya tetapi secara konsep mereka sangat berbeda. FIFO berfungsi pada level yang sangat rendah. Satu proses menulis byte ke dalam pipa dan yang lain membaca dari itu. Soket domain UNIX memiliki perilaku yang sama dengan soket TCP / IP.

Soket adalah dua arah dan dapat digunakan oleh banyak proses secara bersamaan. Suatu proses dapat menerima banyak koneksi pada soket yang sama dan menghadiri beberapa klien secara bersamaan. Kernel mengirimkan deskriptor file baru setiap kali connect(2)atau accept(2)dipanggil pada socket. Paket akan selalu menuju ke proses yang benar.
Pada FIFO, ini tidak mungkin. Untuk komunikasi dua arah, Anda memerlukan dua FIFO, dan Anda membutuhkan sepasang FIFO untuk masing-masing klien Anda. Tidak ada cara menulis atau membaca secara selektif, karena mereka jauh lebih primitif untuk berkomunikasi.

Pipa anonim dan FIFO sangat mirip. Perbedaannya adalah bahwa pipa anonim tidak ada sebagai file pada sistem file sehingga tidak ada proses yang bisa open(2). Mereka digunakan oleh proses yang membagikannya dengan metode lain. Jika suatu proses membuka FIFO dan kemudian melakukan, misalnya, a fork(2), anaknya akan mewarisi deskriptor file dan, di antaranya, pipa.

Soket domain UNIX, pipa anonim dan FIFO serupa dalam kenyataan mereka menggunakan segmen memori bersama. Detail implementasi dapat bervariasi dari satu sistem ke sistem lain tetapi idenya selalu sama: lampirkan bagian memori yang sama dalam dua proses pemetaan memori yang berbeda untuk meminta mereka berbagi data
( edit: itu akan menjadi satu cara yang jelas untuk mengimplementasikannya tetapi itu adalah bukan bagaimana ini sebenarnya dilakukan di Linux, yang hanya menggunakan memori kernel untuk buffer, lihat jawabannya oleh @ tjb63 di bawah).
Kernel kemudian menangani pemanggilan sistem dan mengabstraksi mekanisme tersebut.

lororget
sumber
"Soket domain UNIX dan FIFO dapat berbagi sebagian dari implementasi mereka" ... intinya adalah "sebagian dari" ... Saya baru menyadari pertanyaan saya agak ambigu dan sulit dijawab. Kemungkinan tidak ada yang bisa mengetahui begitu banyak detail bagian apa yang mereka bagikan di kernel (bahkan untuk pengembang kernel). Namun demikian ... adakah yang bisa mengkonfirmasi bahwa soket domain Unix, pipa dan FIFO mereka semua buffer data yang dikirim dalam memori bersama di Linux? Jika sudah dikonfirmasi, pertanyaan saya terpecahkan. Yah ... sebagian terpecahkan.
Justin
Ya, ada buffer yang dikelola oleh kernel. Misalnya, dengan FIFO, Anda dapat membunuh penulis dan pembaca masih dapat mengirim apa yang dikirim ke pipa sebelum kematian penulis. Dengan soket, ini sedikit lebih rumit karena berfungsi dengan protokol yang terhubung. Tetapi jika Anda mengirim, katakanlah, int ke soket, dan kemudian keluar dari ruang lingkup sehingga int dihapus dari tumpukan pengirim, penerima masih bisa membacanya. Jadi, jelas ada buffer di suatu tempat.
lgeorget
Membaca ulang komentar, tidak yakin saya jelas di sini ... Beri tahu saya jika masih ada sesuatu yang tidak jelas.
lgeorget
Komentar Anda jelas bagi saya.
Justin
7

Ada diskusi yang cukup baik tentang ini di sini: http://www.slideshare.net/divyekapoor/linux-kernel-implementation-of-pipes-and-fifos

Sejauh yang saya bisa lihat, baik dari slide presentasi, dan sumber @ http://lxr.free-electrons.com/source/fs/pipe.c - fifo diimplementasikan sebagai pembungkus di sekitar pipa, dan pipa itu sendiri adalah diimplementasikan melalui sistem file virtual pipefs ..

@ lgeorget - Pipa tampaknya menggunakan memori kernel untuk buffer antara pembaca dan penulis - mereka tidak menggunakan 'memori bersama' seperti itu, dan menyalin memori antara ruang alamat pengguna dan kernel (misalnya, pipe_readpanggilan pipe_iov_copy_to_user, yang memanggil __copy_to_user_inatomic(atau copy_to_user) . __copy_to_user_inatomicpanggilan copy_user_generic, yang pada beberapa implementasi ASM.

tjb63
sumber
4

"FIFO" dan " pipa bernama " adalah hal yang sama - meskipun sangat berbeda dari bagaimana shell menangani "pipa" (|) antara dua perintah pada baris perintah.

Pipa bernama (FIFO) adalah "file" tunggal yang dibagikan oleh dua program, di mana satu menulis ke sana dan yang lain membaca darinya ... Soket di sisi lain adalah "koneksi" antara dua "file" - yang mungkin menggunakan jaringan dan berada di komputer yang terpisah - di mana satu program membaca / menulis ke satu "file" dan program lain membaca / menulis ke yang lain ... Saya tidak berpikir mereka sama ... Di sisi lain keduanya soket dan pipa bernama - serta file, perangkat, tautan simbolik - semua menggunakan inode, dan mereka semua mengimplementasikan beberapa fitur umum (seperti membaca dan menulis).

Baard Kopperud
sumber
1
Ya, soket domain Unix adalah sejenis soket, jadi APInya mirip dengan soket soket lain seperti TCP atau UDP, dll. Namun, soket domain Unix hanya dapat digunakan sebagai IPC "lokal". Dan cara transfer data dilakukan pertama-tama, cukup banyak seperti FIFO & pipe. Jadi saya pikir itu mungkin API Unix domain socket hanyalah enkapsulasi dari implementasi yang identik jadi kami menggunakannya seolah-olah itu adalah socket. Saya pikir itu mungkin mereka semua berbagi internal yang sama di kernel ... Saya ingin mengkonfirmasi apakah itu benar atau tidak.
Justin
1

Kurasa tidak, Justin. Jika saya tidak salah, dan saya sangat mungkin, saya pikir FIFO menggunakan file pada disk, dan soket Unix Domain menggunakan memori kernel.

Juga, sebagai tambahan pada poster di atas yang menyebutkan bahwa soket domain Unix adalah dua arah, itu hanya merupakan kasus ketika menggunakan soket SOCK_STREAM. SOCK_DGRAM Soket domain unix sebenarnya adalah uni-directional, dan hanya dapat mengirim () dari kode yang disebut connect (), ke kode yang disebut bind ().

Tentu saja, kode yang disebut connect () juga harus memanggil bind () untuk membuat titik akhir sendiri, tetapi itu tidak ada hubungannya dengan pertanyaan Anda.

Anonim
sumber
3
Selamat datang di StackExchange, dan terima kasih telah memposting. Beberapa komentar ... 1) Jika Anda "sangat mungkin" salah, Anda harus memeriksa ulang sebelum menjawab; situs ini bukan forum atau obrolan. 2) Terima kasih atas ketepatan Anda pada soket berorientasi datagram 3) Tidak perlu memposting sesuatu yang "tidak ada hubungannya" dengan pertanyaan. :)
lgeorget
1

2 sen saya ... FIFO dan UNIX socket keduanya bi-directional (mirip) tetapi socket memiliki topologi bintang sedangkan FIFO hanya antrian (dan karenanya tidak dapat saling menggantikan), ya implementasinya dapat berbagi kode secara internal.

**

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**
Asif Bahrainwala
sumber
FIFO adalah dua arah?
jhfrontz