PID numerik adalah nama dari namespace kernel yang dapat digunakan kembali. Setelah sebuah proses keluar dan PID-nya tersedia lagi, proses lain dapat menerima nomor yang sama. Linux pidfd menyediakan bentuk referensi berbeda: file descriptor yang terikat pada task tertentu, bukan nomor yang harus diresolusi ulang pada setiap operasi.

Perbedaan ini mengubah batas antara penemuan proses dan kontrol proses berikutnya. Program dapat meresolusi PID sekali melalui pidfd_open(), menyimpan descriptor hasilnya, lalu memakai antarmuka berbasis pidfd tanpa menganggap PID numerik sebagai identitas permanen.

Descriptor menangkap referensi task

pidfd_open(pid, flags) meminta kernel membuat file descriptor yang merujuk task yang diidentifikasi pada saat pemanggilan. Jika berhasil, descriptor tersebut memiliki status close-on-exec. Linux memperkenalkan system call ini pada versi 5.3.

Properti utamanya bukan membuat PID berhenti ada atau berhenti dapat digunakan kembali. pidfd mempertahankan referensi ke task tertentu yang telah diresolusi. Jika task itu berakhir, operasi berbasis pidfd tidak diam-diam beralih ke proses baru yang kebetulan menerima PID numerik yang sama.

Hal ini berbeda dari menyimpan integer PID lalu memanggil antarmuka yang meresolusi integer tersebut lagi. Integer tetap berguna untuk tampilan, log, dan API yang memerlukan identifier numerik, tetapi integer itu sendiri tidak mempertahankan identitas task sepanjang waktu.

Exit menjadi status yang dapat dipantau

pidfd proses dapat digunakan bersama poll(), select(), dan epoll. Ketika proses yang dirujuk berakhir dan menjadi zombie, polling melaporkan status readable. Setelah proses di-reap, polling juga dapat melaporkan status hangup.

Descriptor ini dapat dipantau, tetapi bukan byte stream. Pada implementasi Linux saat ini, read() terhadap pidfd gagal dengan EINVAL. Readiness melaporkan transisi lifecycle task yang dirujuk; status itu bukan tanda adanya payload buffered yang menunggu dibaca.

Mekanisme ini menempatkan terminasi proses ke dalam event loop berbasis descriptor tanpa mengubah exit menjadi pesan pipe sintetis. Event loop dapat memantau socket, timer, signal, dan referensi proses melalui antarmuka readiness yang kompatibel, sementara setiap descriptor tetap memiliki semantik objeknya sendiri.

Signaling melalui referensi menutup race akibat penggunaan ulang PID

kill(pid, sig) tradisional menamai target dengan PID numerik. Desain yang memeriksa proses terlebih dahulu lalu memanggil kill() memiliki interval waktu ketika proses awal dapat keluar dan PID-nya dapat dipakai kembali.

pidfd_send_signal() menerima pidfd sebagai gantinya. Jika task yang dirujuk descriptor tersebut telah berakhir, signaling gagal alih-alih memilih proses lain melalui penggunaan ulang PID numerik. Pemeriksaan izin tetap berlaku; referensi stabil tidak memberikan otoritas secara otomatis.

Perbedaannya terletak pada identitas, bukan semantik pengiriman. Signal tetap mengikuti aturan signal Linux, dan pengiriman yang berhasil tidak berarti pekerjaan pada level aplikasi yang terkait dengan signal telah selesai.

Waktu akuisisi tetap memiliki batas

pidfd_open() meresolusi task yang sudah ada, sehingga interval sebelum pemanggilan itu berada di luar perlindungan yang diberikan descriptor hasilnya. Jika perangkat lunak memperoleh PID dari sumber eksternal lalu menunggu sebelum memanggil pidfd_open(), nama numerik tersebut dapat menjadi usang sebelum akuisisi.

Untuk child langsung, retensi zombie dapat mencegah PID digunakan kembali cukup lama agar parent memperoleh pidfd, tetapi hal itu bergantung pada kondisi reaping proses. Linux juga mendukung pembuatan child sekaligus pidfd melalui clone() atau clone3() dengan CLONE_PIDFD, sehingga lookup terpisah setelah pembuatan tidak diperlukan dalam lifecycle tersebut.

Batas umumnya tegas: pidfd menstabilkan identitas setelah referensi task berhasil diperoleh. Mekanisme ini tidak membuat observasi PID numerik yang terjadi sebelumnya bebas race secara retroaktif.

Waiting tetap mengikuti aturan parent-child

pidfd yang merujuk child dapat diberikan kepada waitid() dengan P_PIDFD. Mekanisme ini menghubungkan identitas stabil dengan mekanisme waiting child yang normal.

Memegang pidfd tidak membuat sembarang proses menjadi waitable. Relasi parent-child dan aturan antarmuka wait tetap menentukan apakah exit status dapat dikumpulkan. Pollability dan waitability adalah kapabilitas yang berkaitan, tetapi tidak saling menggantikan.

Pemisahan ini relevan bagi supervisor yang mengamati proses yang tidak dibuatnya. pidfd dapat menyediakan identitas stabil dan exit readiness meski pemanggil tidak memiliki relasi child yang mengizinkannya melakukan reap terhadap target.

Lifetime descriptor bukan kontrol lifetime proses

Menutup pidfd melepaskan referensi tersebut. Tindakan itu tidak menghentikan proses yang dirujuk. Demikian pula, mempertahankan pidfd tetap terbuka tidak membuat proses terus berjalan setelah proses tersebut exit.

Descriptor mengikuti aturan kepemilikan descriptor biasa: dapat diduplikasi, diwariskan ketika perilaku close-on-exec mengizinkan, diteruskan antarproses melalui mekanisme descriptor passing, dan ditutup secara independen dari referensi lain. Transfer semacam itu dapat memindahkan referensi proses yang stabil melewati batas proses, tetapi operasi melalui referensi tersebut tetap dibatasi izin pemanggil dan API berbasis pidfd yang digunakan.

Dengan demikian, pidfd berbentuk seperti referensi capability tanpa menjadi pemberian capability tanpa syarat. pidfd mengidentifikasi objek task kernel secara stabil; otorisasi tetap merupakan keputusan terpisah.

Identitas stabil mempersempit kontrak kontrol proses

Pidfd tidak menggantikan seluruh antarmuka PID numerik, aturan process namespace, atau lifecycle parent-child. Kontribusinya lebih sempit: memisahkan identitas task dari lookup berulang terhadap integer yang dapat digunakan kembali.

Pemisahan tersebut menghasilkan konsekuensi yang dapat diamati. Exit dapat muncul sebagai descriptor readiness, signaling dapat menargetkan referensi task yang telah ditangkap, dan waiting dapat memakai referensi yang sama ketika semantik child-wait mengizinkannya. Setelah akuisisi berhasil, penggunaan ulang PID berikutnya tidak mengarahkan operasi berbasis pidfd itu ke proses lain.

Batas yang tersisa tetap eksplisit: akuisisi dapat mengalami race sebelum descriptor ada, izin tetap mengatur operasi kontrol, poll readiness membawa status lifecycle alih-alih byte yang dapat dibaca, dan lifetime descriptor tidak mengendalikan lifetime proses.