Драйвер Linux для устройства.
Многие новички интересуются как установить драйвер для железяки в Linux.
То есть проводят аналогию с MS Windows, в которой для оборудования требовались многочисленные Далее-Далее в дистрибутивах драйверов.
Дело в том, что в мире Windows принято устанавливать драйвера от производителя железяки и это кажется естественным и разумным. Но в мире Linux, исторически сложилась по другому приципу модель «драйверов».
Но сначала напомню, а что же такое драйвер.
— это программа (некий программный код), который «обслуживает» железяку и служит «прослойкой» между железякой и операционной системой.
Эта модель эффективна, так как операционной системе не нужно знать, как общаться с миллионами устройств по всему миру. Операционная система будет общаться с драйвером по согласованным правилам, а уже драйвер будет общаться с железякой, для которой он и был написан.
А теперь историческая сводка, почему в Линуксе чуть другая система работы с драйверами.
Вы думаете, что когда Линукс делал свои первые шаги, все производители своих железяк бросились писать драйвера для Линукс? Нет. Этого не случилось. Многие не верили в будущий успех Linux на рынке Desktop систем и прямо заявляли, что не станут тратить время своих программистов на написание кода драйвера под Linux, который на рынке занимал маленький процент.
Поэтому драйвера писали энтузиасты, которые хотели видеть работающей в Линуксе ту или иную железяку. Иногда фирмы всё таки помогали так или иначе энтузиастам. Например, публиковали спецификации на свои устройства, чтобы программистам было проще понять логику работы железяки и не мучатся со сложной «обратной разработкой» (reverse engineering).
С ростом популярности Линукс, многие фирмы даже стали выделяли часть сотрудников, которые так или иначе занимались вопросом работоспособности устройства в Линуксе.
Но факт есть факт, исторически так получилось, что открытое сообщество, работающее над ядром линукс во главе с Линусом Торвальдсом, включало после проверки код драйвера в ядро linux. Так как устройствами в системе линукс занимается именно его ядро. То есть, постепенно всё больше и больше писалось драйверов и все они в своё время были включены в ядро. Поэтому, чем новее используемое вами ядро, тем выше шанс, что железяка «запустится».
Раньше традиционно все драйвера, а точнее их код, «размещался» в ядре. Позднее код драйверов стали выносить в отдельные «модули ядра» и загружать в основное ядро с помощью специального механизма.
Любой спросит, а можно ли драйвера устройства написанные для MS Windows, как-нибудь «прикрутить» в Linux. Проведу вам аналогию. Если операционную систему сравнить с «матерью», то у «мамы Windows» свои дети-программы, а следовательно и дети-драйвера. У «мамы Linux» свои.
Есть проекты типа NDISwrapper, которые пытаются использовать не родной код драйвера. В случае с NDISwrapper — это попытка использовать драйверы беспроводных устройств Wi-Fi, предназначенные для операционной системы Microsoft Windows в операционной системе Linux.
Но вы должны понимать, это не просто и лучший вариант всё таки родной драйвер.
Дак как же «поставить драйвер в Linux»?
Самое лучшее — проверить штатными средствами вашей системы, что определилось и что уже работает сразу «искаропки». Помните, что 99-ю процентами устройств в линуксе занимается ядро линукс.
В Ubuntu есть Менеджер драйверов (Драйверы Устройств), которые покажет те устройства, для которых есть проприетарные (закрытые) драйвера от производителя. Если производители не закрывали бы коды своих драйверов, как они делают это в MS Windows, то у вас не было бы никаких проблем и всё было оформлено заранее в виде соответствующих модулей ядра.
Не нужно ничего устанавливать вручную, если не понимаете, что делаете. Это чревато тем, что при вашем обновлении новыми ядрами — 99% что ваш вручную установленный драйвер «слетит». Новое ядро не будет уведомлено о ваших вручную сделанных изменениях-костылях и многое «рухнет». Например, вручную установленный непонятно откуда взятый драйвер видеокарты при обновлении ядра может «слететь» и следующая загрузка в ваше графическое окружение может закончиться неудачно.
Для искоренения этой ситуации во многих дистрибутивах линукс используется система DKMS, которая при выходе новых ядер перекомпилирует код драйверов.
Утомил?
Кратко! Обновляйтесь и не используйте старые версии вашего дистрибутива. Одно дело использовать стабильные долгоподдерживаемые релизы Ubuntu LTS, а другое дело просто сидеть на старом релизе, боясь обновлений.
Помните! Новее ядро — выше шанс, что железяка заработает.
При прочтении каких-либо советов из Интернета — будьте предельно аккуратны! Наши друзья это — репозитория и/или deb пакеты.
Не нужны всякие make install в современных системах Linux, основанных на идеи пакетного менеджмента, в таких как Ubuntu Linux.
Похожие материалы:
Установка программ в Ubuntu
Репозитории Ubuntu
Делаем отчёт по оборудованию в MS Windows — получаем результат о поддержке Линуксом Linux HCL : поддерживаемое оборудование
Источник
Где скачать драйвера для линукс?
Где скачать драйвера для линукс? Такой вопрос возникает у всех, кто переходит с Windows на Linux, ведь там дополнительные драйвера всегда приходилось где-то искать. Linux не загружает некоторые драйверы автоматически, потому что они представляют собой патентованное (proprietary) программное обеспечение, которое не подлежит свободному распространению. Патентованные драйвера для линукс предоставляют открыто исходный код и, следовательно, не проходят полной проверки Linux-сообществом.
Иногда у компаний есть законные причины скрывать исходный код — например, них есть лицензия на применение фрагмента кода, предоставленная другой компанией. При этом права на раскрытие этого исходного кода у компании отсутствуют, но патентованные драйверы, которые вы можете загружать, применяя процедуру, описанную в данном разделе, были проверены командой Linux, поэтому вы можете считать их достаточно безопасными.
Таким образом, если вы установили Linux как единственную операционную систему или как часть системы с двумя или несколькими ОС, у вас есть возможность установить для вашего оборудования патентованные драйверы. Их нужно загрузить с Web-сайтов разработчиков, поэтому ваша система должна быть подключена к Интернету. С интернета можно также загрузить 1с, жалко 1С не работает напрямую в Linux.
Если вы запускаете Linux прямо с DVD-носителя, вы не сможете выбирать разрешения кроме тех, которые отображаются в окне Параметры монитора (Display Preferences). Поэтому, если вы все еще не готовы выполнить полную установку Linux, я советую либо применить программу Wubi для установки Linux рядом с ОС Windows, либо установить Linux на виртуальной машине VirtualBox. В любом из этих случаев вы сохраните на компьютере свою исходную операционную систему.
Чтобы выяснить, есть ли какие-нибудь подходящие драйверы на вашем компьютере, выберите из меню команды Система | Администрирование | Драйверы устройств (System | Administration | Hardware Drivers), и вы увидите окно, выглядящее примерно так.
В нем будут перечислены все патентованные драйверы, имеющиеся на вашем компьютере. В системе, которую я использовал для получения дополнительных функций и более широкого набора разрешений экрана, можно подключить некоторые графические драйверы NVIDIA.
Начиная с версии Ubuntu 10.04, самые свежие Linux драйверы приводятся с пометкой текущей версии, что облегчает выбор наилучшего варианта. Если вы увидите в этом окне какие-нибудь драйверы, можно попытаться задействовать один из них, выделив его и щелкнув мышью по кнопке Активировать (Activate).
При этом система запрашивает ваш пароль Linux, после чего загружает и устанавливает выбранные вами драйверы. После завершения установки следует перезагрузить Linux, чтобы внесенные изменения вступили в силу. Обычно после перезагрузки вы увидите, что список допустимых экранных разрешений пополнился.
Если есть несколько драйверов, можно испытать их по очереди, определив, какой из них лучше подходит для вашего монитора. Сделать это можно, проверив три варианта: Без эффектов: (No extra features), Стандарт: (Normal) и Экстра: (Extra), которые можно выбрать с помощью последовательности Система | Параметры | Внешний вид | Визуальные эффекты (System | Preferences | Appearance | Visual Effects).
После установки патентованного драйвера вам, возможно, будет предложено использовать утилиту настройки разрешений от производителя патентованного драйвера. Если вы выберете кнопку Нет (No), то на экране появится стандартное окно настройки экрана, которое может обеспечить нужные вам разрешения, но может их и не обеспечить. Если же вы дадите утвердительный ответ, нажав кнопку Да (Yes), то на экране появится нестандартное окно.
Поскольку существует множество патентованных драйверов, то, начиная с этого момента, вы остаетесь с ними «один на один», так как их подробное описание не включено в статью. Тем не менее вы, как правило, найдете интуитивно понятные программные средства, легкие в применении и сравнимые (если не более многофункциональные) со стандартными средствами Linux.
Вот так вы можете установить Linux драйверы (патентованные) в свою систему. Я это делал уже не раз, и хотя не всегда всё получалось, но это дало бесценный опыт.
Источник
Пишем свой драйвер под Linux
Хочу признаться сразу, что я вас отчасти обманул, ибо драйвер, если верить википедии — это компьютерная программа, с помощью которой другая программа (обычно операционная система) получает доступ к аппаратному обеспечению некоторого устройства. А сегодня мы создадим некую заготовку для драйвера, т.к. на самом деле ни с каким железом мы работать не будем. Эту полезную функциональность вы сможете добавить сами, если пожелаете.
То, что мы сегодня создадим, корректнее будет назвать LKM (Linux Kernel Module или загрузочный модуль ядра). Стоит сказать, что драйвер – это одна из разновидностей LKM.
Писать модуль мы будем под ядра линейки 2.6. LKM для 2.6 отличается от 2.4. Я не буду останавливаться на различиях, ибо это не входит в рамки поста.
Мы создадим символьное устройство /dev/test, которое будет обрабатываться нашим модулем. Хочу сразу оговориться, что размещать символьное устройство не обязательно в каталоге /dev, просто это является частью «древнего магического ритуала».
Немного теории
Если кратко, то LKM – это объект, который содержит код для расширения возможностей уже запущенного ядра Linux. Т.е. работает он в пространстве ядра, а не пользователя. Так что не стоит экспериментировать на рабочем сервере. В случае ошибки, закравшейся в модуль, получите kernel panic. Будем считать, что я вас предупредил.
Модуль ядра должен иметь как минимум 2 функции: функцию инициализации и функцию выхода. Первая вызывается во время загрузки модуля в пространство ядра, а вторая, соответственно, при выгрузке его. Эти функции задаются с помощью макроопределений: module_init и module_exit.
Стоит сказать несколько слов о функции printk(). Основное назначение этой функции — реализация механизма регистрации событий и предупреждений. Иными словами эта функция для записи в лог ядра некой информации.
Т.к. драйвер работает в пространстве ядра, то он отграничен от адресного пространства пользователя. А нам хотелось бы иметь возможность вернуть некий результат. Для этого используется функция put_user(). Она как раз и занимается тем, что перекидывает данные из пространства ядра в пользовательское.
Хочу ещё сказать пару слов о символьных устройствах.
Выполните команду ls -l /dev/sda* . Вы увидите что-то вроде:
brw-rw—- 1 root disk 8, 0 2010-10-11 10:23 /dev/sda
brw-rw—- 1 root disk 8, 1 2010-10-11 10:23 /dev/sda1
brw-rw—- 1 root disk 8, 2 2010-10-11 10:23 /dev/sda2
brw-rw—- 1 root disk 8, 5 2010-10-11 10:23 /dev/sda5
Между словом «disk» и датой есть два числа разделённых запятой. Первое число называют старшим номером устройства. Старший номер указывает на то, какой драйвер используется для обслуживания данного устройства. Каждый драйвер имеет свой уникальный старший номер.
Файлы устройства создаются с помощью команты mknod, например: mknod /dev/test c 12 . Этой командой мы создадим устройство /dev/test и укажем для него старший номер (12).
Я не буду сильно углубляться в теорию, т.к. кому интересно – тот сможет сам почитать про это подробнее. Я дам ссылку в конце.
Прежде чем начать
Нужно знать несколько «волшебных» команд:
- insmod – добавить модуль в ядро
- rmmod – соответственно, удалить
- lsmod – вывести список текущих модулей
- modinfo – вывести информацию о модуле
Для компиляции модуля нам потребуются заголовки текущего ядра.
В debian/ubutnu их можно легко поставить так (к примеру для 2.6.26-2-686):
apt-get install linux-headers-2.6.26-2-686
Либо собрать пакет для вашего текущего ядра самим: fakeroot make-kpkg kernel_headers
Исходник
#include
/* Для printk() и т.д. */
#include/* Эта частичка древней магии, которая оживляет модули */
#include/* Определения макросов */
#include#include /* put_user */
// Ниже мы задаём информацию о модуле, которую можно будет увидеть с помощью Modinfo
MODULE_LICENSE( «GPL» );
MODULE_AUTHOR( «Alex Petrov
» );
MODULE_DESCRIPTION( «My nice module» );
MODULE_SUPPORTED_DEVICE( «test» ); /* /dev/testdevice */
#define SUCCESS 0
#define DEVICE_NAME «test» /* Имя нашего устройства */
// Поддерживаемые нашим устройством операции
static int device_open( struct inode *, struct file * );
static int device_release( struct inode *, struct file * );
static ssize_t device_read( struct file *, char *, size_t, loff_t * );
static ssize_t device_write( struct file *, const char *, size_t, loff_t * );
// Глобальные переменные, объявлены как static, воизбежание конфликтов имен.
static int major_number; /* Старший номер устройства нашего драйвера */
static int is_device_open = 0; /* Используется ли девайс ? */
static char text[ 5 ] = «test\n» ; /* Текст, который мы будет отдавать при обращении к нашему устройству */
static char * text_ptr = text; /* Указатель на текущую позицию в тексте */
// Прописываем обработчики операций на устройством
static struct file_operations fops =
<
.read = device_read,
.write = device_write,
.open = device_open,
.release = device_release
>;
// Функция загрузки модуля. Входная точка. Можем считать что это наш main()
static int __init test_init( void )
<
printk( KERN_ALERT «TEST driver loaded!\n» );
// Регистрируем устройсво и получаем старший номер устройства
major_number = register_chrdev( 0, DEVICE_NAME, &fops );
if ( major_number «Registering the character device failed with %d\n» , major_number );
return major_number;
>
// Сообщаем присвоенный нам старший номер устройства
printk( «Test module is loaded!\n» );
printk( «Please, create a dev file with ‘mknod /dev/test c %d 0’.\n» , major_number );
// Функция выгрузки модуля
static void __exit test_exit( void )
<
// Освобождаем устройство
unregister_chrdev( major_number, DEVICE_NAME );
printk( KERN_ALERT «Test module is unloaded!\n» );
>
// Указываем наши функции загрузки и выгрузки
module_init( test_init );
module_exit( test_exit );
static int device_open( struct inode *inode, struct file *file )
<
text_ptr = text;
if ( is_device_open )
return -EBUSY;
static int device_release( struct inode *inode, struct file *file )
<
is_device_open—;
return SUCCESS;
>
device_write( struct file *filp, const char *buff, size_t len, loff_t * off )
<
printk( «Sorry, this operation isn’t supported.\n» );
return -EINVAL;
>
static ssize_t device_read( struct file *filp, /* include/linux/fs.h */
char *buffer, /* buffer */
size_t length, /* buffer length */
loff_t * offset )
<
int byte_read = 0;
if ( *text_ptr == 0 )
return 0;
return byte_read;
>
* This source code was highlighted with Source Code Highlighter .
Сборка модуля
Ну а теперь можем написать небольшой Makefile:
obj-m += test.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
И проверить его работоспособность:
root@joker:/tmp/test# make
make -C /lib/modules/2.6.26-2-openvz-amd64/build M=/tmp/test modules
make[1]: Entering directory `/usr/src/linux-headers-2.6.26-2-openvz-amd64′
CC [M] /tmp/1/test.o
Building modules, stage 2.
MODPOST 1 modules
CC /tmp/test/test.mod.o
LD [M] /tmp/test/test.ko
make[1]: Leaving directory `/usr/src/linux-headers-2.6.26-2-openvz-amd64′
Посмотрим что у нас получилось:
root@joker:/tmp/test# ls -la
drwxr-xr-x 3 root root 4096 Окт 21 12:32 .
drwxrwxrwt 12 root root 4096 Окт 21 12:33 ..
-rw-r—r— 1 root root 219 Окт 21 12:30 demo.sh
-rw-r—r— 1 root root 161 Окт 21 12:30 Makefile
-rw-r—r— 1 root root 22 Окт 21 12:32 modules.order
-rw-r—r— 1 root root 0 Окт 21 12:32 Module.symvers
-rw-r—r— 1 root root 2940 Окт 21 12:30 test.c
-rw-r—r— 1 root root 10364 Окт 21 12:32 test.ko
-rw-r—r— 1 root root 104 Окт 21 12:32 .test.ko.cmd
-rw-r—r— 1 root root 717 Окт 21 12:32 test.mod.c
-rw-r—r— 1 root root 6832 Окт 21 12:32 test.mod.o
-rw-r—r— 1 root root 12867 Окт 21 12:32 .test.mod.o.cmd
-rw-r—r— 1 root root 4424 Окт 21 12:32 test.o
-rw-r—r— 1 root root 14361 Окт 21 12:32 .test.o.cmd
drwxr-xr-x 2 root root 4096 Окт 21 12:32 .tmp_versions
Теперь посмотрим информацию о только что скомпилированном модуле:
root@joker:/tmp/test# modinfo test.ko
filename: test.ko
description: My nice module
author: Alex Petrov
license: GPL
depends:
vermagic: 2.6.26-2-openvz-amd64 SMP mod_unload modversions
Ну и наконец установим модуль в ядро:
root@joker:/tmp/test# insmod test.ko
Посмотрим есть ли наш модуль с списке:
root@joker:/tmp/test# lsmod | grep test
И что попало в логи:
root@joker:/tmp/test# dmesg | tail
[829528.598922] Test module is loaded!
[829528.598926] Please, create a dev file with ‘mknod /dev/test c 249 0’.
Наш модуль подсказываем нам что нужно сделать.
Последуем его совету:
root@joker:/tmp/test# mknod /dev/test c 249 0
Ну и наконец проверим работает ли наш модуль:
root@joker:/tmp/test# cat /dev/test
Наш модуль не поддерживает приём данных со стороны пользователя:
root@joker:/tmp/test# echo 1 > /dev/test
bash: echo: ошибка записи: Недопустимый аргумент
Посмотрим что что скажет модуль на наши действия:
root@joker:/tmp/test# dmesg | tail
[829528.598922] Test module is loaded!
[829528.598926] Please, create a dev file with ‘mknod /dev/test c 249 0’.
[829747.462715] Sorry, this operation isn’t supported.
root@joker:/tmp/test# rmmod test
И посмотрим что он нам скажет на прощание:
root@joker:/tmp/test# dmesg | tail
[829528.598922] Test module is loaded!
[829528.598926] Please, create a dev file with ‘mknod /dev/test c 249 0’.
[829747.462715] Sorry, this operation isn’t supported.
[829893.681197] Test module is unloaded!
Удалим файл устройства, что бы он нас не смущал:
root@joker:/tmp/test# rm /dev/test
Заключение
Дальнейшее развитие этой «заготовки» зависит только от вас. Можно превратить её в настоящий драйвер, который будет предоставлять интерфейс к вашему девайсу, либо использовать для дальнейшего изучения ядра Linux.
Только что в голову пришла совершенно безумная идея сделать sudo через файл устройства. Т.е. посылаем в /dev/test команду и она выполняется от имени root.
Литература
И под конец дам ссылку на книгу заклинаний LKMPG (Linux Kernel Module Programming Guide)
UPD:
У некоторых может не собраться модуль через Makefile, описанный выше.
Решение:
Создаём Makefile только с одной строкой: obj-m += test.o
И запускаем сборку так:
make -C /usr/src/linux-headers-`uname -r` SUBDIRS=$PWD modules
UPD2:
Поправил ошибки в исходнике.
Парсер глючит и сохраняет ‘MODULE_DEscriptION( «My nice module» );’. Естественно в module_description все буквы заглавные.
UPD3:
segoon прислал несколько поправок к посту:
1) В функции device_open() находится race condition:
static int device_open( struct inode *inode, struct file *file )
<
text_ptr = text;
Источник