ดีไวซ์ไดรเวอร์ จาก 2.4 ถึง 2.6 : ตอนที่ 1 "Hello World\n"
จาก Linux Kernel 2.4 ถึง 2.6 มีการเปลี่ยนแปลงหลายอย่าง ทั้ง Kernel, System Calls รวมไปถึง Device Driver และการจัดการต่างๆ เอกสารชุดนี้จะอธิบายวิธีการแปลงดีไวซ์ไดรเวอร์จากเคอร์เนลเก่า (2.4) ไปยังเคอร์เนลใหม่ (2.6) เราจะสันนิษฐานว่าผู้อ่านมีความคุ้นเคยกับการเขียนดีไวซ์ไดรเวอร์อยู่บ้างแล้วระดับนึง..
โปรแกรมแรกของหลายๆคนคงหนีไม่พ้นโปรแกรม Hello World ใครๆก็ใช้โปรแกรมนี้เป็นแบบฝึกหัดแรก เราก็จะถือเก๋เริ่มด้วยโปรแกรม สวัสดีโลก เหมือนชาวโลกเค้าบ้าง จะเขียนกันแบบ kernel loadable module (อีกแบบก็ built-in คงรู้ความแตกต่างกันอยู่แล้ว)
มาดูโค้ดดีไวซ์ไดร์เวอร์สำหรับ kernel 2.4 กันก่อน:
ใน 2.4 เราใช้การประกาศคู่ฟังก์ชั่น init_module/cleanup_module แต่ใน 2.6 จะใช้การประกาศฟังก์ชั่นผ่าน module_init/module_exit ถึงตอนนี้ก็ยังอาจจะใช้คู่เดิมได้อยู่ แต่เราแนะนำให้เปลี่ยนชื่อใหม่แล้วประกาศผ่านฟังก์ชั่นชุดใหม่จะดีกว่า อ่อ เกือบลืม ฟังก์ชั่น module_init กับ module_exit ประกาศอยู่ใน <linux/init.h> ถ้าจะใช้ก็ต้อง include ด้วยเน้อ
เปลี่ยน ๒ สามจุด ตอนนี้หน้าตาของโปรแกรมสวัสดีโลกของเราก็เป็นแบบนี้:
ปล. เนื้อหาและความรู้จาก
โปรแกรมแรกของหลายๆคนคงหนีไม่พ้นโปรแกรม Hello World ใครๆก็ใช้โปรแกรมนี้เป็นแบบฝึกหัดแรก เราก็จะถือเก๋เริ่มด้วยโปรแกรม สวัสดีโลก เหมือนชาวโลกเค้าบ้าง จะเขียนกันแบบ kernel loadable module (อีกแบบก็ built-in คงรู้ความแตกต่างกันอยู่แล้ว)
มาดูโค้ดดีไวซ์ไดร์เวอร์สำหรับ kernel 2.4 กันก่อน:
#define MODULE #include <linux/module.h> #include <linux/kernel.h> int init_module(void) { printk(KERN_INFO "Hello World\n"); return 0; } void cleanup_module(void) { printk(KERN_INFO "Goodbye cruel world\n"); }โมดุลสวัสดีโลกง่ายๆนี้ อาจจะดูธรรมดา แต่จากรุ่นหนึ่งสู่รุ่นหนึ่ง จากยุคของ ๒.๔ ถึง ๒.๖ เราต้องแปลงโฉมโมดุลนี้ซะใหม่ เปลี่ยนกันตั้งแต่บรรทัดแรกเลย
#define MODULEไม่จำเป็นอีกแล้วสำหรับมาโคร MODULE ตัวนี้ เพราะใน ๒.๖ นั้น ใช้ระบบการ build kernel/module แบบใหม่ และมาโครนี้จะถูก define แล้วโดยอัติโนมัติ (เรื่อง ระบบ build kernel จะพูดถึงกันอีกที)
ใน 2.4 เราใช้การประกาศคู่ฟังก์ชั่น init_module/cleanup_module แต่ใน 2.6 จะใช้การประกาศฟังก์ชั่นผ่าน module_init/module_exit ถึงตอนนี้ก็ยังอาจจะใช้คู่เดิมได้อยู่ แต่เราแนะนำให้เปลี่ยนชื่อใหม่แล้วประกาศผ่านฟังก์ชั่นชุดใหม่จะดีกว่า อ่อ เกือบลืม ฟังก์ชั่น module_init กับ module_exit ประกาศอยู่ใน <linux/init.h> ถ้าจะใช้ก็ต้อง include ด้วยเน้อ
เปลี่ยน ๒ สามจุด ตอนนี้หน้าตาของโปรแกรมสวัสดีโลกของเราก็เป็นแบบนี้:
#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> static int hello_init(void) { printk(KERN_ALERT "Hello World\n"); return 0; } static void hello_exit(void) { printk(KERN_ALERT "Goodbye cruel world\n"); } module_init(hello_init); module_exit(hello_exit);
โมดุลของเราตอนนี้ก็พร้อมจะถูก compile แล้ว แต่เอาไว้ว่ากันต่อคราวหน้าดีกว่า.. อ่อ โมดุลสวัสดีโลกของเราตอนนี้ ถ้าถูกโหลดเข้าไปใน Kernel เรานอกจาก "Hello World\n" แล้ว ยังจะได้ message นี้ด้วย
hello: module license 'unspecified' taints kernel.ซึ่งจะว่าไปก็ไม่ซีเรียสอะไรมาก แค่บ่นๆว่าทำไมเอาโมดุลไลเซนส์น่าเกลียดมาทำให้ kernel เปรอะเปรื้อน (แปลแล้วน่าเกลียดแฮะ) ถ้าจะไม่ให้มีเมสเซสนี้ก็แค่ประกาศ
MODULE_LICENSE("Dual BSD/GPL");เรื่อง module license ก็ไม่ใช่เรื่องใหม่อะไร มีมานานแล้วแต่บางครั้งก็หลงลืมไม่ได้ใส่กัน มาตอนนี้แนะนำให้ใส่กันได้แล้ว และการประกาศไลเซนส์แบบนี้ยังจะช่วยให้เราสามารถเข้าไปเรียกใช้งาน GPL-only symbols ได้ด้วย (มีอะไรบ้างอย่าถาม แปลมา)
ปล. เนื้อหาและความรู้จาก
- ตำราคลาสสิคสำหรับนักเขียนลีนุกซ์ดีไวซ์ไดร์เวอร์ Linux Device Drivers, 2nd Edition
- Driver porting: hello world ในชุด Porting device drivers to the 2.6 kernel โดย Jonathan Corbet หนึ่งในผู้เขียนหนังสือเล่มข้างบน
0 Comments:
Post a Comment
<< Home