Sebuah proses dapat memperoleh descriptor baru yang merujuk ke open file description yang sama dengan descriptor milik proses lain tanpa meminta proses target mengirimkannya. Linux menyediakan operasi ini melalui pidfd_getfd(). Descriptor hasilnya berada di descriptor table caller, tetapi objek kernel di belakangnya tetap sama dengan descriptor target.
Perbedaan tersebut penting karena nomor descriptor hanya merupakan entri pada descriptor table sebuah proses. Open file description membawa state seperti posisi file saat ini dan file status flags. Duplikasi lintas proses karena itu memberikan referensi ke instance file kernel yang sudah ada, bukan membuka ulang pathname atau membuat instance independen.
Descriptor hasil duplikasi mempertahankan state open file
Operasi ini menerima PID file descriptor, nomor descriptor dari proses yang dirujuk, dan argumen flags:
int fd = syscall(SYS_pidfd_getfd, pidfd, targetfd, 0);Jika berhasil, fd dialokasikan pada caller. Descriptor tersebut merujuk ke open file description yang sama dengan targetfd. Jika objek itu memiliki file offset bersama, operasi read atau write melalui salah satu descriptor dapat mengubah offset yang terlihat melalui descriptor lainnya. File status flags yang terkait dengan open file description juga dibagi.
Descriptor flags berada pada layer terpisah. Linux memasang FD_CLOEXEC pada descriptor yang dikembalikan pidfd_getfd(). Flag tersebut menjadi milik entri descriptor caller dan menyebabkan descriptor ditutup saat execve() berhasil, kecuali caller mengubahnya.
API saat ini mengharuskan flags bernilai nol. Nilai selain nol ditolak dengan EINVAL.
PID file descriptor menstabilkan pemilihan proses
PID numerik dapat digunakan kembali setelah sebuah proses berakhir. pidfd_getfd() tidak menerima PID biasa sebagai handle proses. Interface ini menerima PID file descriptor, yang umumnya diperoleh melalui pidfd_open() atau dibuat melalui interface pembuatan proses yang sesuai.
Desain tersebut membuat target menjadi objek yang dirujuk descriptor, bukan angka yang terus di-resolve oleh aplikasi. Namun, identitas berbasis descriptor tidak mengubah akses menjadi capability tanpa syarat. Kernel tetap menjalankan ptrace access check untuk permintaan duplikasi.
Pemeriksaan yang relevan adalah PTRACE_MODE_ATTACH_REALCREDS. Caller yang memiliki pidfd tetapi tidak lolos pemeriksaan otorisasi ini menerima EPERM. Identitas proses dan izin untuk mengambil salah satu descriptornya merupakan dua hal terpisah.
Proses target tidak perlu berpartisipasi
Pengiriman descriptor melalui SCM_RIGHTS pada UNIX domain socket memerlukan channel komunikasi dan sender yang aktif. pidfd_getfd() memakai model koordinasi berbeda. Setelah caller memiliki pidfd yang sesuai dan lolos pemeriksaan akses, proses target tidak perlu menjalankan operasi send.
Properti ini cocok untuk desain supervision, inspection, checkpointing, dan process management ketika controller sudah memiliki otoritas terhadap target tetapi tidak tersedia protokol transfer descriptor yang kooperatif.
Operasi tersebut juga tidak identik dengan membuka /proc/<pid>/fd/<n>. Membuka ulang link descriptor pada procfs dapat memiliki pembatasan spesifik objek dan dapat menghasilkan state open file yang berbeda, bergantung pada objek serta operasinya. pidfd_getfd() secara eksplisit menduplikasi open file description milik descriptor yang sudah ada.
Offset bersama menciptakan coupling yang terlihat
Misalkan descriptor target untuk regular file berada pada offset 4096. Setelah duplikasi berhasil, kedua descriptor merujuk ke open file description yang sama:
target fd ----+
|
v
open file description
offset = 4096
^
|
caller fd ----+read() melalui descriptor caller dapat memajukan offset bersama tersebut. read() sekuensial berikutnya melalui descriptor target kemudian dimulai dari posisi yang sudah berubah. Duplikasi lintas proses dengan demikian membentuk relasi berbagi state, bukan snapshot.
Operasi dengan offset eksplisit seperti pread() tidak mengubah posisi file bersama, tetapi hal itu tidak membuat kedua descriptor menjadi independen. State open file lainnya tetap dibagi ketika API objek tersebut menetapkannya demikian.
Untuk socket dan objek kernel berbasis descriptor lainnya, descriptor hasil duplikasi juga merujuk ke objek dasar yang sama. Operasi melalui satu referensi dapat memengaruhi objek yang terlihat melalui referensi lainnya.
Lifetime descriptor menjadi independen setelah duplikasi
Berbagi open file description tidak berarti salah satu proses memiliki entri descriptor table milik proses lain. Setelah pidfd_getfd() berhasil, caller dan target memiliki entri descriptor terpisah yang kebetulan merujuk ke objek kernel yang sama.
Menutup descriptor target tidak menutup hasil duplikasi pada caller. Menutup descriptor caller juga tidak menghapus entri milik target. Open file description tetap hidup selama masih ada referensi terhadapnya.
Properti lifetime ini dapat memperpanjang usia resource secara sengaja. Controller yang menduplikasi socket, endpoint pipe, event descriptor, atau regular file dapat mempertahankan referensi ke objek dasar setelah target menutup descriptornya sendiri. Kebijakan ownership resource perlu memperhitungkan referensi tambahan tersebut.
Nomor descriptor tetap lokal terhadap proses
Argumen targetfd diinterpretasikan pada descriptor table proses yang dirujuk oleh pidfd. Integer hasil dialokasikan pada descriptor table caller dan dapat memiliki nilai numerik yang sama sekali berbeda.
Sistem monitoring karena itu tidak dapat memperlakukan nomor descriptor sebagai identifier objek global. Pasangan konteks proses dan nomor descriptor mengidentifikasi entri table; open file description di balik entri tersebut merupakan objek kernel yang berbeda.
Jika targetfd sudah tidak terbuka ketika kernel mengevaluasi permintaan, operasi gagal dengan EBADF. Kondisi ini dapat berlomba dengan penutupan atau penggantian descriptor pada target yang terus mengubah descriptor table-nya. Pidfd menstabilkan proses yang dirujuk, bukan arti setiap slot descriptor di dalam proses tersebut untuk seluruh waktu berikutnya.
Failure mode memperlihatkan batas resource dan lifecycle
pidfd_getfd() dapat gagal dengan EMFILE ketika caller mencapai batas descriptor per proses dan dengan ENFILE ketika batas open file pada tingkat sistem habis. Kegagalan tersebut dapat terjadi meskipun descriptor target masih valid.
ESRCH dapat menandakan bahwa proses yang dirujuk pidfd tidak lagi berada pada state yang diperlukan operasi. EBADF juga mencakup pidfd yang tidak valid atau target descriptor yang tidak valid. Kode yang memakai interface ini perlu memisahkan lifecycle target, validitas slot descriptor, otorisasi, dan batas resource caller.
Batas tersebut penting pada process supervisor. Keberhasilan memperoleh pidfd tidak menjamin ekstraksi descriptor berikutnya akan berhasil; target dapat berakhir, menutup descriptor, atau mengubah topologi descriptornya di antara kedua operasi.
Duplikasi lintas proses memperoleh referensi ke objek bersama
pidfd_getfd() paling tepat dimodelkan sebagai perolehan referensi tambahan ke open file description yang sudah ada. Operasi ini tidak menyalin isi file, mengkloning state open file, atau membuka ulang resource berdasarkan nama. Caller memperoleh entri descriptor sendiri sambil berbagi objek kernel dan state open file terkait dengan target.
Model tersebut menjelaskan manfaat sekaligus risikonya. Interface ini dapat mengambil akses ke resource aktif tanpa kerja sama target, tetapi juga dapat menghubungkan offset, memperpanjang lifetime resource, dan membuka operasi terhadap objek dasar yang sama. Ptrace authorization check membatasi pihak yang boleh melintasi batas proses tersebut, sedangkan descriptor hasilnya mengikuti aturan lifetime descriptor dan open file description biasa.