LINUX.ORG.RU

Kernel threads - «неправильная» многопоточность.

 , , , ,


1

3

Всем привет.

Пишу драйвер, так вышло, что в нём необходимо организовать простые TCP серверы для закидывания конфигурации драйвера в рантайме по сети. Да, именно в драйвере это надо делать, есть различные причины для этого, выбор сделан и пересмотру не подлежит.

Итак, в драйвере создаются 4 инстанса «сервера» - каждый на свой порт и для них отдельный поток, проверяющий входящие соединения на соккетах раз в 500 мс.

Ещё есть в драйвере основной поток, в котором производится некая обработка данных (позднее он будет выпилен и обработка будет сделано по прерыванию на GPIO но сейчас именно так).

Оба потока создаются так:

kthread_run( thread_func, thread_param, thread_name);

Потоки отлично создаются и работают за исключением 1 момента! Они работают не параллельно а «последовательно». 1-2 секунды на поток! Сначала один поток работает 1-2 секунды а второй «спит», потом первый «засыпает» а второй начинает работать так же 1-2 секунды.

Такая работа не преемлима. Вопрос в том - как заставить их работать «параллельно». Никогда с таким не сталкивался (раньше на Windоws работал), идей нет и гугл не помог.

Буду признателен за помощь.

p.s. юзаю OE Linux, ядро 3.2.0 (собирал всё сам), проц OMAP3530

У меня всегда двоякое чувство, когда по-русски выходит очередной перевод очередной книги по ядру.

С одной строны радостно, что объем профессиональной литературы увеличивается.

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

Особо позабавило исчерпывающее описание

Оба потока создаются так:

kthread_run( thread_func, thread_param, thread_name);

Понятное дело, работать у тебя ничего не будет, поэтому даже не буду тебе желать убить себя об стену.

ttnl ★★★★★
()

Пишу драйвер, так вышло, что в нём необходимо организовать простые TCP серверы для закидывания конфигурации драйвера в рантайме по сети. Да, именно в драйвере это надо делать, есть различные причины для этого, выбор сделан и пересмотру не подлежит.

раньше на Windоws работал

Ад и Израиль.

гугл не помог.

http://kernel.org/doc/htmldocs/device-drivers/API-kthread-run.html

«the function to run until signal_pending(current)»

does it ring a bell?

tailgunner ★★★★★
()
Ответ на: комментарий от ttnl

С какой целью ты зашёл в эту тему? Сказать, что ничего работать не будет? Я это и без тебя уже прекрасно понял. Потроллить и пожелать убиться ап стену? Неужели тебя так много свободного времени, чтобы лазать по разным веткам форума и писать абсолютно безсмысленные комментарии, не несущие никакой полезной информации, кроме как, быть может, потешивания своего ЧСВ за счёт новичков в линуксе типа меня и получения одобрения троллинга со стороны таких же как ты, быть может тебе не хватает общения и ты ищешь его тут таким слегка странным способом?

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

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

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

Я_понятно_объясняю?

l-proger
() автор топика
Ответ на: комментарий от Jetty

Ты невнимательно читаешь:

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

Надо быстро != дело не быстрое ) Потмоу и пишу, параллельно читая доки. Может быстрее поможете (ведь раз вы зашли сюда, значит у вас _есть_ свободное время на это. А раз есть, то я понадеялся, что вы возможно потратите его не на троллинг, а на помощь по делу.

До чего докурил:

ставлю процессу флаг set_current_state(TASK_INTERRUPTIBLE); после проверки входящих соединений на соккетах. Насколько я понял - с этого момента шедулер понимает, что процесс можно прервать и отдаёт процессорное время другому ожидающему процессу.

и ставлю ещё schedule_timeout(100);

вместо mdelay

l-proger
() автор топика
Ответ на: комментарий от l-proger

проблема в том, что надо запилить фичу одну как можно быстрее

И при этом используются сокеты в ядре и нити ядра для общения по сокетам. Для человека, не знакомого с Linux-драйверами - прекрасный способ ускорить разработку.

tailgunner ★★★★★
()
Ответ на: комментарий от l-proger

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

Jetty ★★★★★
()

OMAP3530
Они работают не параллельно а «последовательно»

а как ты хотел-то на одноядерном чипе?

но вообще пихать в ядро - это конечно сильно. Напиши юзерспейсовые сервера и выставь им нужный приоритет. И всё.k

anonymous
()
Ответ на: комментарий от l-proger

Я_понятно_объясняю?

И незачем так переживать.

не объяснить доходчиво об организации правильной многопоточности в драйверах

Есть отличные мануалы про это. Зачем еще раз писать своими словами.

раньше на Windоws работал

Мое личное наблюдение. Программисты, которые долгое время работали на венде пытаются узнать не полезную информацию, а готовое решение. И когда ты говоришь такому программисту: «Прочти в википедии, там все написано», то он считает, что ты его оскорбил. А там действительно все написано.

trex6 ★★★★★
()

так вышло, что в нём необходимо организовать простые TCP

а почему не SNMP?

cvv ★★★★★
()

Потоки отлично создаются и работают за исключением 1 момента! Они работают не параллельно а «последовательно». 1-2 секунды на поток! Сначала один поток работает 1-2 секунды а второй «спит», потом первый «засыпает» а второй начинает работать так же 1-2 секунды.

как вариант - ты в потоках запрещаешь прерывания на 1-2 секунды

cvv ★★★★★
()
Ответ на: комментарий от Jetty

Я уже понял, что быстро не выходит ) До этого вполне успешно написал драйвера нескольких своих устройств под Gumstix, даже вт накидал свой драйвер ISP (хотя он есть в линуксе, но плотно вшит в V4L2, а нужна лишь чатсь функционала по сливанию 10 bit RAW данных с сенсора, драйвера радио модулей по SPI написал и прочего железа. Всё постепенно курил и, собсно, раскурил (на достаточном для написания данных дров уровне).

Просто потоки как-то не нужны били в тех дровах, в нынешнем понадобились, именно сегодня ) Поискал семплы внятные, но их найти сложновато. Маны - большие и суровые, а запилить надо быстро ) Я довольно быстро понимаю тему если мне её «на пальцах» объясняют, потому и запостил. Выглядит возможно как help vampire, но уверяю, что это не так. Всё дело именно в сроках )

anonymous
()
Ответ на: комментарий от anonymous

а как ты хотел-то на одноядерном чипе?

Я не про физическое параллельное выполнение потоков говорил ) А про правильное равномерное распределение квантов времени на потоки )

но вообще пихать в ядро - это конечно сильно. Напиши юзерспейсовые сервера и выставь им нужный приоритет. И всё.k

Ну а разница то какая? Я написал простенький сервер и менеджер подключений за час, может полтора, всё работает отлично и свои функции выполняет ) Это не «игровые сервера», а сервера настроек, фидбека и отправки данных. Данных очень мало )

l-proger
() автор топика

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

сервера настроек, фидбека и отправки данных

Да, это надо делать именно в драйвере.

unfo ★★★★★
()
Ответ на: комментарий от l-proger

Блин, чувак, да ты вообще вкорне неправ. За каким хером такую хрень пихать в ядро? Ты вообще знаешь для чего нужно ядро ОС и драйверы?

А давай еще web-сервер в ядре замутим, положим туда PHP-скрипт, и нехай у нас будет сайт а прямо из ядра, представляешь как будет клево хакерам сломавшим этот сайт????

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

Dennis7
()
Ответ на: комментарий от l-proger

ну может ты какойто мьютекс или семафор захватываешь в одном треде на слишком долгое время? или неаккуратно пользуешь спинлоки? или чего хуже пользуешь спинлоки вместо мьютексов?

cvv ★★★★★
()
Ответ на: комментарий от l-proger

А чего /proc не заюзать и пихать туда настройки из юзер-спейса?

Ну а разница то какая? Я написал простенький сервер и менеджер подключений за час, может полтора, всё работает отлично и свои функции выполняет ) Это не «игровые сервера», а сервера настроек, фидбека и отправки данных. Данных очень мало )

Разница может быть. Зависит от условий эксплуатации. Если в диких условиях, баг в сервере повалит все ядро. За час-полтора всего не отловишь.

anonymous
()
Ответ на: комментарий от cvv

ну может ты какойто мьютекс или семафор захватываешь в одном треде на слишком долгое время?

Судя по «позднее он будет выпилен и обработка будет сделано по прерыванию», ставлю на busy wait при отключенном CONFIG_PREEMPT :)

tailgunner ★★★★★
()
Ответ на: комментарий от Dennis7

Ты вообще знаешь для чего нужно ядро ОС и драйверы?

Yep

А давай еще web-сервер в ядре замутим, положим туда PHP-скрипт, и нехай у нас будет сайт а прямо из ядра, представляешь как будет клево хакерам сломавшим этот сайт????

Нет, это уже бредово.

За каким хером такую хрень пихать в ядро?

А вот за каким: с некоего нашего девайса через DMA трансферы в память пишутся данные. Данных много и сливание их в память основного борда, как и обработка - операции очень не дешёвые. У нас критична скорость. И речь не о секундах, а о _микро_ секундах! Так вот. Среди данных надо найти N паттернов, обработать их и отослать о них инфу (несколько байт) на центральный комп пока что по Ethernet (позднее свой интерфейс на основе SPI будет, но пока вот Ethernet ибо уже долго на нём работаем и времени на новый пока нет).

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

Что сейчас делается: инициируются DMA трансферы, каждые N байт (относительно большое количество) вызывается прерывание, обработчик прерывания рассчитывает сколько страниц памяти уже слилось, апдейтит их в кеше CPU и ставит worker-потоку в очередь на обработку. Таким образом данные обрабатываются параллельно с их сливанием ) + Как только находится необходимый паттерн - он тут же отправяется по сети на центральный комп! Сливание и обработка в худшем случае занимают 20 мс. То есть почти всегда такой подход себя оправдывает, т.к. паттерны данных в памяти расположены близко друг к другу и не надо ждать сливания всей порции данных, чтобы как раньше потом передать в юзер мод и там ещё потом обработать.

Если у тебя есть идеи как пропихнуть обработчик прерываний в юхер мод - милости прошу, излагай )

l-proger
() автор топика
Ответ на: комментарий от l-proger

Если у тебя есть идеи как пропихнуть обработчик прерываний в юхер мод - милости прошу, излагай )

А не надо пропихивать обработчик. Делаешь блокирующий read, и юзермод-приложение вызывает его; когда данных достаточно, обработчик прерывания разблокирует приложение, оно получает данные, ищет паттерн и отсылает сообщение по сети. Конечно, это уже не микросекунды, а десятки или даже сотни микросекунд, но передача управления воркеру и выдача сообщения в сеть - тоже операции нетривальные.

Сливание и обработка в худшем случае занимают 20 мс

20 миллисекунд? Даже говорить не о чем.

tailgunner ★★★★★
()

tcp сервера никто не пишет с помощью тредов. ъ пасаны делают так:

мастер поток создает несколько дочерних потоков (обычно по количеству ядер) и создает ассептор на сокет. как только клиент пытается подключится - мастер использует хитрый алгоритм распределения нагрузки - передает клиентский сокет на один из дочерних потоков. обработка данных (например обработка самого протокола cgi, fcgi + некая логика) внутри потока происходит строго асинхронно. для этого используется epoll

некоторые (boost::asio например. пруф линк лень искать) считают что ассептор не должен быть один и находится в мастере. те пасаны создают ассептор в каждом дочернем потоке. но суть от этого сильно не меняется

punya ★★
()
Ответ на: комментарий от punya

tcp сервера никто не пишет с помощью тредов. ъ пасаны делают так:

Передай ъ посонам, чтобы занимались своей вебелью. Вебельные подходы нафиг не нужны для того, чтобы скогнфигурировать устройство.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Среди данных надо найти N паттернов, обработать их и отослать о них инфу (несколько байт)
...
каждые N байт (относительно большое количество) вызывается прерывание, обработчик прерывания рассчитывает сколько страниц памяти уже слилось

Делаешь блокирующий read, и юзермод-приложение вызывает его; когда данных достаточно, обработчик прерывания разблокирует приложение, оно получает данные, ищет паттерн и отсылает сообщение по сети.

В его случае, вероятно, есть смысл искать паттерн в драйвере и делать copy_to_user только для тех самых нескольких байт.

LamerOk ★★★★★
()
Ответ на: комментарий от tailgunner

понял вебель как веб-дривен

чтобы сконфигурировать устройство не пишут на си tcp сервера. но если у тс в одном месте пороху много то пускай осилит простейший асинхронный сервер в 1 поток. готовых примеров вагон

punya ★★
()
Ответ на: комментарий от punya

чтобы сконфигурировать устройство не пишут на си tcp сервера.

Это да, но у ТС это временная мера, насколько я понял. Дальше будет SPI.

tailgunner ★★★★★
()
Ответ на: комментарий от LamerOk

вероятно, есть смысл искать паттерн в драйвере и делать copy_to_user только для тех самых нескольких байт.

Нет. Если делается выход в юзерспейс, то пусть и поиск делается там. Если паттерн есть не во всех пакетах, может, и есть смысл искать в ядре, но отнюдь не факт.

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

Гм... Да, прикольно, да только это нафиг не надо.

Dennis7
()

Давно уже придумано, что есть задачи, за которые отвечает ядро ОС, а есть задачи для user-spaace. И не надо их понапрасну «смешивать».

Dennis7
()

Вот скажи мне, упоротый, о каких таких микросекундных задержках может идти речь, если данные предлагается гонять по сети? Даже если на другом конце отвечалка тоже в ядро вкрячена, по сравнению с latency ethernet'а время переключения из kernel в userspace будет пренебрежимо мало. Это даже в том случае, если хосты в одной сети находятся, а если нет? Для IP-сетей latency измеряется в лучшем случае в миллисекундах, даже если ты в драйвере eth0 свой сервер будешь крутить. Короче, либо тебе не нужнен доступ к своему поделию через TCP/IP, и тогда информацию из драйвера надо сливать не через сеть, а через что-то более быстро, неказистое и дружественное по отношению к ядру, либо тебе отчего-то нужна сеть, но тогда твои рассуждения о latency бессмысленны.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.