ความแตกต่างระหว่างไดรเวอร์เคอร์เนลและโมดูลเคอร์เนลคืออะไร?


67

เมื่อฉันทำlspci -kบน Kubuntu ด้วยเคอร์เนล 3.2.0-29-generic ฉันสามารถเห็นสิ่งนี้:

01:00.0 VGA compatible controller: NVIDIA Corporation G86 [Quadro NVS 290] (rev a1)
    Subsystem: NVIDIA Corporation Device 0492
    Kernel driver in use: nvidia
    Kernel modules: nvidia_current, nouveau, nvidiafb

มีคนขับเคอร์เนลnvidiaและโมดูลเคอร์เนลnvidia_current, ,nouveaunvidiafb

ตอนนี้ฉันสงสัยว่าอะไรคือความแตกต่างระหว่างไดรเวอร์เคอร์เนลและโมดูลเคอร์เนล

คำตอบ:


78

โมดูลเคอร์เนลบิตของรหัสเรียบเรียงที่สามารถแทรกเข้าไปในเมล็ดที่ใช้เวลาเช่นกับหรือinsmodmodprobe

ไดรเวอร์คือรหัสเล็กน้อยที่ทำงานในเคอร์เนลเพื่อพูดคุยกับอุปกรณ์ฮาร์ดแวร์บางอย่าง มัน "ไดรฟ์" ฮาร์ดแวร์ ฮาร์ดแวร์ทุกบิตส่วนใหญ่ในคอมพิวเตอร์ของคุณมีไดรเวอร์ที่เกี่ยวข้อง kernel ส่วนใหญ่ของเคอร์เนลที่ใช้คือรหัสไดรเวอร์²

ไดรเวอร์อาจถูกสร้างขึ้นแบบคงที่ลงในไฟล์เคอร์เนลบนดิสก์ driver ไดรเวอร์อาจถูกสร้างขึ้นเป็นโมดูลเคอร์เนลเพื่อให้สามารถโหลดแบบไดนามิกในภายหลัง (และจากนั้นอาจยกเลิกการโหลด)

มาตรฐานการปฏิบัติคือการสร้างไดรเวอร์เป็นโมดูลเคอร์เนลที่เป็นไปได้มากกว่าที่จะเชื่อมโยงพวกเขาไปยังเคอร์เนลแบบคงที่เนื่องจากที่ให้ความยืดหยุ่นมากขึ้น อย่างไรก็ตามมีเหตุผลที่ดีที่ไม่ควรทำ:

  • บางครั้งไดรเวอร์ที่ให้มาจำเป็นอย่างยิ่งที่จะช่วยให้ระบบบูตขึ้น ที่ไม่ได้เกิดขึ้นบ่อยเท่าที่คุณอาจคิดเนื่องจากinitrdคุณลักษณะ

  • แบบคงที่คนขับรถที่สร้างขึ้นอาจจะเป็นสิ่งที่คุณต้องการในระบบที่มีการกำหนดขอบเขตแบบคงที่เช่นระบบฝังตัว กล่าวคือถ้าคุณรู้ล่วงหน้าว่าจะต้องใช้ไดรเวอร์ตัวใดเสมอและสิ่งนี้จะไม่เปลี่ยนแปลงคุณมีเหตุผลที่ดีที่จะไม่ยุ่งกับโมดูลเคอร์เนลแบบไดนามิก

  • หากคุณสร้างเคอร์เนลของคุณแบบสแตติกและปิดใช้งานคุณลักษณะการโหลดโมดูลแบบไดนามิกของ Linux คุณจะป้องกันการแก้ไขรันไทม์ของรหัสเคอร์เนล สิ่งนี้ให้ความปลอดภัยและความมั่นคงที่เพิ่มขึ้นโดยใช้ความยืดหยุ่น

ไม่ใช่ทุกโมดูลเคอร์เนลเป็นไดรเวอร์ ยกตัวอย่างเช่นคุณลักษณะล่าสุดค่อนข้างในลินุกซ์คือการที่คุณสามารถโหลดกำหนดการกระบวนการที่แตกต่างกัน อีกตัวอย่างหนึ่งคือประเภทฮาร์ดแวร์ที่ซับซ้อนมากขึ้นมักจะมีเลเยอร์ทั่วไปหลายเลเยอร์ที่อยู่ระหว่างไดรเวอร์ฮาร์ดแวร์ระดับต่ำและผู้ใช้เช่นไดรเวอร์ USB HIDซึ่งใช้องค์ประกอบเฉพาะของสแต็ก USBเป็นอิสระจากฮาร์ดแวร์พื้นฐาน


มานี:

  1. ข้อยกเว้นอย่างหนึ่งสำหรับคำสั่งทั่วไปนี้คือชิป CPU ซึ่งไม่มี "ไดรเวอร์" ต่อหนึ่งรายการ คอมพิวเตอร์ของคุณอาจมีฮาร์ดแวร์ที่คุณไม่มีไดรเวอร์

  2. ส่วนที่เหลือของรหัสในระบบปฏิบัติการเคอร์เนลให้บริการทั่วไปเช่นการจัดการหน่วยความจำ , IPC , การตั้งเวลา , ฯลฯ บริการเหล่านี้ส่วนใหญ่อาจจะทำหน้าที่userlandการใช้งานเช่นเดียวกับตัวอย่างที่เชื่อมโยงก่อนหน้านี้หรือพวกเขาอาจจะใช้บริการภายในโดยไดรเวอร์หรือโยกย้ายงานทั้งอื่น ๆ โครงสร้างพื้นฐานเคอร์เนล

  3. หนึ่งใน/boot, โหลดลงใน RAM ในเวลาบูตโดยบูตในช่วงต้นขั้นตอนการบู๊ต


1
โมดูลสามารถเป็นระบบไฟล์โปรโตคอลเครือข่ายฟังก์ชันไฟร์วอลล์และอีกมากมาย ฮาร์ดแวร์บางตัว (เช่นการ์ด WiFi) ต้องใช้โมดูลหลายตัวบางตัวเสนอโครงสร้างพื้นฐานทั่วไปขณะที่ฮาร์ดแวร์อื่น ๆ จัดการกับฮาร์ดแวร์เอง
vonbrand

1
นี่เป็นโครงร่างทั่วไปที่ดี แต่ฉันมีคำถามเดียวกันกับ OP จากนั้นก็เจอคำตอบนี้และยังไม่รู้ว่าทำไม "ไดรเวอร์ที่ใช้งาน" แตกต่างจาก "โมดูล" ในทางตรงกันข้ามคำตอบของ @Jim Paris นั้นถูกต้อง จากman lspci: "-k แสดงไดรเวอร์เคอร์เนลที่จัดการแต่ละอุปกรณ์และโมดูลเคอร์เนลที่สามารถจัดการได้" คุณสามารถอ่านได้ว่า: "แสดงไดรเวอร์ปัจจุบัน / จัดการอุปกรณ์จริง ๆและโมดูลทั้งหมดที่สามารถ / มีไว้เพื่อจัดการอุปกรณ์ "
Binarus

ถ้าคุณรู้ว่า windows: โมดูลคล้ายกับ DLL บนยูนิกซ์โมดูลจะคล้ายกับอ็อบเจ็กต์ที่แบ่งใช้ แต่โมดูลนั้นใช้สำหรับเคอร์เนลเท่านั้น โมดูลที่ลิงก์แบบไดนามิกสามารถมีไดรเวอร์ได้ เคอร์เนลสามารถมีไดรเวอร์ที่ลิงก์แบบสแตติก โมดูลแตกต่างจาก DLL (หรือ. so) เนื่องจากเคอร์เนลมีข้อกำหนดเฉพาะสำหรับวิธีการโหลดสิ่งต่าง ๆ แบบไดนามิก
robocat

18

เพื่อตอบคำถามเฉพาะของคุณเกี่ยวกับlspciผลลัพธ์บรรทัด "เคอร์เนลไดรเวอร์" หมายถึงไดรเวอร์ใดที่ถูกผูกไว้กับการ์ดในกรณีนี้nvidiaไดรเวอร์ที่เป็นกรรมสิทธิ์ บรรทัด "โมดูลเคอร์เนล" แสดงรายการไดรเวอร์ทั้งหมดที่ทราบว่าสามารถเชื่อมโยงกับการ์ดนี้ได้ ที่นี่ไดรเวอร์ที่เป็นกรรมสิทธิ์จะแสดงชื่อที่แตกต่างกันอาจเป็นเพราะวิธีการที่lspciพบว่าไดรเวอร์และชื่อไฟล์กับชื่อที่เข้ารหัสลงในไดร์เวอร์เอง


ขอบคุณ - ที่ช่วย ถ้าฉันเพิ่งออกman lspci- มันบอกว่าสิ่งที่คุณเขียน
Binarus

5

ตามแบบฝึกหัดที่ดีนี้:

... โมดูลประเภทหนึ่งคือไดรเวอร์อุปกรณ์ซึ่งช่วยให้เคอร์เนลเข้าถึงฮาร์ดแวร์ที่เชื่อมต่อกับระบบ

ดังนั้นถ้าเราพยายามที่จะวาดต้นไม้เราจะมี "Device driver" ซึ่งสืบทอดมาจาก (ขยาย) โมดูลและที่มีลักษณะเฉพาะมากขึ้นระหว่างที่เราพบ "การเข้าถึงฮาร์ดแวร์" ...


สิ่งนี้ถูกต้องเพียงบางส่วนเท่านั้น ไดรเวอร์เป็นวัตถุของคลาสในลำดับชั้น (ใช่การออกแบบภายในของ Linux เป็นระบบปฏิบัติการปัจจุบันส่วนใหญ่เป็นแบบวัตถุ) แต่ไดรเวอร์ดังกล่าวอาจเป็นโมดูล (โหลดได้ที่รันไทม์) หรือรวบรวมไว้ในเคอร์เนล ไม่มีความแตกต่าง (หรือน้อยมาก) ระหว่างทางเลือกคือรหัสที่ชาญฉลาด
vonbrand

4

โมดูลเคอร์เนลอาจไม่ได้เป็นไดรเวอร์อุปกรณ์เลย

"โปรแกรมควบคุมเคอร์เนล" ไม่ใช่คำที่กำหนดไว้อย่างชัดเจน แต่ลองมาดูกัน

นี่คือเคอร์เนลโมดูลที่ไม่ได้ขับฮาร์ดแวร์ใด ๆ และดังนั้นจึงไม่สามารถพิจารณาได้อย่างสมเหตุสมผล "ไดรเวอร์อุปกรณ์":

#include <linux/module.h>
#include <linux/kernel.h>

MODULE_LICENSE("GPL");

static int myinit(void)
{
    printk(KERN_INFO "hello init\n");
    return 0;
}

static void myexit(void)
{
    printk(KERN_INFO "hello exit\n");
}

module_init(myinit)
module_exit(myexit)

หลังจากสร้างแล้วคุณสามารถใช้กับ:

insmod hello.ko

และก็พิมพ์ไปhello initdmesg

อย่างไรก็ตามมีโมดูลเคอร์เนลที่ไม่ใช่ไดรเวอร์อุปกรณ์ แต่มีประโยชน์จริงเช่นโมดูลที่เปิดเผยข้อมูลการดีบักเคอร์เนล / ประสิทธิภาพ

ไดรเวอร์อุปกรณ์มักจะเป็นโมดูลเคอร์เนล

ตัวอย่างของสิ่งที่เป็น "ไดรเวอร์อุปกรณ์" นั้นค่อนข้างยากในการสร้างเนื่องจากต้องใช้ฮาร์ดแวร์ในการขับเคลื่อนและคำอธิบายฮาร์ดแวร์มักจะซับซ้อน

อย่างไรก็ตามการใช้ QEMU หรืออีมูเลเตอร์อื่น ๆ เราสามารถสร้างแบบจำลองซอฟต์แวร์ของฮาร์ดแวร์จริงหรือแบบง่ายซึ่งเป็นวิธีที่ดีในการเรียนรู้วิธีพูดคุยกับฮาร์ดแวร์ นี่คือตัวอย่างง่ายๆของไดร์เวอร์อุปกรณ์ PCI ขั้นต่ำ: https://github.com/cirosantilli/linux-kernel-module-cheat/blob/6788a577c394a2fc512d8f3df0806d84dc09f355/kernel_module/hello.c

จากนั้นเราจะเห็นว่าใน x86 การพูดคุยกับฮาร์ดแวร์นั้นลงไปที่:

การดำเนินการเหล่านั้นไม่สามารถทำได้โดยทั่วไปจาก userland ดังที่อธิบายไว้ที่: พื้นที่ผู้ใช้กับพื้นที่เคอร์เนลแตกต่างกันอย่างไร มี แต่ข้อยกเว้นบางประการ: https://stackoverflow.com/questions/7986260/linux-interrupt-handling-in-user-space

เคอร์เนลเสนอ APIs ระดับสูงกว่าเพื่อให้การโต้ตอบกับฮาร์ดแวร์ง่ายและสะดวกยิ่งขึ้น:

  • request_irq เพื่อจัดการขัดจังหวะ
  • ioreadX และการแมปหน่วยความจำ IO
  • อินเตอร์เฟสระดับสูงขึ้นสำหรับโปรโตคอลยอดนิยมเช่น PCI และ USB

0

คำตอบของฉันจะไปกับจิม เคอร์เนลไดรเวอร์คือโปรแกรม (โมดูลเคอร์เนล) ที่ออกแบบมาเพื่อขับชิ้นส่วนของฮาร์ดแวร์ เอาต์พุต lspci กล่าวว่า nvidia เป็นไดรเวอร์เคอร์เนลเนื่องจากเป็นloadedโมดูลสำหรับอุปกรณ์ พร้อมกับมันมาโมดูลเคอร์เนลอื่น ๆ ที่มีอยู่

ฉันจะเพิ่มคำสั่งที่อยู่ในลินุกซ์ที่จะแสดงรายการและลบไดรเวอร์lsmodและrmmodตามลำดับ ซึ่งกล่าวว่ารายการโมดูลและลบโมดูล


0

ไดรเวอร์ทั้งหมดเป็นโมดูล ไม่ใช่โมดูลทั้งหมดที่เป็นไดรเวอร์

สามารถแทรกโมดูลที่รันไทม์ Modules / Drivers สามารถรวบรวมแบบสแตติกพร้อมกับเคอร์เนลได้เช่นกัน

init โมดูลทั่วไปมี

module_init(init_fn);
init_fn()
{
   /* some code */
}

โมดูลเดียวกันสามารถทำให้ไดรเวอร์

module_init(init_fn);
init_fn()
{
   device_register(&device);
   /* some code */
}

8
ไดรเวอร์ไม่ได้เป็นโมดูลเสมอไปสามารถรวมอยู่ในอิมเมจเคอร์เนลหลักได้
Gilles

3
@Prabagaran: "ไดรเวอร์ทั้งหมดเป็นโมดูลโมดูลทั้งหมดไม่ใช่ไดรเวอร์" นี่คือความขัดแย้ง ในแง่คณิตศาสตร์สิ่งที่คุณพูดคือ D -> M และ M ->! D สิ่งนี้อนุญาตสำหรับ D และ! D
Francesco Turco

2
ฉันคิดว่าเขาหมายถึง "ไดรเวอร์ทั้งหมดเป็นโมดูลไม่ใช่โมดูลทั้งหมดเป็นไดรเวอร์"
Renan

4
@ Renan: นั่นจะถูกต้อง แต่ถ้าคุณดูที่ประวัติการแก้ไขสำหรับคำตอบนี้มีคนพยายามแก้ไขข้อผิดพลาดแล้วและผู้เขียนกลับมาใช้อีก โดยปกติฉันจะแก้ไขเพื่อแก้ไขข้อผิดพลาดและดำเนินการต่อ แต่ในกรณีนี้ฉันเคยได้รับ -1 เนื่องจากมันผิดและสับสน
คาเลบ

อย่างที่ฉันจำได้ (ยังไม่หลงกลซักพัก) มีไดรเวอร์บางตัวที่ไม่สามารถสร้างเป็นโมดูลที่โหลดได้ ฉันดูเหมือนจะจำคนอื่นซึ่งสามารถจัดการได้เป็นโมดูลเท่านั้น
vonbrand
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.