Kernel unix tradisional memiliki satu kunci, yang dipegang oleh sebuah utas saat kode kernel sedang berjalan. Oleh karena itu, tidak ada kode kernel lain yang dapat mengganggu utas tersebut.
Hal ini membuat perancangan kernel menjadi lebih mudah, karena Anda mengetahui bahwa sementara satu thread menggunakan sumber daya kernel, tidak ada thread lain yang menggunakan sumber daya tersebut. Oleh karena itu utas yang berbeda tidak dapat mengacaukan pekerjaan satu sama lain.
Dalam sistem prosesor tunggal, hal ini tidak menyebabkan terlalu banyak masalah.
Namun dalam sistem multiprosesor, Anda dapat mengalami situasi di mana beberapa utas pada prosesor atau inti yang berbeda semuanya ingin menjalankan kode kernel secara bersamaan. Artinya, bergantung pada jenis beban kerja, Anda dapat memiliki banyak prosesor, tetapi semuanya menghabiskan sebagian besar waktunya untuk menunggu satu sama lain.
Di Linux 2.6, sumber daya kernel dibagi menjadi unit-unit yang jauh lebih kecil, dilindungi oleh kunci individu, dan kode kernel ditinjau untuk memastikan bahwa kunci hanya ditahan saat sumber daya yang sesuai sedang digunakan. Jadi sekarang prosesor yang berbeda hanya perlu menunggu satu sama lain jika ingin mengakses sumber daya yang sama (misalnya sumber daya perangkat keras).
Sebelum kernel Linux versi 2.5.4, Kernel Linux tidak preemptive yang berarti proses yang berjalan dalam mode kernel tidak dapat dipindahkan dari prosesor sampai proses itu sendiri meninggalkan prosesor atau mulai menunggu beberapa operasi input output selesai.
Umumnya proses dalam mode pengguna dapat masuk ke mode kernel menggunakan panggilan sistem. Sebelumnya ketika kernel bersifat non-preemptive, proses dengan prioritas lebih rendah dapat memprioritaskan membalikkan proses dengan prioritas lebih tinggi dengan menolak aksesnya ke prosesor dengan berulang kali memanggil panggilan sistem dan tetap dalam mode kernel. Bahkan jika timelice proses berprioritas lebih rendah kedaluwarsa, ia akan terus berjalan hingga menyelesaikan pekerjaannya di kernel atau secara sukarela melepaskan kendali. Jika proses berprioritas lebih tinggi yang menunggu untuk dijalankan adalah editor teks tempat pengguna mengetik atau pemutar MP3 siap mengisi ulang buffer audionya, hasilnya adalah kinerja interaktif yang buruk. Kernel non-preemptive dengan cara ini merupakan kelemahan utama pada saat itu.
Bayangkan tampilan sederhana dari preemptive multi-tasking. Kami memiliki dua tugas pengguna, keduanya berjalan sepanjang waktu tanpa menggunakan I/O atau melakukan panggilan kernel. Kedua tugas tersebut tidak harus melakukan sesuatu yang khusus untuk dapat berjalan di sistem operasi multi-tasking. Kernel, biasanya berdasarkan interupsi pengatur waktu, hanya memutuskan bahwa sudah waktunya satu tugas berhenti untuk membiarkan tugas lain berjalan. Tugas yang dipermasalahkan sama sekali tidak menyadari bahwa sesuatu telah terjadi.
Namun, sebagian besar tugas terkadang membuat permintaan kernel melalui syscalls. Saat ini terjadi, konteks pengguna yang sama akan ada, tetapi CPU menjalankan kode kernel atas nama tugas tersebut.
Kernel Linux yang lebih lama tidak akan pernah mengizinkan preemption tugas saat sedang sibuk menjalankan kode kernel. (Perhatikan bahwa operasi I/O selalu menjadwal ulang secara sukarela. Saya berbicara tentang kasus di mana kode kernel memiliki beberapa operasi intensif CPU seperti menyortir daftar.)
Jika sistem mengizinkan tugas itu untuk didahului ketika sedang menjalankan kode kernel, maka kita memiliki apa yang disebut "kernel preemptive." Sistem seperti itu kebal terhadap penundaan tak terduga yang dapat ditemui selama syscall, sehingga mungkin lebih cocok untuk tugas tersemat atau tugas real-time.
Misalnya, jika pada CPU tertentu ada dua tugas yang tersedia, dan salah satunya membutuhkan syscall yang membutuhkan waktu 5 md untuk diselesaikan, dan yang lainnya adalah aplikasi pemutar MP3 yang perlu memberi makan pipa audio setiap 2 md, Anda mungkin mendengar audio gagap.
Argumen yang menentang preemption adalah bahwa semua kode kernel yang mungkin dipanggil dalam konteks tugas harus dapat bertahan dari preemption-- ada banyak kode driver perangkat yang buruk, misalnya, yang mungkin lebih baik jika selalu dapat menyelesaikan operasi sebelum mengizinkan beberapa tugas lain untuk dijalankan pada prosesor itu. (Dengan sistem multi-prosesor aturan daripada pengecualian hari ini, semua kode kernel harus masuk kembali, sehingga argumen itu tidak relevan hari ini.) Selain itu, jika tujuan yang sama dapat dipenuhi dengan meningkatkan syscalls dengan buruk latensi, mungkin preemption tidak diperlukan.
Kompromi adalah CONFIG_PRREEMPT_VOLUNTARY, yang memungkinkan peralihan tugas pada titik-titik tertentu di dalam kernel, tetapi tidak di semua tempat. Jika hanya ada sedikit tempat di mana kode kernel mungkin macet, ini adalah cara yang murah untuk mengurangi latensi sekaligus menjaga agar kompleksitas tetap dapat dikelola.
Preemption memungkinkan kernel untuk memberikan KESAN paralelisme:Anda hanya memiliki satu prosesor (katakanlah satu dekade yang lalu), tetapi Anda merasa semua proses Anda berjalan secara bersamaan. Itu karena kernel mendahului (yaitu, mengambil eksekusi dari) eksekusi dari satu proses untuk memberikannya ke proses berikutnya (mungkin sesuai dengan prioritasnya).
EDIT Bukan kernel preemptive menunggu proses untuk memberikan kembali tangan (yaitu, selama syscalls), jadi jika proses Anda menghitung banyak data dan tidak memanggil yield
jenis apa pun fungsi, proses lain tidak akan dapat mengeksekusi untuk mengeksekusi panggilan mereka. Sistem seperti itu dikatakan kooperatif karena mereka meminta kerja sama proses untuk memastikan kesetaraan waktu eksekusi
EDIT 2 Tujuan utama preemption adalah untuk meningkatkan reaktivitas sistem di antara banyak tugas, jadi itu bagus untuk pengguna akhir, sedangkan di sisi lain, server ingin mencapai througput tertinggi, jadi mereka tidak membutuhkannya:(dari konfigurasi kernel Linux)
- Kernel yang dapat diakhiri (desktop latensi rendah)
- Preemption kernel sukarela (desktop)
- Tidak ada preemption paksa (server)