Page fault biasanya membawa eksekusi dari proses ke kernel dan baru kembali setelah kernel menyelesaikan kondisi virtual-memory atau mengirim error. Linux userfaultfd dapat menyisipkan komponen user-space ke jalur tersebut untuk rentang alamat yang didaftarkan secara eksplisit. Kernel melaporkan fault terpilih melalui file descriptor, memblokir execution context yang mengalami fault saat mode mengharuskannya, lalu menerima ioctl yang menyelesaikan fault tersebut.

Ini adalah antarmuka virtual-memory Linux, bukan jaminan memori dari C atau POSIX. Perilakunya bergantung pada fitur kernel yang dinegosiasikan, rentang terdaftar, jenis mapping, dan mode registrasi.

Registrasi menetapkan batas fault

Pemanggilan userfaultfd() membuat descriptor, tetapi descriptor itu sendiri tidak mengalihkan fault. Proses lebih dahulu menegosiasikan API dengan UFFDIO_API, lalu mendaftarkan interval alamat melalui UFFDIO_REGISTER. Mode yang diminta menentukan kelas fault yang masuk ke protokol.

UFFDIO_REGISTER_MODE_MISSING mencakup akses ke page yang belum tersedia pada mapping terdaftar yang didukung. UFFDIO_REGISTER_MODE_WP menyediakan fault write protection dari userfaultfd. UFFDIO_REGISTER_MODE_MINOR, jika didukung untuk jenis mapping dan kernel terkait, melaporkan minor fault untuk page yang konten backing-nya sudah ada tetapi state page table-nya masih perlu diselesaikan.

Mode-mode tersebut tidak saling menggantikan. Handler missing-page memasok konten atau mengisi page dengan nol. Handler write-protection mengendalikan write barrier pada page yang sudah dipetakan. Handler minor-fault dapat mengoordinasikan pemasangan page table tanpa menganggap data backing belum tersedia.

Registrasi dengan demikian menjadi batas capability pada interval alamat, bukan pengganti mekanisme page-fault kernel untuk seluruh proses. Fault di luar rentang terdaftar tetap mengikuti jalur kernel biasa.

Pengiriman fault memakai protokol descriptor

Descriptor userfaultfd dapat dipantau dengan poll(), select(), atau epoll(). Operasi read mengembalikan satu atau beberapa record struct uffd_msg. Untuk event page fault, record membawa alamat fault dan flag yang menandai properti relevan seperti akses tulis atau fault write-protection.

Event tersebut adalah notifikasi, bukan resolusi. Pada mode fault yang menghentikan eksekusi sementara, thread yang menyentuh alamat tetap terblokir sampai execution context lain menjalankan operasi yang membuat fault dapat diselesaikan, atau sampai state mapping di sekitarnya berubah sehingga penantian itu berakhir.

Pemisahan ini memiliki konsekuensi concurrency penting: thread yang mengalami fault tidak dapat sekaligus menjadi satu-satunya handler yang bertanggung jawab melayani fault-nya sendiri ketika thread tersebut terblokir. Desain umumnya menyediakan thread atau proses lain untuk membaca descriptor dan menjalankan ioctl resolusi. Handler itu juga perlu menghindari akses ke memori terdaftar yang menciptakan siklus dependensi melalui jalur layanan yang sama.

Resolusi mengubah state memori, bukan record event

Untuk missing fault, UFFDIO_COPY menyalin byte ke rentang fault dan memasang state page yang dihasilkan secara atomik terhadap operasi resolusi fault. UFFDIO_ZEROPAGE, pada mapping yang mendukungnya, menyelesaikan missing page dengan konten berisi nol. Operasi tersebut bekerja pada rentang yang selaras dengan batas page walaupun alamat fault yang dilaporkan menunjuk ke posisi di dalam page.

Untuk minor fault, UFFDIO_CONTINUE meminta kernel melanjutkan penanganan fault dengan konten backing yang sudah ada. Untuk mode write-protection, UFFDIO_WRITEPROTECT menerapkan atau melepas state write protection userfaultfd pada suatu rentang.

Ioctl resolusi yang berhasil tidak berarti setiap akses berikutnya ke rentang tersebut bebas fault. Page lain masih dapat berstatus missing, write protection dapat tetap aktif pada page di sebelahnya, dan perubahan mapping dapat membatalkan asumsi handler. Protokol bekerja pada state virtual-memory saat ini, bukan janji permanen mengenai interval alamat.

Mutasi mapping membentuk bidang event kedua

Rentang alamat virtual bukan identitas statis. munmap(), operasi remapping, pembuatan proses, dan perubahan mapping lain dapat mengubah hubungan antara alamat dan backing object. userfaultfd menyediakan negosiasi fitur dan mekanisme event untuk perubahan tertentu yang bukan page fault, dengan ketersediaan bergantung pada fitur API yang diminta dan dukungan kernel.

Handler yang hanya menyimpan alamat fault mentah karena itu dapat menjadi usang. Alamat memiliki makna relatif terhadap memory map proses saat event diinterpretasikan. Jika aplikasi mengizinkan mutasi mapping secara bersamaan, handler memerlukan kontrak sinkronisasi yang menghubungkan metadata miliknya dengan mutasi tersebut.

Hal ini berbeda dari request storage yang memakai immutable object identifier. Alamat virtual adalah lokasi dalam address space yang dapat berubah. Memperlakukannya sebagai identitas permanen dapat membuat respons fault yang terlambat mengisi rentang yang peran aplikasinya sudah berubah.

Penyalinan data page tidak menetapkan ownership aplikasi

UFFDIO_COPY menyediakan operasi kernel untuk memasang konten page, tetapi tidak menetapkan model ownership tingkat aplikasi bagi data sumber. Handler tetap bertanggung jawab atas lifetime dan konsistensi source buffer atau backing store yang dipakai untuk menghasilkan page.

Batas yang sama muncul pada desain snapshot dan migrasi. userfaultfd dapat mengekspos akses pertama, konten yang belum tersedia, atau upaya tulis melalui mode yang didukung, tetapi antarmuka ini tidak dengan sendirinya menetapkan konsistensi snapshot. Jika thread lain dapat memutasi state terkait, aplikasi tetap memerlukan aturan ordering yang menentukan versi state yang terkait dengan respons page tertentu.

Mode write-protection sangat berguna sebagai sinyal sinkronisasi karena operasi tulis dapat dicegat sebelum page terlindungi dimodifikasi. Event yang terlihat tetap tidak menentukan kebijakan. Handler dapat mencatat dirtiness, menyalin konten lama, melepas protection, atau menggabungkan tindakan tersebut, tetapi jaminan konsistensi berasal dari keseluruhan protokol di sekitar urutan ioctl.

Kegagalan handler menjadi bagian dari kontrak memori

Memindahkan resolusi ke user space juga memindahkan dependensi liveness. Thread yang terblokir pada fault yang dikelola userfaultfd tidak dapat maju selama tindakan handler yang diperlukan belum terjadi. Jika handler menunggu lock yang dipegang thread yang mengalami fault, deadlock dapat terjadi walaupun antarmuka kernel bekerja sesuai spesifikasinya.

Tekanan resource dapat membentuk siklus serupa. Handler yang mengalokasikan memori, melakukan filesystem I/O, atau memanggil runtime dengan perilaku page-touch sendiri dapat secara tidak langsung bergantung pada memori yang dicakup layanan fault yang sama. Kernel menyediakan mekanisme tersebut; kernel tidak dapat menjamin bahwa graf dependensi di sekitarnya bebas siklus.

Menutup descriptor, membatalkan registrasi rentang, atau mengubah mapping juga memengaruhi fault yang sedang berlangsung dan fault berikutnya sesuai aturan antarmuka kernel. Shutdown karena itu memerlukan ordering eksplisit antara penghentian sumber akses baru, penyelesaian atau pembatalan pekerjaan fault, perubahan registrasi, dan pelepasan resource handler.

Descriptor memisahkan deteksi dari kebijakan

Properti utama userfaultfd bukan sekadar membuat page fault terlihat oleh aplikasi. Antarmuka ini memisahkan deteksi kernel atas event virtual-memory terpilih dari keputusan user-space mengenai konten page, kelanjutan page table, atau write protection. Pemisahan tersebut membentuk batas yang dapat diprogram dengan operasi ioctl yang presisi sekaligus kewajiban liveness yang juga presisi.

Antarmuka ini paling kokoh ketika ownership rentang alamat, mutasi mapping, concurrency handler, dan urutan shutdown diperlakukan sebagai bagian dari satu protokol. Tanpa batasan tersebut, event fault yang valid secara teknis masih dapat tiba pada handler dengan metadata usang atau dependensi yang membuatnya tidak mampu menyelesaikan execution context yang terblokir.