- Pola desain berorientasi objek memungkinkan penerapan polimorfisme dan modularitas bahkan di kernel yang ditulis dalam bahasa C, sehingga desain sistem menjadi lebih fleksibel
- Dengan menggunakan vtable (tabel fungsi virtual), antarmuka perangkat dan layanan dapat distandardisasi, serta perubahan dinamis saat runtime mendukung beragam perilaku
- Layanan kernel dan scheduler menyediakan antarmuka yang konsisten seperti mulai, berhenti, dan mulai ulang melalui vtable, sambil mengenkapsulasi detail implementasi
- Dikombinasikan dengan modul kernel, pendekatan ini mendukung pemuatan driver secara dinamis dan memungkinkan sistem diperluas tanpa kompilasi ulang
- Pendekatan ini memberi fleksibilitas dan kebebasan bereksperimen, tetapi kelemahannya adalah sintaks yang kompleks dan kerepotan akibat pengiriman objek secara eksplisit
Kebebasan dalam pengembangan OS dan pola berorientasi objek
- Mengembangkan OS sendiri memungkinkan eksperimen bebas tanpa batasan kolaborasi atau tuntutan aplikasi nyata
- Bebas dari kerentanan keamanan, pemeliharaan kode, dan beban rilis
- Ini menjadi daya tarik pengembangan OS, karena memungkinkan eksplorasi pola pemrograman yang tidak standar
- Artikel LWN “Object-oriented design patterns in the kernel” memperkenalkan contoh bagaimana kernel Linux menerapkan prinsip berorientasi objek dalam C
- Polimorfisme diterapkan melalui struktur yang berisi pointer fungsi
- Melalui enkapsulasi, modularitas, dan ekstensibilitas, keunggulan berorientasi objek dapat dimanfaatkan bahkan di kernel tingkat rendah
Konsep dasar vtable
- vtable adalah struktur yang berisi pointer fungsi dan mendefinisikan antarmuka sebuah objek
- Contoh: struktur untuk operasi perangkat
struct device_ops { void (*start)(void); void (*stop)(void); }; struct device { const char *name; const struct device_ops *ops; };
- Contoh: struktur untuk operasi perangkat
- Perangkat yang berbeda (misalnya
netdev,disk) menggunakan API yang sama, tetapi implementasinya berbedanetdev.ops->start()memanggil operasi perangkat jaringan, sedangkandisk.ops->start()memanggil operasi perangkat disk
- Perubahan saat runtime: vtable dapat diganti secara dinamis untuk mengubah perilaku tanpa mengubah kode pemanggil
- Dengan sinkronisasi yang tepat, ini memungkinkan evolusi perilaku dinamis yang rapi
Contoh penerapan di OS
Manajemen layanan
- Layanan kernel (manajer jaringan, worker pool, server jendela, dan sebagainya) dapat dikelola dengan antarmuka yang konsisten
- Struktur layanan:
struct service_ops { void (*start)(void); void (*stop)(void); void (*restart)(void); }; struct service { pid_t pid; const struct service_ops *ops; };
- Struktur layanan:
- Setiap layanan mengimplementasikan perilaku uniknya sendiri, tetapi mulai/berhenti/mulai ulang dapat dijalankan dari terminal dengan cara yang terstandarisasi
- Keterikatan antara kode dan layanan berkurang, sehingga pengelolaan menjadi lebih sederhana
Scheduler
- Scheduler dapat mendukung berbagai strategi seperti round robin, shortest job first, FIFO, dan penjadwalan prioritas
- Antarmukanya disederhanakan menjadi
yield,block,add, dannext - Didefinisikan lewat vtable sehingga kebijakan penjadwalan dapat diganti saat runtime
- Seluruh kebijakan dapat diubah tanpa memodifikasi bagian kernel lainnya
- Antarmukanya disederhanakan menjadi
Abstraksi file
- Struktur file_operations di Linux mewujudkan filosofi “segala sesuatu adalah file”
- Contoh: https://elixir.bootlin.com/linux/v6.15/source/include/linux/fs.h
struct file_operations { struct module *owner; loff_t (*llseek)(struct file *, loff_t, int); ssize_t (*read)(struct file *, char __user *, size_t, loff_t *); ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *); ... };
- Contoh: https://elixir.bootlin.com/linux/v6.15/source/include/linux/fs.h
- Socket, perangkat, dan file teks semuanya menyediakan antarmuka read/write yang sama
- Kode ruang pengguna dapat bekerja secara konsisten tanpa perlu mengetahui detail implementasinya
Integrasi dengan modul kernel
- Modul kernel mendukung pemuatan driver atau hook secara dinamis melalui penggantian vtable
- Seperti modul Linux, kernel dapat diperluas tanpa kompilasi ulang atau reboot
- Saat menambahkan fitur baru, cukup memperbarui vtable pada struktur yang sudah ada
Kekurangan
- Kompleksitas sintaks:
- Objek harus dikirim secara eksplisit seperti
object->ops->start(object) - Lebih merepotkan dibanding pengiriman implisit di C++
- Signature fungsi juga lebih panjang:
static void object_start(struct object* this) { this->id = ... }
- Objek harus dikirim secara eksplisit seperti
- Kelebihan: pengiriman eksplisit membuat dependensi fungsi jelas, dan keterikatan antara objek serta perilaku menjadi transparan
- Ini adalah tradeoff yang tepat antara kompleksitas dan kejelasan dalam kode kernel
Implikasi
- vtable menyediakan cara sederhana untuk mengurangi kompleksitas sambil mempertahankan fleksibilitas
- Penggantian perilaku saat runtime, pemeliharaan antarmuka yang konsisten, dan kemudahan menambahkan fitur baru
- Menunjukkan cara baru untuk menerapkan desain berorientasi objek dalam bahasa C, sekaligus menekankan keseruan eksperimental pengembangan OS
- Referensi tambahan: proyek xine (https://xine.sourceforge.net/hackersguide#id324430) memperkenalkan cara mengelola variabel privat dengan vtable
- Pengembangan OS adalah ajang eksperimen kreatif, dan pola berorientasi objek terbukti menjadi alat yang kuat bahkan pada sistem tingkat rendah
1 komentar
Komentar Hacker News
object->ops->start(object)objek harus disebut dua kali: sekali untuk resolusi vtable, dan sekali lagi untuk mengoper objek ke implementasi fungsi Cfoo_lebih disukai karena lebih ringkas daripadathis->foo. Tentu saja, di C++ kita juga bisa menulis this secara eksplisitmystruct_dosmth(s);terasa kurang alami dibandings->dosmth();struct file_operationsberisi function pointer yang tidak menerima pointer this, sehingga sulit disebut benar-benar sebagai vtablething->vtable->foo(thing, ...), bisa ditulisfoo(thing, ...)