Saya sedang meneliti pertanyaan lain , ketika saya menyadari saya tidak mengerti apa yang terjadi di bawah tenda, /dev/fd/*
file apa itu dan bagaimana proses anak bisa membukanya.
bash
process-substitution
x-yuri
sumber
sumber
Jawaban:
Ya, ada banyak aspek untuk itu.
Penjelas file
Untuk setiap proses, kernel memelihara tabel file yang terbuka (well, itu mungkin diimplementasikan secara berbeda, tetapi karena Anda tidak dapat melihatnya, Anda bisa menganggap itu adalah tabel sederhana). Tabel itu berisi informasi tentang file mana itu / di mana ia dapat ditemukan, dalam mode apa Anda membukanya, di posisi mana Anda sedang membaca / menulis, dan apa pun yang diperlukan untuk benar-benar melakukan operasi I / O pada file itu. Sekarang prosesnya tidak pernah membaca (atau bahkan menulis) tabel itu. Ketika proses membuka file, itu akan kembali disebut file descriptor. Yang hanya merupakan indeks ke dalam tabel.
Direktori
/dev/fd
dan isinyaDi Linux
dev/fd
sebenarnya tautan simbolis ke/proc/self/fd
./proc
adalah sistem file pseudo di mana kernel memetakan beberapa struktur data internal untuk diakses dengan file API (sehingga mereka hanya terlihat seperti file biasa / direktori / symlink ke program). Terutama ada informasi tentang semua proses (yang memberi nama itu). Tautan simbolik/proc/self
selalu merujuk ke direktori yang terkait dengan proses yang sedang berjalan (yaitu, proses memintanya; proses yang berbeda akan melihat nilai yang berbeda). Di direktori proses, ada subdirektorifd
yang untuk setiap file yang terbuka berisi tautan simbolik yang namanya hanyalah representasi desimal dari deskriptor file (indeks ke dalam tabel file proses, lihat bagian sebelumnya), dan yang targetnya adalah file yang sesuai dengan itu.Deskriptor file saat membuat proses anak
Proses anak dibuat oleh a
fork
. Afork
membuat salinan deskriptor file, yang berarti proses anak yang dibuat memiliki daftar file terbuka yang sama dengan proses induk. Jadi kecuali salah satu file yang terbuka ditutup oleh anak, mengakses deskriptor file yang diwarisi pada anak akan mengakses file yang sama seperti mengakses deskriptor file asli dalam proses induk.Perhatikan bahwa setelah garpu, Anda awalnya memiliki dua salinan dari proses yang sama yang hanya berbeda dalam nilai balik dari panggilan garpu (orang tua mendapat PID anak, anak mendapat 0). Biasanya, sebuah garpu diikuti oleh
exec
untuk menggantikan salah satu salinan oleh executable lain. Deskriptor file terbuka bertahan dari eksekutif itu. Perhatikan juga bahwa sebelum eksekutif, proses tersebut dapat melakukan manipulasi lain (seperti menutup file yang seharusnya tidak didapat oleh proses baru, atau membuka file lain).Pipa yang tidak disebutkan namanya
Pipa tanpa nama hanyalah sepasang deskriptor file yang dibuat berdasarkan permintaan oleh kernel, sehingga semua yang ditulis ke deskriptor file pertama diteruskan ke yang kedua. Penggunaan yang paling umum adalah untuk membangun pipa
foo | bar
daribash
, di mana output standarfoo
diganti dengan menulis bagian dari pipa, dan input standar Menggantikan oleh bagian dibaca. Input standar dan output standar hanyalah dua entri pertama dalam tabel file (entri 0 dan 1; 2 adalah kesalahan standar), dan karenanya menggantinya berarti hanya menulis ulang entri tabel tersebut dengan data yang sesuai dengan deskriptor file lainnya (sekali lagi, implementasi aktual mungkin berbeda). Karena proses tidak dapat mengakses tabel secara langsung, ada fungsi kernel untuk melakukan itu.Substitusi proses
Sekarang kita memiliki segalanya bersama untuk memahami bagaimana proses substitusi bekerja:
echo
proses. Proses anak (yang merupakan salinan tepat daribash
proses asli ) menutup ujung pembacaan pipa dan mengganti output standar sendiri dengan ujung penulisan pipa. Mengingat bahwa ituecho
adalah builtin shell,bash
mungkin mengampuniexec
panggilan itu sendiri , tetapi toh itu tidak masalah (shell builtin juga dapat dinonaktifkan, dalam hal ini ia menjalankan/bin/echo
).<(echo 1)
dengan tautan file pseudo yang/dev/fd
merujuk pada ujung bacaan dari pipa yang tidak disebutkan namanya./dev/fd/
. Karena deskriptor file yang sesuai masih terbuka, itu masih sesuai dengan ujung pipa pembacaan. Oleh karena itu jika program PHP membuka file yang diberikan untuk dibaca, apa yang sebenarnya dilakukannya adalah membuatsecond
deskriptor file untuk ujung bacaan dari pipa yang tidak disebutkan namanya. Tapi itu tidak masalah, bisa dibaca dari keduanya.echo
perintah yang menuju akhir penulisan dari pipa yang sama.sumber
php
skenario, tetapiphp
tidak menangani pipa dengan baik . Juga, mengingat perintahcat <(echo test)
, yang aneh di sini adalah bahwabash
garpu sekali untukcat
, tetapi dua kali untukecho test
.Meminjam dari
celtschk
jawaban,/dev/fd
adalah tautan simbolis ke/proc/self/fd
. Dan/proc
adalah sistem file pseudo, yang menyajikan informasi tentang proses dan informasi sistem lainnya dalam struktur seperti file hirarkis. File dalam/dev/fd
berhubungan dengan file, dibuka oleh suatu proses dan memiliki deskriptor file sebagai nama mereka dan file itu sendiri sebagai target mereka. Membuka file/dev/fd/N
sama dengan duplikasi deskriptorN
(dengan asumsi deskriptorN
terbuka).Dan berikut ini adalah hasil penyelidikan saya tentang cara kerjanya (
strace
output menghilangkan detail yang tidak perlu dan dimodifikasi untuk mengekspresikan apa yang terjadi dengan lebih baik):Pada dasarnya,
bash
buat sebuah pipa dan memberikan ujung-ujungnya kepada anak-anaknya sebagai deskriptor file (baca akhir1.out
, dan tuliskan akhir2.out
). Dan melewati baca sebagai parameter baris perintah ke1.out
(/dev/fd/63
). Cara1.out
ini bisa terbuka/dev/fd/63
.sumber