В чем разница между драйверами ядра и модулями ядра?

67

Когда я делаю lspci -kна своем Kubuntu с ядром 3.2.0-29, я вижу что-то вроде этого:

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, nouveau, nvidiafb.

Теперь мне стало интересно, в чем может быть разница между драйверами ядра и модулями ядра?

JohnnyFromBF
источник

Ответы:

78

Модуль ядра - это немного скомпилированного кода, который может быть вставлен в ядро ​​во время выполнения, например, с помощью insmodили modprobe.

Драйвер - это фрагмент кода, который запускается в ядре для связи с некоторым аппаратным устройством. Он "гонит" железо. Почти каждое устройство на вашем компьютере имеет связанный с ним драйвер. Большая часть работающего ядра - это код драйвера.

Драйвер может быть встроен статически в файл ядра на диске. Драйвер также может быть встроен как модуль ядра, чтобы его можно было динамически загрузить позже. (А потом может быть выгружен.)

Стандартная практика - создавать драйверы как модули ядра, где это возможно, а не связывать их статически с ядром, поскольку это дает большую гибкость. Однако есть веские причины не делать этого:

  • Иногда данный драйвер абсолютно необходим для загрузки системы. Это происходит не так часто, как вы можете себе представить, благодаря функции initrd .

  • Статически построенные драйверы могут быть именно тем, что вы хотите в статически ограниченной системе, такой как встроенная система . То есть, если вы заранее точно знаете, какие драйверы всегда будут нужны, и что это никогда не изменится, у вас есть веская причина не беспокоиться о динамических модулях ядра.

  • Если вы собираете ядро ​​статически и отключаете функцию динамической загрузки модулей в Linux, вы предотвращаете изменение кода ядра во время выполнения. Это обеспечивает дополнительную безопасность и стабильность за счет гибкости.

Не все модули ядра являются драйверами. Например, относительно недавняя функция ядра Linux заключается в том, что вы можете загрузить другой планировщик процессов . Другой пример состоит в том, что более сложные типы оборудования часто имеют несколько общих уровней, которые находятся между драйвером аппаратного обеспечения низкого уровня и пользовательским пространством, таким как драйвер USB HID , который реализует определенный элемент стека USB , независимый от базового оборудования.


Asides:

  1. Единственное исключение из этого широкого утверждения является чипом процессора, который не имеет «драйвера» как таковые . Ваш компьютер также может содержать оборудование, для которого у вас нет драйвера.

  2. Остальная часть кода в ядре ОС предоставляет общие сервисы, такие как управление памятью , IPC , планирование и т. Д. Эти сервисы могут в первую очередь обслуживать пользовательские приложения, как это было в предыдущих примерах, или они могут быть внутренними сервисами, используемыми драйверами или другими внутренними приложениями. инфраструктура ядра.

  3. Один /bootвход, загруженный в ОЗУ во время загрузки загрузчиком в начале процесса загрузки .

Уоррен Янг
источник
1
Модулями могут быть файловые системы, сетевые протоколы, функции брандмауэра и многое другое. Некоторое оборудование (например, карты Wi-Fi) требует стека модулей, некоторые предлагают общую инфраструктуру, в то время как другие обрабатывают само оборудование.
vonbrand
1
Это хороший общий план, но у меня был точно такой же вопрос, как и у ОП, потом наткнулся на этот ответ и все еще не знал, почему «используемый драйвер» отличается от «модулей». Напротив, ответ @Jim Paris правильный. From man lspci: "-k Показать драйверы ядра, обрабатывающие каждое устройство, а также модули ядра, способные его обрабатывать ." Вы можете прочитать это как: «Показать драйвер, который в данный момент / фактически обрабатывает устройство, а также все модули, которые могут / предназначены для его обработки ”.
Бинар
Если вы знаете Windows: модуль очень похож на DLL. В Unix модуль похож на общий объект, но модуль только для ядра. Динамически связанный модуль может содержать драйверы. Ядро может содержать статически связанные драйверы. Модуль отличается от DLL (или .so) тем, что ядро ​​предъявляет особые требования к динамической загрузке.
Робокат
18

Чтобы ответить на ваш конкретный вопрос о lspciвыводе, строка «драйвер ядра» указывает, какой драйвер в данный момент связан с картой, в данном случае проприетарным nvidiaдрайвером. В строке «модули ядра» перечислены все драйверы, о которых известно, что они могут быть привязаны к этой карте. Здесь, проприетарный драйвер показывает его другое имя, вероятно, из-за того, как был lspciнайден драйвер и его имя файла по сравнению с именем, закодированным в самом драйвере.

Джим Пэрис
источник
Спасибо - это помогло. Если бы я только выпустил man lspci- там написано именно то, что вы написали.
Бинар
5

Согласно этому хорошему уроку :

... одним типом модуля является драйвер устройства, который позволяет ядру получать доступ к оборудованию, подключенному к системе.

Итак, если мы попытаемся нарисовать дерево, у нас будет «Драйвер устройства», который наследуется от (расширяет) модуля и имеет более специфические характеристики, между которыми мы находим «доступ к оборудованию» ...

user1847726
источник
Это только частично правильно. Драйвер является объектом класса в иерархии (да, внутренний дизайн 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 initна dmesg.

Однако существуют модули ядра, которые не являются драйверами устройств, но на самом деле полезны, например, модули, которые предоставляют информацию об отладке / производительности ядра.

Драйверы устройств обычно также являются модулями ядра.

Пример чего-то, что является «драйвером устройства», генерировать немного сложнее, поскольку для его работы требуется аппаратное обеспечение, а описания аппаратного обеспечения, как правило, сложны.

Однако используя QEMU или другие эмуляторы, мы можем создавать программные модели из реального или упрощенного аппаратного обеспечения, что является отличным способом научиться общаться с аппаратным обеспечением. Вот простой пример минимального драйвера устройства PCI: https://github.com/cirosantilli/linux-kernel-module-cheat/blob/6788a577c394a2fc512d8f3df0806d84dc09f355/kernel_module/hello.c

Затем мы видим, что в x86 общение с оборудованием сводится к:

Эти операции, как правило, не могут быть выполнены из пользовательского пространства , как объяснено в разделе: В чем разница между пространством пользователя и пространством ядра? Однако есть некоторые исключения: https://stackoverflow.com/questions/7986260/linux-interrupt-handling-in-user-space .

Затем ядро ​​предлагает API более высокого уровня, чтобы сделать такое аппаратное взаимодействие более простым и переносимым:

  • request_irq обрабатывать прерывания
  • ioreadX и отображение памяти ввода-вывода
  • интерфейсы еще более высокого уровня для популярных протоколов, таких как PCI и USB
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
источник
0

Мой ответ пойдет с Джимом. Драйвер ядра - это программа (модуль ядра), предназначенная для управления частью аппаратного обеспечения. Вывод lspci говорит, что nvidia - это драйвер ядра, так как это loadedмодуль для устройства. Наряду с этим доступны другие доступные модули ядра.

Добавлю, что команды в linux для вывода списка и удаления драйверов есть lsmodи rmmodсоответственно. Что говорит список модулей и удалить модуль.

коробка красок
источник
0

Все Драйверы являются модулями. Не все модули являются драйверами.

Модули могут быть вставлены во время выполнения. Модули / Драйверы могут быть статически скомпилированы вместе с ядром.

Типичный модуль init имеет

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

Этот же модуль можно сделать драйвером

module_init(init_fn);
init_fn()
{
   device_register(&device);
   /* some code */
}
Prabagaran
источник
8
Драйверы не всегда являются модулями, их можно включить в основной образ ядра.
Жиль "ТАК ... перестать быть злым"
3
@Prabagaran: «Все драйверы являются модулями. Все модули не являются драйверами». Это противоречиво. С математической точки зрения вы говорите, что D -> M и M ->! D. Это позволяет D и! D.
Франческо Турко
2
Я думаю, что он имеет в виду «Все драйверы являются модулями. Не все модули являются драйверами».
Ренан
4
@Renan: Это было бы правильно, но если вы посмотрите историю изменений этого ответа, кто-то уже пытался исправить ошибку, и автор отменил ее. Обычно я просто редактировал бы, чтобы исправить ошибку и двигаться дальше, но в этом случае я сделал -1, потому что это просто неправильно и запутывает проблему.
Калеб
Как я помню (давно не дурачился), есть некоторые драйверы, которые нельзя создать как загружаемые модули. Кажется, я помню другие, которые можно обрабатывать только как модули.
vonbrand