Документ взят из кэша поисковой машины. Адрес оригинального документа : http://www.fds-net.ru/showflat.php?Number=12664480&src=&showlite=l
Дата изменения: Unknown
Дата индексирования: Tue Apr 12 06:38:43 2016
Кодировка: Windows-1251
Вывод быстроменяющихся данных из ядра в пользовательское пространство - Public forum of MSU united student networks
Technical >> Development

Страницы: 1 | (1)
gudok : Re: Вывод быстроменяющихся данных из ядра в пользовательское пространс  [re:Vilfred_Sagen]   08.04.2016 19:39    | Reply | Edit |
8
Ну, традиционно самый быстрый способ - это через отображение памяти. Системные вызовы, связанные со временем, делаются именно так.

Т.е. твой драйвер создает страницу памяти, которую шарит внутрь виртуального адресного пространства твоего userspace процесса. Ну и дальше перегоняет данные из устройства в эту страницу, а userspace процесс - читает из нее (например, в цикле).

А если доступ к устройству - простой memory-mapped, API устройства простое, и устройство отдает данные быстро, то можно смаппить прямо адресное пространство устройства внутрь userspace процесса.

Ну или вообще, реализовать код userspace процесса in-kernel.

Вообще, тебя какая модель общения интересует? Чтобы userspace процесс on-demand дергал какую-то функцию, и она отдавала с минимальным latency текущее значение из устройства? Или тебе нужно последовательность значений из устройства вытаскивать (не потеряв промежуточные значения)?

gudok   [re:gudok]   08.04.2016 20:10    | Reply | Edit |
7
Как-то так:
1. Драйвер при инициализации выделяет страницу памяти (kmalloc). Запоминает ее адрес.
2. Драйвер постоянно перегоняет данные из устройства в эту страницу
3. Драйвер реализует ioctl, результат которого - физический адрес этой странички
4. Процесс при инициализации дергает этот ioctl, тем самым знает, откуда эти данные забирать
5. Процесс отображает эту страницу в свое виртуальное пространство (mmap на /dev/mem по полученному выше адресу).
6. Теперь процесс может считывать в цикле данные из отображенной страницы

Замечание #1. Использование /dev/mem требует соответствующих прав и, вообще говоря, несколько криво. Наверняка, есть более красивый способ.

Замечание #2. Если данные не влезают в машинное слово, то можно огрести проблем с атомарностью. Например, считывание 128-битного значения на 64-битной архитектуре требует два 64-битных mov, тем самым ты можешь получить левую часть от считывания N_i, а правую - от считывания N_j.

Традиционная книжка по драйверам: http://www.makelinux.net/ldd3/


Vilfred_Sagen   [re:gudok]   09.04.2016 11:39    | Reply | Edit |
-3
допустим нужно сообщить 64 бита в юзерспейс. При чем о состоянии регистра, значение которого меняется чаще чем исполняются машинные команды. Делаю драйвер, который тратит 100% CPU на копирование этого регистра в какую-то там память, с потерями. Потом юзерский процесс пытается достучаться до этих восьми байт - обращается к 4196-байтной странице памяти,

прошу прощения, прерывание по неотложным причинам

в которую драйвер записал данные хуй знает когда. Едро вместо этого сначала

прошу прощения, прерывание по неотложным причинам

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

прошу прощения, прерывание по неотложным причинам

имеет право читать эти

прошу прощения, прерывание по неотложным причинам

данные, когда ядро убедилось что

прошу прощения, прерывание по неотложным причинам

твой процесс имеет право доступа к

прошу прощения, прерывание по неотложным причинам

данной области памяти, оно начинает долго и томи

прошу прощения, прерывание по неотложным причинам

тельно тянуть эти четыре килоба

прошу прощения, прерывание по неотложным причинам

йта из RAM потому, что друг

прошу прощения, прерывание по неотложным причинам

ие процессы уже вытеснили страницу из кеш-лайна.

Вот что тут можно гарантировать для рил-тайма кроме 100% потребления одного ядра CPU?

gudok   [re:Vilfred_Sagen]   09.04.2016 12:35    | Reply | Edit |
1
Вышеуказанное решение я написал из расчета, что данные уже в ядре, и тебе осталось только сделать "Вывод быстроменяющихся данных из ядра в пользовательское пространство". Про busyloop в ядре я ничего не писал, только в userspace. :)

Как происходит забирание данных из устройства: чтение из памяти (mov) или чтение из порта (inb/inw)? Сколько времени обходится одно чтение?

Просто мне кажется, что в твоем случае самый простой способ будет и самым быстрым:
1) userspace дергает некий ioctl
2) драйвер при получении ioctl опрашивает устройство и возвращает значение как результат ioctl

Если чтение из устройства использует только mov, то можно заморочиться и код драйвера перенести в сам userspace процесс (общение в память через /dev/mem). Будет экономия на syscall.

P.S. Ну и это, что-то у тебя слишком часто прерывания идут. Может, их обработку на другие ядра перевесить?

gudok   [re:gudok]   09.04.2016 12:39    | Reply | Edit |
1
Тебе что важнее: получить как можно более свежие данные или как можно меньше блокировать процесс? Одновременно и то, и другое не получится.

Rokhan   [re:Vilfred_Sagen]   10.04.2016 01:39    | Reply | Edit |
0
В ответ на:

Вот что тут можно гарантировать для рил-тайма кроме 100% потребления одного ядра CPU?



Линукс не является системой RTOS по определению, твоя задача наверняка решается куда проще чем ты сейчас загоняешь.
Создаешь FIFO и пихаешь в него твои данные.

niman   [re:Rokhan]   10.04.2016 18:52    | Reply | Edit |
0
вроде сейчас можно освободить от кернел-тредов ядро проца, соответственно вся нереальность упирается в прерывания, которые вообще не проблемы линукса, а железа

Top