diff options
Diffstat (limited to 'documentation/content/ru/books/arch-handbook/driverbasics')
-rw-r--r-- | documentation/content/ru/books/arch-handbook/driverbasics/_index.adoc | 347 | ||||
-rw-r--r-- | documentation/content/ru/books/arch-handbook/driverbasics/_index.po | 867 |
2 files changed, 1214 insertions, 0 deletions
diff --git a/documentation/content/ru/books/arch-handbook/driverbasics/_index.adoc b/documentation/content/ru/books/arch-handbook/driverbasics/_index.adoc new file mode 100644 index 0000000000..74129e845c --- /dev/null +++ b/documentation/content/ru/books/arch-handbook/driverbasics/_index.adoc @@ -0,0 +1,347 @@ +--- +description: 'Написание драйверов устройств для FreeBSD' +next: books/arch-handbook/isa +params: + path: /books/arch-handbook/driverbasics/ +prev: books/arch-handbook/partii +showBookMenu: true +tags: ["writing", "device drivers", "KLD", "FreeBSD"] +title: 'Глава 9. Написание драйверов устройств для FreeBSD' +weight: 11 +--- + +[[driverbasics]] += Написание драйверов устройств для FreeBSD +:doctype: book +:toc: macro +:toclevels: 1 +:icons: font +:sectnums: +:sectnumlevels: 6 +:sectnumoffset: 9 +:partnums: +:source-highlighter: rouge +:experimental: +:images-path: books/arch-handbook/ + +ifdef::env-beastie[] +ifdef::backend-html5[] +:imagesdir: ../../../../images/{images-path} +endif::[] +ifndef::book[] +include::shared/authors.adoc[] +include::shared/mirrors.adoc[] +include::shared/releases.adoc[] +include::shared/attributes/attributes-{{% lang %}}.adoc[] +include::shared/{{% lang %}}/teams.adoc[] +include::shared/{{% lang %}}/mailing-lists.adoc[] +include::shared/{{% lang %}}/urls.adoc[] +toc::[] +endif::[] +ifdef::backend-pdf,backend-epub3[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] +endif::[] + +ifndef::env-beastie[] +toc::[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] + +[[driverbasics-intro]] +== Введение + +В этой главе представлено краткое введение в написание драйверов устройств для FreeBSD. Устройство в данном контексте — это термин, используемый в основном для аппаратных компонентов системы, таких как диски, принтеры или графический дисплей с клавиатурой. Драйвер устройства — это программный компонент операционной системы, который управляет конкретным устройством. Также существуют так называемые псевдоустройства, где драйвер эмулирует поведение устройства программно, без использования какого-либо конкретного аппаратного обеспечения. Драйверы устройств могут быть статически скомпилированы в систему или загружены по требованию через механизм динамической загрузки модулей ядра `kld`. + +Большинство устройств в операционной системе, подобной UNIX(R), доступны через специальные файлы устройств, также называемые узлами устройств. Эти файлы обычно расположены в каталоге [.filename]#/dev# в иерархии файловой системы. + +Драйверы устройств можно условно разделить на две категории: символьные драйверы и драйверы сетевых устройств. + +[[driverbasics-kld]] +== Динамический загрузчик модулей ядра - KLD + +Интерфейс kld позволяет системным администраторам динамически добавлять и удалять функциональность в работающей системе. Это позволяет разработчикам драйверов устройств загружать свои новые изменения в работающее ядро без постоянной перезагрузки для проверки изменений. + +Интерфейс kld используется с помощью следующих команд: + +* `kldload` - загружает новый модуль ядра +* `kldunload` — выгружает модуль ядра +* `kldstat` — выводит список загруженных модулей + +Каркасная структура модуля ядра + +[.programlisting] +.... +/* + * KLD Skeleton + * Inspired by Andrew Reiter's Daemonnews article + */ + +#include <sys/types.h> +#include <sys/systm.h> /* uprintf */ +#include <sys/errno.h> +#include <sys/param.h> /* defines used in kernel.h */ +#include <sys/module.h> +#include <sys/kernel.h> /* types used in module initialization */ + +/* + * Load handler that deals with the loading and unloading of a KLD. + */ + +static int +skel_loader(struct module *m, int what, void *arg) +{ + int err = 0; + + switch (what) { + case MOD_LOAD: /* kldload */ + uprintf("Skeleton KLD loaded.\n"); + break; + case MOD_UNLOAD: + uprintf("Skeleton KLD unloaded.\n"); + break; + default: + err = EOPNOTSUPP; + break; + } + return(err); +} + +/* Declare this module to the rest of the kernel */ + +static moduledata_t skel_mod = { + "skel", + skel_loader, + NULL +}; + +DECLARE_MODULE(skeleton, skel_mod, SI_SUB_KLD, SI_ORDER_ANY); +.... + +=== Makefile + +FreeBSD предоставляет системный makefile для упрощения компиляции модуля ядра. + +[.programlisting] +.... +SRCS=skeleton.c +KMOD=skeleton + +.include <bsd.kmod.mk> +.... + +Запуск `make` с этим makefile создаст файл [.filename]#skeleton.ko#, который можно загрузить в ядро, набрав: + +[source, bash] +.... +# kldload -v ./skeleton.ko +.... + +[[driverbasics-char]] +== Символьные устройства + +Драйвер символьного устройства — это драйвер, который передает данные напрямую между устройством и пользовательским процессом. Это наиболее распространенный тип драйвера устройств, и в дереве исходного кода есть множество простых примеров. + +Этот простой пример псевдоустройства запоминает все значения, записанные в него, и может затем воспроизводить их при чтении. + +.Пример образца драйвера псевдоустройства Echo для FreeBSD 10.X - 12.X +[example] +==== +[.programlisting] +.... +/* + * Simple Echo pseudo-device KLD + * + * Murray Stokely + * Søren (Xride) Straarup + * Eitan Adler + */ + +#include <sys/types.h> +#include <sys/systm.h> /* uprintf */ +#include <sys/param.h> /* defines used in kernel.h */ +#include <sys/module.h> +#include <sys/kernel.h> /* types used in module initialization */ +#include <sys/conf.h> /* cdevsw struct */ +#include <sys/uio.h> /* uio struct */ +#include <sys/malloc.h> + +#define BUFFERSIZE 255 + +/* Function prototypes */ +static d_open_t echo_open; +static d_close_t echo_close; +static d_read_t echo_read; +static d_write_t echo_write; + +/* Character device entry points */ +static struct cdevsw echo_cdevsw = { + .d_version = D_VERSION, + .d_open = echo_open, + .d_close = echo_close, + .d_read = echo_read, + .d_write = echo_write, + .d_name = "echo", +}; + +struct s_echo { + char msg[BUFFERSIZE + 1]; + int len; +}; + +/* vars */ +static struct cdev *echo_dev; +static struct s_echo *echomsg; + +MALLOC_DECLARE(M_ECHOBUF); +MALLOC_DEFINE(M_ECHOBUF, "echobuffer", "buffer for echo module"); + +/* + * This function is called by the kld[un]load(2) system calls to + * determine what actions to take when a module is loaded or unloaded. + */ +static int +echo_loader(struct module *m __unused, int what, void *arg __unused) +{ + int error = 0; + + switch (what) { + case MOD_LOAD: /* kldload */ + error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK, + &echo_dev, + &echo_cdevsw, + 0, + UID_ROOT, + GID_WHEEL, + 0600, + "echo"); + if (error != 0) + break; + + echomsg = malloc(sizeof(*echomsg), M_ECHOBUF, M_WAITOK | + M_ZERO); + printf("Echo device loaded.\n"); + break; + case MOD_UNLOAD: + destroy_dev(echo_dev); + free(echomsg, M_ECHOBUF); + printf("Echo device unloaded.\n"); + break; + default: + error = EOPNOTSUPP; + break; + } + return (error); +} + +static int +echo_open(struct cdev *dev __unused, int oflags __unused, int devtype __unused, + struct thread *td __unused) +{ + int error = 0; + + uprintf("Opened device \"echo\" successfully.\n"); + return (error); +} + +static int +echo_close(struct cdev *dev __unused, int fflag __unused, int devtype __unused, + struct thread *td __unused) +{ + + uprintf("Closing device \"echo\".\n"); + return (0); +} + +/* + * The read function just takes the buf that was saved via + * echo_write() and returns it to userland for accessing. + * uio(9) + */ +static int +echo_read(struct cdev *dev __unused, struct uio *uio, int ioflag __unused) +{ + size_t amt; + int error; + + /* + * How big is this read operation? Either as big as the user wants, + * or as big as the remaining data. Note that the 'len' does not + * include the trailing null character. + */ + amt = MIN(uio->uio_resid, uio->uio_offset >= echomsg->len + 1 ? 0 : + echomsg->len + 1 - uio->uio_offset); + + if ((error = uiomove(echomsg->msg, amt, uio)) != 0) + uprintf("uiomove failed!\n"); + + return (error); +} + +/* + * echo_write takes in a character string and saves it + * to buf for later accessing. + */ +static int +echo_write(struct cdev *dev __unused, struct uio *uio, int ioflag __unused) +{ + size_t amt; + int error; + + /* + * We either write from the beginning or are appending -- do + * not allow random access. + */ + if (uio->uio_offset != 0 && (uio->uio_offset != echomsg->len)) + return (EINVAL); + + /* This is a new message, reset length */ + if (uio->uio_offset == 0) + echomsg->len = 0; + + /* Copy the string in from user memory to kernel memory */ + amt = MIN(uio->uio_resid, (BUFFERSIZE - echomsg->len)); + + error = uiomove(echomsg->msg + uio->uio_offset, amt, uio); + + /* Now we need to null terminate and record the length */ + echomsg->len = uio->uio_offset; + echomsg->msg[echomsg->len] = 0; + + if (error != 0) + uprintf("Write failed: bad address!\n"); + return (error); +} + +DEV_MODULE(echo, echo_loader, NULL); +.... +==== + +Загрузив этот драйвер, попробуйте: + +[source, bash] +.... +# echo -n "Test Data" > /dev/echo +# cat /dev/echo +Opened device "echo" successfully. +Test Data +Closing device "echo". +.... + +Реальные аппаратные устройства описаны в следующей главе. + +[[driverbasics-block]] +== Блочные устройства (удалены) + +Другие системы UNIX(R) могут поддерживать второй тип дисковых устройств, известный как блочные устройства. Блочные устройства — это дисковые устройства, для которых ядро предоставляет кэширование. Это кэширование делает блочные устройства практически непригодными или, по крайней мере, опасно ненадёжными. Кэширование изменяет порядок операций записи, лишая приложение возможности точно знать содержимое диска в любой момент времени. + +Это делает невозможным предсказуемое и надежное восстановление после сбоев для структур данных на диске (файловых систем, баз данных и т. д.). Поскольку операции записи могут быть отложены, ядро не может сообщить приложению, какая именно операция записи столкнулась с ошибкой, что усугубляет проблему согласованности. + +По этой причине ни одно серьезное приложение не полагается на блочные устройства, и фактически почти все приложения, которые обращаются к дискам напрямую, прилагают значительные усилия, чтобы указать, что следует всегда использовать символьные (или "сырые") устройства. Поскольку реализация псевдонимов для каждого диска (раздела) в виде двух устройств с разной семантикой значительно усложняла соответствующий код ядра, FreeBSD отказалась от поддержки кэшируемых дисковых устройств в рамках модернизации инфраструктуры ввода-вывода для дисков. + +[[driverbasics-net]] +== Драйверы сетевых устройств + +Драйверы сетевых устройств не используют узлы устройств для доступа. Их выбор основан на других решениях, принимаемых внутри ядра, и вместо вызова open() использование сетевого устройства обычно осуществляется через системный вызов socket(2). + +Для получения дополнительной информации см. ifnet(9), исходный текст loopback-устройства. diff --git a/documentation/content/ru/books/arch-handbook/driverbasics/_index.po b/documentation/content/ru/books/arch-handbook/driverbasics/_index.po new file mode 100644 index 0000000000..c02c2b0fa1 --- /dev/null +++ b/documentation/content/ru/books/arch-handbook/driverbasics/_index.po @@ -0,0 +1,867 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR The FreeBSD Project +# This file is distributed under the same license as the FreeBSD Documentation package. +# Vladlen Popolitov <vladlenpopolitov@list.ru>, 2025. +msgid "" +msgstr "" +"Project-Id-Version: FreeBSD Documentation VERSION\n" +"POT-Creation-Date: 2025-10-14 22:43+0300\n" +"PO-Revision-Date: 2025-09-23 04:45+0000\n" +"Last-Translator: Vladlen Popolitov <vladlenpopolitov@list.ru>\n" +"Language-Team: Russian <https://translate-dev.freebsd.org/projects/" +"documentation/booksarch-handbookdriverbasics_index/ru/>\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.17\n" + +#. type: Title = +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:1 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:14 +#, no-wrap +msgid "Writing FreeBSD Device Drivers" +msgstr "Написание драйверов устройств для FreeBSD" + +#. type: Yaml Front Matter Hash Value: title +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:1 +#, no-wrap +msgid "Chapter 9. Writing FreeBSD Device Drivers" +msgstr "Глава 9. Написание драйверов устройств для FreeBSD" + +#. type: Title == +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:52 +#, no-wrap +msgid "Introduction" +msgstr "Введение" + +#. type: Plain text +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:55 +msgid "" +"This chapter provides a brief introduction to writing device drivers for " +"FreeBSD. A device in this context is a term used mostly for hardware-related " +"stuff that belongs to the system, like disks, printers, or a graphics " +"display with its keyboard. A device driver is the software component of the " +"operating system that controls a specific device. There are also so-called " +"pseudo-devices where a device driver emulates the behavior of a device in " +"software without any particular underlying hardware. Device drivers can be " +"compiled into the system statically or loaded on demand through the dynamic " +"kernel linker facility `kld'." +msgstr "" +"В этой главе представлено краткое введение в написание драйверов устройств " +"для FreeBSD. Устройство в данном контексте — это термин, используемый в " +"основном для аппаратных компонентов системы, таких как диски, принтеры или " +"графический дисплей с клавиатурой. Драйвер устройства — это программный " +"компонент операционной системы, который управляет конкретным устройством. " +"Также существуют так называемые псевдоустройства, где драйвер эмулирует " +"поведение устройства программно, без использования какого-либо конкретного " +"аппаратного обеспечения. Драйверы устройств могут быть статически " +"скомпилированы в систему или загружены по требованию через механизм " +"динамической загрузки модулей ядра `kld`." + +#. type: Plain text +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:57 +msgid "" +"Most devices in a UNIX(R)-like operating system are accessed through device-" +"nodes, sometimes also called special files. These files are usually located " +"under the directory [.filename]#/dev# in the filesystem hierarchy." +msgstr "" +"Большинство устройств в операционной системе, подобной UNIX(R), доступны " +"через специальные файлы устройств, также называемые узлами устройств. Эти " +"файлы обычно расположены в каталоге [.filename]#/dev# в иерархии файловой " +"системы." + +#. type: Plain text +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:59 +msgid "" +"Device drivers can roughly be broken down into two categories; character and " +"network device drivers." +msgstr "" +"Драйверы устройств можно условно разделить на две категории: символьные " +"драйверы и драйверы сетевых устройств." + +#. type: Title == +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:61 +#, no-wrap +msgid "Dynamic Kernel Linker Facility - KLD" +msgstr "Динамический загрузчик модулей ядра - KLD" + +#. type: Plain text +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:64 +msgid "" +"The kld interface allows system administrators to dynamically add and remove " +"functionality from a running system. This allows device driver writers to " +"load their new changes into a running kernel without constantly rebooting to " +"test changes." +msgstr "" +"Интерфейс kld позволяет системным администраторам динамически добавлять и " +"удалять функциональность в работающей системе. Это позволяет разработчикам " +"драйверов устройств загружать свои новые изменения в работающее ядро без " +"постоянной перезагрузки для проверки изменений." + +#. type: Plain text +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:66 +msgid "The kld interface is used through:" +msgstr "Интерфейс kld используется с помощью следующих команд:" + +#. type: Plain text +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:68 +msgid "`kldload` - loads a new kernel module" +msgstr "`kldload` - загружает новый модуль ядра" + +#. type: Plain text +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:69 +msgid "`kldunload` - unloads a kernel module" +msgstr "`kldunload` — выгружает модуль ядра" + +#. type: Plain text +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:70 +msgid "`kldstat` - lists loaded modules" +msgstr "`kldstat` — выводит список загруженных модулей" + +#. type: Plain text +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:72 +msgid "Skeleton Layout of a kernel module" +msgstr "Каркасная структура модуля ядра" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:79 +#, no-wrap +msgid "" +"/*\n" +" * KLD Skeleton\n" +" * Inspired by Andrew Reiter's Daemonnews article\n" +" */\n" +msgstr "" +"/*\n" +" * KLD Skeleton\n" +" * Inspired by Andrew Reiter's Daemonnews article\n" +" */\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:86 +#, no-wrap +msgid "" +"#include <sys/types.h>\n" +"#include <sys/systm.h> /* uprintf */\n" +"#include <sys/errno.h>\n" +"#include <sys/param.h> /* defines used in kernel.h */\n" +"#include <sys/module.h>\n" +"#include <sys/kernel.h> /* types used in module initialization */\n" +msgstr "" +"#include <sys/types.h>\n" +"#include <sys/systm.h> /* uprintf */\n" +"#include <sys/errno.h>\n" +"#include <sys/param.h> /* defines used in kernel.h */\n" +"#include <sys/module.h>\n" +"#include <sys/kernel.h> /* types used in module initialization */\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:90 +#, no-wrap +msgid "" +"/*\n" +" * Load handler that deals with the loading and unloading of a KLD.\n" +" */\n" +msgstr "" +"/*\n" +" * Load handler that deals with the loading and unloading of a KLD.\n" +" */\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:95 +#, no-wrap +msgid "" +"static int\n" +"skel_loader(struct module *m, int what, void *arg)\n" +"{\n" +"\tint err = 0;\n" +msgstr "" +"static int\n" +"skel_loader(struct module *m, int what, void *arg)\n" +"{\n" +"\tint err = 0;\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:109 +#, no-wrap +msgid "" +"\tswitch (what) {\n" +"\tcase MOD_LOAD: /* kldload */\n" +"\t\tuprintf(\"Skeleton KLD loaded.\\n\");\n" +"\t\tbreak;\n" +"\tcase MOD_UNLOAD:\n" +"\t\tuprintf(\"Skeleton KLD unloaded.\\n\");\n" +"\t\tbreak;\n" +"\tdefault:\n" +"\t\terr = EOPNOTSUPP;\n" +"\t\tbreak;\n" +"\t}\n" +"\treturn(err);\n" +"}\n" +msgstr "" +"\tswitch (what) {\n" +"\tcase MOD_LOAD: /* kldload */\n" +"\t\tuprintf(\"Skeleton KLD loaded.\\n\");\n" +"\t\tbreak;\n" +"\tcase MOD_UNLOAD:\n" +"\t\tuprintf(\"Skeleton KLD unloaded.\\n\");\n" +"\t\tbreak;\n" +"\tdefault:\n" +"\t\terr = EOPNOTSUPP;\n" +"\t\tbreak;\n" +"\t}\n" +"\treturn(err);\n" +"}\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:111 +#, no-wrap +msgid "/* Declare this module to the rest of the kernel */\n" +msgstr "/* Declare this module to the rest of the kernel */\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:117 +#, no-wrap +msgid "" +"static moduledata_t skel_mod = {\n" +"\t\"skel\",\n" +"\tskel_loader,\n" +"\tNULL\n" +"};\n" +msgstr "" +"static moduledata_t skel_mod = {\n" +"\t\"skel\",\n" +"\tskel_loader,\n" +"\tNULL\n" +"};\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:119 +#, no-wrap +msgid "DECLARE_MODULE(skeleton, skel_mod, SI_SUB_KLD, SI_ORDER_ANY);\n" +msgstr "DECLARE_MODULE(skeleton, skel_mod, SI_SUB_KLD, SI_ORDER_ANY);\n" + +#. type: Title === +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:121 +#, no-wrap +msgid "Makefile" +msgstr "Makefile" + +#. type: Plain text +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:124 +msgid "" +"FreeBSD provides a system makefile to simplify compiling a kernel module." +msgstr "" +"FreeBSD предоставляет системный makefile для упрощения компиляции модуля " +"ядра." + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:129 +#, no-wrap +msgid "" +"SRCS=skeleton.c\n" +"KMOD=skeleton\n" +msgstr "" +"SRCS=skeleton.c\n" +"KMOD=skeleton\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:131 +#, no-wrap +msgid ".include <bsd.kmod.mk>\n" +msgstr ".include <bsd.kmod.mk>\n" + +#. type: Plain text +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:134 +msgid "" +"Running `make` with this makefile will create a file " +"[.filename]#skeleton.ko# that can be loaded into the kernel by typing:" +msgstr "" +"Запуск `make` с этим makefile создаст файл [.filename]#skeleton.ko#, который " +"можно загрузить в ядро, набрав:" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:138 +#, no-wrap +msgid "# kldload -v ./skeleton.ko\n" +msgstr "# kldload -v ./skeleton.ko\n" + +#. type: Title == +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:141 +#, no-wrap +msgid "Character Devices" +msgstr "Символьные устройства" + +#. type: Plain text +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:144 +msgid "" +"A character device driver is one that transfers data directly to and from a " +"user process. This is the most common type of device driver and there are " +"plenty of simple examples in the source tree." +msgstr "" +"Драйвер символьного устройства — это драйвер, который передает данные " +"напрямую между устройством и пользовательским процессом. Это наиболее " +"распространенный тип драйвера устройств, и в дереве исходного кода есть " +"множество простых примеров." + +#. type: Plain text +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:146 +msgid "" +"This simple example pseudo-device remembers whatever values are written to " +"it and can then echo them back when read." +msgstr "" +"Этот простой пример псевдоустройства запоминает все значения, записанные в " +"него, и может затем воспроизводить их при чтении." + +#. type: Block title +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:147 +#, no-wrap +msgid "Example of a Sample Echo Pseudo-Device Driver for FreeBSD 10.X - 12.X" +msgstr "Пример образца драйвера псевдоустройства Echo для FreeBSD 10.X - 12.X" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:159 +#, no-wrap +msgid "" +"/*\n" +" * Simple Echo pseudo-device KLD\n" +" *\n" +" * Murray Stokely\n" +" * Søren (Xride) Straarup\n" +" * Eitan Adler\n" +" */\n" +msgstr "" +"/*\n" +" * Simple Echo pseudo-device KLD\n" +" *\n" +" * Murray Stokely\n" +" * Søren (Xride) Straarup\n" +" * Eitan Adler\n" +" */\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:168 +#, no-wrap +msgid "" +"#include <sys/types.h>\n" +"#include <sys/systm.h> /* uprintf */\n" +"#include <sys/param.h> /* defines used in kernel.h */\n" +"#include <sys/module.h>\n" +"#include <sys/kernel.h> /* types used in module initialization */\n" +"#include <sys/conf.h> /* cdevsw struct */\n" +"#include <sys/uio.h> /* uio struct */\n" +"#include <sys/malloc.h>\n" +msgstr "" +"#include <sys/types.h>\n" +"#include <sys/systm.h> /* uprintf */\n" +"#include <sys/param.h> /* defines used in kernel.h */\n" +"#include <sys/module.h>\n" +"#include <sys/kernel.h> /* types used in module initialization */\n" +"#include <sys/conf.h> /* cdevsw struct */\n" +"#include <sys/uio.h> /* uio struct */\n" +"#include <sys/malloc.h>\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:170 +#, no-wrap +msgid "#define BUFFERSIZE 255\n" +msgstr "#define BUFFERSIZE 255\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:176 +#, no-wrap +msgid "" +"/* Function prototypes */\n" +"static d_open_t echo_open;\n" +"static d_close_t echo_close;\n" +"static d_read_t echo_read;\n" +"static d_write_t echo_write;\n" +msgstr "" +"/* Function prototypes */\n" +"static d_open_t echo_open;\n" +"static d_close_t echo_close;\n" +"static d_read_t echo_read;\n" +"static d_write_t echo_write;\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:186 +#, no-wrap +msgid "" +"/* Character device entry points */\n" +"static struct cdevsw echo_cdevsw = {\n" +"\t.d_version = D_VERSION,\n" +"\t.d_open = echo_open,\n" +"\t.d_close = echo_close,\n" +"\t.d_read = echo_read,\n" +"\t.d_write = echo_write,\n" +"\t.d_name = \"echo\",\n" +"};\n" +msgstr "" +"/* Character device entry points */\n" +"static struct cdevsw echo_cdevsw = {\n" +"\t.d_version = D_VERSION,\n" +"\t.d_open = echo_open,\n" +"\t.d_close = echo_close,\n" +"\t.d_read = echo_read,\n" +"\t.d_write = echo_write,\n" +"\t.d_name = \"echo\",\n" +"};\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:191 +#, no-wrap +msgid "" +"struct s_echo {\n" +"\tchar msg[BUFFERSIZE + 1];\n" +"\tint len;\n" +"};\n" +msgstr "" +"struct s_echo {\n" +"\tchar msg[BUFFERSIZE + 1];\n" +"\tint len;\n" +"};\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:195 +#, no-wrap +msgid "" +"/* vars */\n" +"static struct cdev *echo_dev;\n" +"static struct s_echo *echomsg;\n" +msgstr "" +"/* vars */\n" +"static struct cdev *echo_dev;\n" +"static struct s_echo *echomsg;\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:198 +#, no-wrap +msgid "" +"MALLOC_DECLARE(M_ECHOBUF);\n" +"MALLOC_DEFINE(M_ECHOBUF, \"echobuffer\", \"buffer for echo module\");\n" +msgstr "" +"MALLOC_DECLARE(M_ECHOBUF);\n" +"MALLOC_DEFINE(M_ECHOBUF, \"echobuffer\", \"buffer for echo module\");\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:207 +#, no-wrap +msgid "" +"/*\n" +" * This function is called by the kld[un]load(2) system calls to\n" +" * determine what actions to take when a module is loaded or unloaded.\n" +" */\n" +"static int\n" +"echo_loader(struct module *m __unused, int what, void *arg __unused)\n" +"{\n" +"\tint error = 0;\n" +msgstr "" +"/*\n" +" * This function is called by the kld[un]load(2) system calls to\n" +" * determine what actions to take when a module is loaded or unloaded.\n" +" */\n" +"static int\n" +"echo_loader(struct module *m __unused, int what, void *arg __unused)\n" +"{\n" +"\tint error = 0;\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:220 +#, no-wrap +msgid "" +"\tswitch (what) {\n" +"\tcase MOD_LOAD: /* kldload */\n" +"\t\terror = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK,\n" +"\t\t &echo_dev,\n" +"\t\t &echo_cdevsw,\n" +"\t\t 0,\n" +"\t\t UID_ROOT,\n" +"\t\t GID_WHEEL,\n" +"\t\t 0600,\n" +"\t\t \"echo\");\n" +"\t\tif (error != 0)\n" +"\t\t\tbreak;\n" +msgstr "" +"\tswitch (what) {\n" +"\tcase MOD_LOAD: /* kldload */\n" +"\t\terror = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK,\n" +"\t\t &echo_dev,\n" +"\t\t &echo_cdevsw,\n" +"\t\t 0,\n" +"\t\t UID_ROOT,\n" +"\t\t GID_WHEEL,\n" +"\t\t 0600,\n" +"\t\t \"echo\");\n" +"\t\tif (error != 0)\n" +"\t\t\tbreak;\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:236 +#, no-wrap +msgid "" +"\t\techomsg = malloc(sizeof(*echomsg), M_ECHOBUF, M_WAITOK |\n" +"\t\t M_ZERO);\n" +"\t\tprintf(\"Echo device loaded.\\n\");\n" +"\t\tbreak;\n" +"\tcase MOD_UNLOAD:\n" +"\t\tdestroy_dev(echo_dev);\n" +"\t\tfree(echomsg, M_ECHOBUF);\n" +"\t\tprintf(\"Echo device unloaded.\\n\");\n" +"\t\tbreak;\n" +"\tdefault:\n" +"\t\terror = EOPNOTSUPP;\n" +"\t\tbreak;\n" +"\t}\n" +"\treturn (error);\n" +"}\n" +msgstr "" +"\t\techomsg = malloc(sizeof(*echomsg), M_ECHOBUF, M_WAITOK |\n" +"\t\t M_ZERO);\n" +"\t\tprintf(\"Echo device loaded.\\n\");\n" +"\t\tbreak;\n" +"\tcase MOD_UNLOAD:\n" +"\t\tdestroy_dev(echo_dev);\n" +"\t\tfree(echomsg, M_ECHOBUF);\n" +"\t\tprintf(\"Echo device unloaded.\\n\");\n" +"\t\tbreak;\n" +"\tdefault:\n" +"\t\terror = EOPNOTSUPP;\n" +"\t\tbreak;\n" +"\t}\n" +"\treturn (error);\n" +"}\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:242 +#, no-wrap +msgid "" +"static int\n" +"echo_open(struct cdev *dev __unused, int oflags __unused, int devtype __unused,\n" +" struct thread *td __unused)\n" +"{\n" +"\tint error = 0;\n" +msgstr "" +"static int\n" +"echo_open(struct cdev *dev __unused, int oflags __unused, int devtype __unused,\n" +" struct thread *td __unused)\n" +"{\n" +"\tint error = 0;\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:246 +#, no-wrap +msgid "" +"\tuprintf(\"Opened device \\\"echo\\\" successfully.\\n\");\n" +"\treturn (error);\n" +"}\n" +msgstr "" +"\tuprintf(\"Opened device \\\"echo\\\" successfully.\\n\");\n" +"\treturn (error);\n" +"}\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:251 +#, no-wrap +msgid "" +"static int\n" +"echo_close(struct cdev *dev __unused, int fflag __unused, int devtype __unused,\n" +" struct thread *td __unused)\n" +"{\n" +msgstr "" +"static int\n" +"echo_close(struct cdev *dev __unused, int fflag __unused, int devtype __unused,\n" +" struct thread *td __unused)\n" +"{\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:255 +#, no-wrap +msgid "" +"\tuprintf(\"Closing device \\\"echo\\\".\\n\");\n" +"\treturn (0);\n" +"}\n" +msgstr "" +"\tuprintf(\"Closing device \\\"echo\\\".\\n\");\n" +"\treturn (0);\n" +"}\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:266 +#, no-wrap +msgid "" +"/*\n" +" * The read function just takes the buf that was saved via\n" +" * echo_write() and returns it to userland for accessing.\n" +" * uio(9)\n" +" */\n" +"static int\n" +"echo_read(struct cdev *dev __unused, struct uio *uio, int ioflag __unused)\n" +"{\n" +"\tsize_t amt;\n" +"\tint error;\n" +msgstr "" +"/*\n" +" * The read function just takes the buf that was saved via\n" +" * echo_write() and returns it to userland for accessing.\n" +" * uio(9)\n" +" */\n" +"static int\n" +"echo_read(struct cdev *dev __unused, struct uio *uio, int ioflag __unused)\n" +"{\n" +"\tsize_t amt;\n" +"\tint error;\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:274 +#, no-wrap +msgid "" +"\t/*\n" +"\t * How big is this read operation? Either as big as the user wants,\n" +"\t * or as big as the remaining data. Note that the 'len' does not\n" +"\t * include the trailing null character.\n" +"\t */\n" +"\tamt = MIN(uio->uio_resid, uio->uio_offset >= echomsg->len + 1 ? 0 :\n" +"\t echomsg->len + 1 - uio->uio_offset);\n" +msgstr "" +"\t/*\n" +"\t * How big is this read operation? Either as big as the user wants,\n" +"\t * or as big as the remaining data. Note that the 'len' does not\n" +"\t * include the trailing null character.\n" +"\t */\n" +"\tamt = MIN(uio->uio_resid, uio->uio_offset >= echomsg->len + 1 ? 0 :\n" +"\t echomsg->len + 1 - uio->uio_offset);\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:277 +#, no-wrap +msgid "" +"\tif ((error = uiomove(echomsg->msg, amt, uio)) != 0)\n" +"\t\tuprintf(\"uiomove failed!\\n\");\n" +msgstr "" +"\tif ((error = uiomove(echomsg->msg, amt, uio)) != 0)\n" +"\t\tuprintf(\"uiomove failed!\\n\");\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:280 +#, no-wrap +msgid "" +"\treturn (error);\n" +"}\n" +msgstr "" +"\treturn (error);\n" +"}\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:290 +#, no-wrap +msgid "" +"/*\n" +" * echo_write takes in a character string and saves it\n" +" * to buf for later accessing.\n" +" */\n" +"static int\n" +"echo_write(struct cdev *dev __unused, struct uio *uio, int ioflag __unused)\n" +"{\n" +"\tsize_t amt;\n" +"\tint error;\n" +msgstr "" +"/*\n" +" * echo_write takes in a character string and saves it\n" +" * to buf for later accessing.\n" +" */\n" +"static int\n" +"echo_write(struct cdev *dev __unused, struct uio *uio, int ioflag __unused)\n" +"{\n" +"\tsize_t amt;\n" +"\tint error;\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:297 +#, no-wrap +msgid "" +"\t/*\n" +"\t * We either write from the beginning or are appending -- do\n" +"\t * not allow random access.\n" +"\t */\n" +"\tif (uio->uio_offset != 0 && (uio->uio_offset != echomsg->len))\n" +"\t\treturn (EINVAL);\n" +msgstr "" +"\t/*\n" +"\t * We either write from the beginning or are appending -- do\n" +"\t * not allow random access.\n" +"\t */\n" +"\tif (uio->uio_offset != 0 && (uio->uio_offset != echomsg->len))\n" +"\t\treturn (EINVAL);\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:301 +#, no-wrap +msgid "" +"\t/* This is a new message, reset length */\n" +"\tif (uio->uio_offset == 0)\n" +"\t\techomsg->len = 0;\n" +msgstr "" +"\t/* This is a new message, reset length */\n" +"\tif (uio->uio_offset == 0)\n" +"\t\techomsg->len = 0;\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:304 +#, no-wrap +msgid "" +"\t/* Copy the string in from user memory to kernel memory */\n" +"\tamt = MIN(uio->uio_resid, (BUFFERSIZE - echomsg->len));\n" +msgstr "" +"\t/* Copy the string in from user memory to kernel memory */\n" +"\tamt = MIN(uio->uio_resid, (BUFFERSIZE - echomsg->len));\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:306 +#, no-wrap +msgid "\terror = uiomove(echomsg->msg + uio->uio_offset, amt, uio);\n" +msgstr "\terror = uiomove(echomsg->msg + uio->uio_offset, amt, uio);\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:310 +#, no-wrap +msgid "" +"\t/* Now we need to null terminate and record the length */\n" +"\techomsg->len = uio->uio_offset;\n" +"\techomsg->msg[echomsg->len] = 0;\n" +msgstr "" +"\t/* Now we need to null terminate and record the length */\n" +"\techomsg->len = uio->uio_offset;\n" +"\techomsg->msg[echomsg->len] = 0;\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:315 +#, no-wrap +msgid "" +"\tif (error != 0)\n" +"\t\tuprintf(\"Write failed: bad address!\\n\");\n" +"\treturn (error);\n" +"}\n" +msgstr "" +"\tif (error != 0)\n" +"\t\tuprintf(\"Write failed: bad address!\\n\");\n" +"\treturn (error);\n" +"}\n" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:317 +#, no-wrap +msgid "DEV_MODULE(echo, echo_loader, NULL);\n" +msgstr "DEV_MODULE(echo, echo_loader, NULL);\n" + +#. type: delimited block = 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:321 +msgid "With this driver loaded try:" +msgstr "Загрузив этот драйвер, попробуйте:" + +#. type: delimited block . 4 +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:329 +#, no-wrap +msgid "" +"# echo -n \"Test Data\" > /dev/echo\n" +"# cat /dev/echo\n" +"Opened device \"echo\" successfully.\n" +"Test Data\n" +"Closing device \"echo\".\n" +msgstr "" +"# echo -n \"Test Data\" > /dev/echo\n" +"# cat /dev/echo\n" +"Opened device \"echo\" successfully.\n" +"Test Data\n" +"Closing device \"echo\".\n" + +#. type: Plain text +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:332 +msgid "Real hardware devices are described in the next chapter." +msgstr "Реальные аппаратные устройства описаны в следующей главе." + +#. type: Title == +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:334 +#, no-wrap +msgid "Block Devices (Are Gone)" +msgstr "Блочные устройства (удалены)" + +#. type: Plain text +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:337 +msgid "" +"Other UNIX(R) systems may support a second type of disk device known as " +"block devices. Block devices are disk devices for which the kernel provides " +"caching. This caching makes block-devices almost unusable, or at least " +"dangerously unreliable. The caching will reorder the sequence of write " +"operations, depriving the application of the ability to know the exact disk " +"contents at any one instant in time." +msgstr "" +"Другие системы UNIX(R) могут поддерживать второй тип дисковых устройств, " +"известный как блочные устройства. Блочные устройства — это дисковые " +"устройства, для которых ядро предоставляет кэширование. Это кэширование " +"делает блочные устройства практически непригодными или, по крайней мере, " +"опасно ненадёжными. Кэширование изменяет порядок операций записи, лишая " +"приложение возможности точно знать содержимое диска в любой момент времени." + +#. type: Plain text +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:339 +msgid "" +"This makes predictable and reliable crash recovery of on-disk data " +"structures (filesystems, databases, etc.) impossible. Since writes may be " +"delayed, there is no way the kernel can report to the application which " +"particular write operation encountered a write error, this further compounds " +"the consistency problem." +msgstr "" +"Это делает невозможным предсказуемое и надежное восстановление после сбоев " +"для структур данных на диске (файловых систем, баз данных и т. д.). " +"Поскольку операции записи могут быть отложены, ядро не может сообщить " +"приложению, какая именно операция записи столкнулась с ошибкой, что " +"усугубляет проблему согласованности." + +#. type: Plain text +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:341 +msgid "" +"For this reason, no serious applications rely on block devices, and in fact, " +"almost all applications which access disks directly take great pains to " +"specify that character (or \"raw\") devices should always be used. As the " +"implementation of the aliasing of each disk (partition) to two devices with " +"different semantics significantly complicated the relevant kernel code, " +"FreeBSD dropped support for cached disk devices as part of the modernization " +"of the disk I/O infrastructure." +msgstr "" +"По этой причине ни одно серьезное приложение не полагается на блочные " +"устройства, и фактически почти все приложения, которые обращаются к дискам " +"напрямую, прилагают значительные усилия, чтобы указать, что следует всегда " +"использовать символьные (или \"сырые\") устройства. Поскольку реализация " +"псевдонимов для каждого диска (раздела) в виде двух устройств с разной " +"семантикой значительно усложняла соответствующий код ядра, FreeBSD " +"отказалась от поддержки кэшируемых дисковых устройств в рамках модернизации " +"инфраструктуры ввода-вывода для дисков." + +#. type: Title == +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:343 +#, no-wrap +msgid "Network Drivers" +msgstr "Драйверы сетевых устройств" + +#. type: Plain text +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:346 +msgid "" +"Drivers for network devices do not use device nodes in order to be accessed. " +"Their selection is based on other decisions made inside the kernel and " +"instead of calling open(), use of a network device is generally introduced " +"by using the system call socket(2)." +msgstr "" +"Драйверы сетевых устройств не используют узлы устройств для доступа. Их " +"выбор основан на других решениях, принимаемых внутри ядра, и вместо вызова " +"open() использование сетевого устройства обычно осуществляется через " +"системный вызов socket(2)." + +#. type: Plain text +#: documentation/content/en/books/arch-handbook/driverbasics/_index.adoc:347 +msgid "For more information see ifnet(9), the source of the loopback device." +msgstr "" +"Для получения дополнительной информации см. ifnet(9), исходный текст " +"loopback-устройства." |