การแบ่งชนิดของเคอร์เนล
โมโนลิทิก เคอร์เนล (Monolithic kernel) เป็นเคอร์เนลที่รวมการทำงานทุกส่วนไว้ด้วยกันทั้งหมด ทำให้การทำงานร่วมกันระหว่างส่วนต่างๆรวดเร็ว เพราะไม่มีโอเวอร์เฮดของการสื่อสารระหว่างส่วนต่างๆในข้อมูลที่ส่งให้กัน ทำให้การประมวลผลเร็ว แต่มีข้อเสียหลักคือเมื่อเคอร์เนลล่มจะทำให้ระบบทั้งหมดจะหยุดการทำงานทันที
ไมโครเคอร์เนล (Microkernel) เป็นเคอร์เนลที่แบ่งการทำงานในแต่ละส่วนออกจากกัน (อาจจะอยู่กันคนละเครื่อง) เช่น ส่วนของการสื่อสาร ส่วนของอุปกรณ์ ส่วนจัดการหน่วยความจำ และอื่นๆ ในทางแนวคิด ไมโครเคอร์เนลมีความเสถียรสูงเนื่องจากแบ่งการทำงานทุกส่วนออกจากกัน แต่ละส่วนจะมีความสามารถในการอยู่ได้ด้วยตัวเอง และสามารถทำงานสนับสนุนหรือทดแทนกันได้ เมื่อส่วนใดมีปัญหา ทำให้ไม่มีผลกระทบต่อกัน ข้อเสียคือไม่สามารถดึงประสิทธิภาพของระบบออกมาได้เต็มที่ เนื่องจากซีพียูต้องจัดการเรื่องโอเวอร์เฮดของการส่งข้อมูลหากันระหว่างส่วนต่างๆ ด้วย
ลินุกซ์เป็นระบบปฏิบัติการแบบโมโนลิทิก เคอร์เนล (Monolithic kernel) คือรวมการทำงานทุกส่วนอยู่ในไบนารี่เดียวกัน แต่รองรับการทำงานแบบโมดูลในการปรับเปลี่ยน/เพิ่มเติม ความสามารถในขณะทำงานได้
ลินุกซ์เคอร์เนลโมดูล
คือโค้ดส่วนเล็กๆที่สามารถโหลดเข้าไปในเคอร์เนลและถอดออกจากเคอร์เนลได้โดยที่ไม่จำเป็นต้องรีบูตระบบ จุดประสงค์เพื่อให้สามารถปรับเปลี่ยนความสามารถของเคอร์เนลได้ตามความต้องการ ซึ่งช่วยให้มีลินุกซ์เคอร์เนลความยืดหยุ่นในการทำงานมากขึ้น แม้ว่าจะเป็นโมโนลิทิกเคอร์เนล
ตัวอย่างเช่น หากเรามีระบบที่ไม่ต้องการให้ผู้ใช้งานสามารถแก้ไข้ข้อมูลที่อยู่บนแฟลซเมมโมรี่ เราอาจปรับแต่งให้ตัวแฟลซเมมโมรี่ไดร์เวอร์ทำได้แค่การอ่านข้อมูล แต่เนื่องจากผู้ผลิตก็ยังจำเป็นต้องใช้ฟังก์ชั่นการเขียนแฟลซเมมโมรี่ ในขั้นตอนการโปรแกรมเฟิรมแวร์ลงไปในตัวอุปกรณ์ กรณีนี้เราอาจต้องแยกแฟลซเมมโมรี่ไดร์เวอร์ ออกมาเป็นโมดูลภายนอก สองโมดูล คือโมดูลที่สามารถเขียนแฟลซได้ และโมดูลที่ทำได้เฉพาะอ่านแฟลซเมมโมรี่ เมื่อต้องการโปรแกรมเฟิรมแวร์ลงไปในตัวอุปกรณ์ จึงค่อยโหลดโมดูลที่สามารถเขียนแฟลซได้ ส่วนเฟิรมแวร์ที่ติดไปให้ผู้ใช้ก็จะมีแต่โมดูลที่ทำได้เฉพาะอ่านแฟลซเมมโมรี่ จากตัวอย่างนี้จะเห็นว่า การใช้ความสามารถของโมดูลมาช่วยปรับเปลี่ยนความสามารถของเคอร์เนล จะทำให้มีความสะดวกในทำงานขึ้นมาก
ประโยชน์ทางอ้อมอีกอย่างหนึ่งของการใช้ลินุกซ์เคอร์เนลโมดูล คือการนำมาใช้ในขั้นตอนการพัฒนาลินุกซ์ดีไวซ์ไดร์เวอร์ ซึ่งจะช่วยให้นักพัฒนาลดเวลาในการทดสอบโค้ดเนื่องจากไม่ต้องบูตระบบทุกครั้งเวลาที่จะทดสอบไดร์เวอร์ เพราะสามารถถอดไดร์เวอร์โมดูลเก่าแล้วโหลดโมดูลใหม่เพื่อทดสอบได้ทันที เมื่อได้โมดูลที่ทำงานได้สมบูรณ์แล้วจึงเปลี่ยนไปเป็นแบบรวมไว้ในตัวเคอร์เนลภายหลังได้
ขอบเขตของคำว่าเคอร์เนลโมดูลจะจำกัดอยู่ที่ความสามารถในการโหลดเข้าไปในเคอร์เนลและถอดออกจากเคอร์เนลได้เท่านั้น ไม่ได้หมายรวมถึงว่า ลินุกซ์ดีไวซ์ไดร์เวอร์คือโมดูล เนื่องจากว่าดีไวซ์ไดร์เวอร์สามารถเขียนทั้งในรูปแบบรวมเข้าไว้ด้วยกัน (built-in) และแบบโมดูล (**จริงๆ เกี่ยวกับเรื่องนี้แอดมินเองก็ไม่อยากฟันธงเท่าไหร่นัก เพราะเมื่อได้ลองรีวิวเคอร์เนลโค้ดไปเรื่อยๆ ก็จะพบว่ามีการเขียนคอมเม้นในโค้ดของโมดูลเกี่ยวกับไดร์เวอร์ไว้หลายจุด จนเหมือนกับว่ามันคือเรื่องเดียวกัน)
ในระบบที่ต้องการปกป้องทรัพย์สินทางปัญญาที่ไม่ต้องการให้แกะรอยการทำงานของเคอร์เนลได้ นักพัฒนาสามารถปิดความสามารถในการรองรับโมดูลภายนอกได้เพื่อป้องกันการใช้งานร่วมกับโมดูลที่ไม่รู้จักแหล่งที่มา เพราะว่าเมื่อโมดูลถูกโหลดเข้าไปในเคอร์เนลแล้ว จะสามารถเข้าถึงทรัพยากรทั้งหมดของระบบได้ ทำให้เสี่ยงต่อการเจาะระบบ
ตัวอย่างรูปแบบโค้ดของลินุกซ์เคอร์เนลโมดูล
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
/* emb.c - initial device driver, char device interface Copyright (C) 2017 www.embedded-maker.com <embeddedmaker@gmail.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include <linux/kernel.h> #include <linux/module.h> /* * module load/unload */ static int __init emb_init(void) { printk(KERN_INFO "embeddded-maker module loadded.\n"); return 0; } static void __exit emb_exit(void) { printk(KERN_INFO "embedded-maker module unloaded.\n"); } MODULE_AUTHOR("www.embedded-maker.com <embeddedmaker@gmail.com>"); MODULE_DESCRIPTION("Embeddded-maker example module"); MODULE_LICENSE("GPL"); module_init(emb_init); module_exit(emb_exit); |
อธิบายโค้ด
(emb.c: บรรทัด 25 – 31) เป็นฟังก์ชั่นแรกของโมดูล(initialization entry point) ที่จะถูกเรียกเมื่อ <1> โมดูลถูกโหลดเข้าไปในเคอร์เนล หรือ <2> ตอนที่เคอร์เนลรันฟังก์ชั่น do_initcalls() ในกรณีที่เป็นแบบ built-in
ในโค้ดตัวอย่างนี้แสดงเฉพาะการใช้ฟังก์ชั่น printk() พิมพ์ข้อความออกมาทางเคอร์เนลคอนโซลเท่านั้น แต่จุดประสงค์ของฟังก์ชั่นนี้จริงๆคือใช้สำหรับสร้างส่วนที่จำเป็นในการทำงานของโมดูล เช่นการลงทะเบียนกับเคอร์เนลเป็น อุปกรณ์แบบลำดับ (character device) หรือการสร้างแพลตฟอร์มดีไวซ์ (platform device) ก่อนจะไปสู่ขั้นตอนการตรวจสอบอุปกรณ์ (device probing)
ฟังก์ชั่นนี้จะถูกเรียกโดย มาโคร module_init() อีกทีหนึ่ง ทำให้ชื่อของฟังก์ชั่นสามารถเปลี่ยนได้ตามใจผู้พัฒนา
ฟังก์ชั่นที่ถูกเรียกโดยมาโคร module_init() นี้จำเป็นต้องคืนค่า 0 เท่านั้น หากคืนค่าอื่นที่ไม่ใช่ 0 เคอร์เนลจะตีความหมายว่าขั้นตอนเริ่มต้นทำไม่สำเร็จ และจะยกเลิกกระบวนการโหลดโมดูลนี้ ซึ่งเราสามารถใช้เงื่อนไขนี้ ทำให้โค้ดตัดสินใจได้ว่าโมดูลต้องถูกโหลดไปทำงานหรือไม่ หากไม่มีอุปกรณ์ตามที่กำหนดในระบบ
(emb.c: บรรทัด 33 – 36) เป็นฟังก์ชั่นสุดท้ายของโมดูล(exit entry point) ที่จะถูกเรียกเมื่อโมดูลถูกถอดจากเคอร์เนล และจะไม่ถูกเรียกให้ทำงาน ในกรณีที่เป็นถูกคอมไพล์เป็นแบบ built-in
(emb.c: บรรทัด 38) มาโคร MODULE_AUTHOR สำหรับเครดิตเกี่ยวกับผู้เขียนโมดูล โดยอาจมีหรือไม่มีที่อยู่อีเมล์ และสามารถประกาศชื่อผู้เขียนโมดูลได้มากกว่าหนึ่งคน
(emb.c: บรรทัด 39) มาโคร MODULE_DESCRIPTION เป็นคำอธิบายเกี่ยวกับหน้าที่โมดูล
(emb.c: บรรทัด 40) มาโคร MODULE_LICENSE เป็นส่วนประกาศชนิดของใบอนุญาต สำหรับเคอร์เนล รุ่น 4.x สามารถ รองรับชนิดของใบอนุญาต ได้ตามตารางด้านล่าง
ชนิดของใบอนุญาต | คำอธิบาย |
---|---|
GPL | GNU Public License v2 or later |
GPL v2 | GNU Public License v2 |
GPL and additional rights | GNU Public License v2 rights and more |
Dual BSD/GPL | GNU Public License v2 or BSD license choice |
Dual MIT/GPL | GNU Public License v2 or MIT license choice |
Dual MPL/GPL | GNU Public License v2 or Mozilla license choice |
Proprietary | Non free products |
ขอจบเพียงแค่นี้ก่อนนะครับ ตอนหน้าเราจะมาลองคอมไพล์โค้ดตั้งต้นของโมดูลจากตัวอย่างบทนี้ และทดสอบจริงบนบอร์ดราสเบอรี่พายกัน