Как выполнять неблокирующее чтение файла /dev/input/event???
|
|
mashakovmarat | Дата: Четверг, 22.08.2019, 19:04 | Сообщение # 1 |
Сержант
Группа: Пользователи
Сообщений: 36
Статус: Offline
| Думаю, теперь могу сформулировать свою проблему максимально точно. Необходимо организовать неблокирующее чтение файла /dev/input/event. У меня, разумеется, Linux. Платформа ARM. Вроде как есть решения на СИ, но, судя по всему, FB не может выполнить требуемой задачи при использовании функций библиотек СИ, им - Фрибейсиком, поддерживаемых.
Сообщение отредактировал mashakovmarat - Четверг, 22.08.2019, 19:07 |
|
| |
DarkDemon | Дата: Пятница, 23.08.2019, 03:46 | Сообщение # 2 |
Полковник
Группа: Друзья
Сообщений: 188
Статус: Offline
| Понимаешь, во всём разумном мире чтение файлов и так неблокирующее. Нужно разобраться что за файл такой чудесный. Вслепую твою проблему не решить, надо щупать руками. Скинул бы хотя бы код, почитали бы, мне он не нужен, нет планшета, а ошибку узреть могу, вдруг там совсем банальная какая-нибудь хрень.
Цитата mashakovmarat ( ) Вроде как есть решения на СИ, но, судя по всему, FB
Большую часть того, что может си, FB - тоже может. И уж самую базу ввода-вывода - стопудово.
Сообщение отредактировал DarkDemon - Пятница, 23.08.2019, 03:46 |
|
| |
haav | Дата: Пятница, 23.08.2019, 07:10 | Сообщение # 3 |
Генералиссимус
Группа: Администраторы
Сообщений: 1361
Статус: Offline
| Цитата DarkDemon ( ) Большую часть того, что может си, FB - тоже может. И уж самую базу ввода-вывода - стопудово.
Леха, х.з. как там под ARM компиль работает.
Цитата mashakovmarat () /dev/input/event.
В данном каталоге всякие EOF работать не будут , потому что по сути ты не с файлами на жестком диске работаешь , а с оперативкой. Хотя линуксоиды все считают файлами. Для определения конца "файла" , используется метод получения ошибки при чтении. То есть читаешь пока не будет ошибки , как произошла ошибка, значит конец "файла".
В остальном подсказать\помочь не смогу. Я уже писал, что у меня ARM нет , а так гадать бесполезно.
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
mashakovmarat | Дата: Пятница, 23.08.2019, 13:26 | Сообщение # 4 |
Сержант
Группа: Пользователи
Сообщений: 36
Статус: Offline
| Цитата DarkDemon ( ) Скинул бы хотя бы код, почитали бы
DarkDemon, приветствую.
Чтобы все было максимально просто, выкладываю следующий код (он на основе, как бы, туториала с форума freebasic.net). Тут есть все необходимое. Я только добавил блок под комментарием 'open pipe и соответствующие требуемые переменные.
За основу взял работу с /dev/input/event1 - здесь на моем компе (Linux Debian 32 бита) заведена мыша, так что, если что меняйте под себя.
Код ' 2018-08-14, MrSwiss '
' thread data-type (typedef struct in C-language) Type thr_data ' a default initialized data-type As ZString * 9 sTime = "" ' actual payload (user data, the time) As Boolean cont = TRUE ' thread procedure control (loop run/quit) End Type
Dim As thr_data dt1 ' we need one of above types for this thread Dim Shared As Any Ptr MLock ' define the common MUTEX (to all threads!)
const EVENT_FILE = "sudo cat /dev/input/event1" Dim As Byte tsFreeFileNumber Dim As Long evFile Dim As Byte Ptr tsev
' the threads 'worker' procedure Sub thr_run( ByVal pd As Any Ptr ) ' ptr 'pd', provides access to above type Dim As thr_data Ptr ptd = pd ' convert 'any ptr' to 'data-type ptr' !!! While ptd->cont ' run, until Boolean turns FALSE (thread quit) MutexLock(MLock) ' lock mutex (for as long as we process data) If ptd->sTime <> Time Then ptd->sTime = Time ' update time, when changed only! End If Color 12 ' hilight thread output (bright red) Locate 1, 72 : Print ptd->sTime; ' output whatever the thread deliveres MutexUnLock(MLock) ' free mutex (any other thread can use it now) Sleep(200, 1) ' take a break (length defines time accuracy!) Wend ' 200 mS is sufficiently accurate and saves _ End Sub ' a lot of resources, for other processes!
' get our thread up and running MLock = MutexCreate() ' create common MUTEX (mutually exclusive) Dim As Any Ptr thread = ThreadCreate(@thr_run, @dt1) ' create thread (one shot) If thread = 0 Then ' error check (no error = no action) Print "thread creation failed! "; ' on error, inform user, then wait Beep : Sleep : End 1 ' on user action --> error-quit End If ' thread started successfully
' open pipe tsFreeFileNumber = FreeFile evFile = Open Pipe(EVENT_FILE For Input As #tsFreeFileNumber) If evFile = -1 Then Print "ERROR : EVENT IS NOT ACCESSIBLE"; Beep : Sleep : End 1 ' on user action --> error-quit EndIf
' ===== start main ===== Dim As String hi = "Welcome, to FreeBASIC's threading ... "
Width 80, 25 ' define standard console size Locate 1, 60 : Print "thread -->" ' since we don't use cls, once only needed Locate 21, 1 : Print "press a key, to EXIT!"
Do MutexLock(MLock) ' MAIN run's exclusive (other thread stopped) Color 7 ' reset color to default Locate 11, 2 : Print "MAIN --> " + hi; ' this is just for control purposes ' do any other mighty important stuff from here ...
tsev = Allocate(16*SizeOf(Byte)) Get #tsFreeFileNumber,,*tsev,16 locate 5,10: color 10: ? *tsev; DeAllocate tsev
' finish mighty important before this line MutexUnLock(MLock) ' release MAIN lock Loop Until Len(InKey()) > 0 ' on user action --> exit program ' ===== end main ===== ' clean up ... in oposite order of creation! dt1.cont = FALSE ' stop thread procedure ThreadWait(thread) ' wait for thread stop MutexDestroy(MLock) ' delete mutex
Добавлено (23.08.2019, 13:31) ---------------------------------------------
Цитата haav ( ) В остальном подсказать\помочь не смогу. Я уже писал, что у меня ARM нет , а так гадать бесполезно. haav, здравствуйте.
Тут не обязательно ARM - абсолютно та же ситуация и на настольном PC (Linux Debian 32 бита).Добавлено (23.08.2019, 13:34) --------------------------------------------- И еще, может это покажется глупостью, но может есть смысл обратиться к /dev/input/event не через pipe, а open com ???
Сообщение отредактировал mashakovmarat - Пятница, 23.08.2019, 13:28 |
|
| |
DarkDemon | Дата: Пятница, 23.08.2019, 14:33 | Сообщение # 5 |
Полковник
Группа: Друзья
Сообщений: 188
Статус: Offline
| Цитата haav ( ) Леха, х.з. как там под ARM компиль работает.
Вроде "linux он и в африке linux"? По идее без разницы должно быть.
Цитата haav ( ) Хотя линуксоиды все считают файлами.
Вот и не понимаю, почему оно стопорится, как бы не должно. Обычный блин файл. Ух нагородили пингвы. Чтобы включить эвенты ошибок, насколько понимаю там надо писать в QB режиме и ключик в компиляторе указать для ON ERROR. И тут как понимаю не вариант это всё, потому что до ошибки мол не дойдёт, хотя если так подумать может сначала возникает ошибка, а повторно чтение уже даёт ступор. Короче челу надо все эти моменты тестировать. Но циклиться оно не должно, это уже алгоритмический косяк где-то.
Цитата mashakovmarat ( ) open com
Ты пробовал простой OPEN? В т.ч. бинарно? Это аналог сишного fopen, но работает вроде не идентично. COM - это другое, это работа с COM портом, тебе оно не надо. Вообще нагорожено пипец, прога 100 строк не превышает, а уже мьютексы, зачем? У тебя может из-за этого и идёт циклинг, там надо анализировать, сначала без дебрей лучше. Проще надо быть, сделай проще для начала. Заведи поток, пусть он обращается к глобалке, глобалку-флаг переключаешь - поток убивается(внутри потока цикл, выход из которого идёт по флагу, в цикле ты должен порциями читать свои данные, можешь попробовать LINE INPUT). Не работает так? - тогда нужно курить как создавать и убивать поток средствами API самого линукса. Хотя как по мне прога, которая будет постоянно создавать и убивать поток - это херовая прога, потому что промежутки между работой потоков будут приводить к возможной потере данных. но если другого выхода у тебя не будет - как бы тут возразить нечего.
Сообщение отредактировал DarkDemon - Пятница, 23.08.2019, 14:35 |
|
| |
haav | Дата: Пятница, 23.08.2019, 16:44 | Сообщение # 6 |
Генералиссимус
Группа: Администраторы
Сообщений: 1361
Статус: Offline
| Цитата mashakovmarat ( ) Вроде как есть решения на СИ
А где это решение?
И кстати , да действительно при чтении таким способом сишная функция fREAD ждет пока устройство не проснется. Похоже на то, что в вызове fREAD включается бесконечный цикл, пока например не подвигаешь мышью или не поводишь пальцем по экрану.
Мне кажется для программирования подобного , надо почитать не одну умную книжку. Язык программирования тут неважен , хотя удобнее если это будет СИ.
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
mashakovmarat | Дата: Пятница, 23.08.2019, 17:49 | Сообщение # 7 |
Сержант
Группа: Пользователи
Сообщений: 36
Статус: Offline
| Цитата haav ( ) А где это решение? В принципе, его можно "вымучать" ))) - https://it.wikireading.ru/1029 - https://stackoverflow.com/questions/36673972/non-blocking-read-on-pipe - https://ps-group.github.io/os/nonblocking_io_posix#wow2
Так получилось, что с СИ я особо не дружу, но, начав работать с Linux, видимо освоить его придется.Добавлено (23.08.2019, 17:54) --------------------------------------------- Также очень интересна в СИ функция select. Добавлено (23.08.2019, 18:03) --------------------------------------------- Вот еще неплохая статья https://en.wikipedia.org/wiki/Asynchronous_I/O#Examples
Обширная тема, прям, е-мое, целая парадигма ))) .. параллельное программирование ..беда.
|
|
| |
haav | Дата: Суббота, 24.08.2019, 09:38 | Сообщение # 8 |
Генералиссимус
Группа: Администраторы
Сообщений: 1361
Статус: Offline
| Я тут намолевал код, который у меня в принципе работает (если что, то у меня linux mint 64-bit). Читает асинхронно "файл" /dev/input/mouse0. Естественно я не искал и не изучал структуру "файла" mouse0. Просто попробовал считать первые два байта и они уж очень похожи на дельту мыши.
Скомпилированный код нужно запускать с правами root:
Код #Include "crt.bi" #include "crt/unistd.bi" #include "crt/fcntl.bi"
dim shared as Byte bExit
dim shared as any ptr handle
Dim Shared As Any Ptr MLock
sub readMem(p as any ptr) dim as Byte ptr ie = callocate(10) dim as Long handle = open_("/dev/input/mouse0", O_RDONLY or O_NONBLOCK) If handle <> -1 Then do read_(handle, ie, 10) MutexLock(MLock) Color 1 Locate 1 ,10 dim as byte bXdelta , bYdelta bXdelta = ie[1] bYdelta = ie[2] ? bXdelta , bYdelta if bExit then exit do MutexUnLock(MLock) fflush(stdout) Loop Close_(handle) EndIf cls deallocate(ie) ? "Thread to be ended" End sub
cls
MLock = MutexCreate()
dim as any ptr thread = threadcreate ( @readMem() )
do MutexLock(MLock) Color 12
Locate 3, 30
? time MutexUnLock(MLock) sleep(100) Loop until multikey(1)
MutexLock(MLock)
bExit = 1
MutexUnLock(MLock)
ThreadWait(thread)
MutexDestroy(MLock)
? "End Program"
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
DarkDemon | Дата: Суббота, 24.08.2019, 11:37 | Сообщение # 9 |
Полковник
Группа: Друзья
Сообщений: 188
Статус: Offline
| Поставил FB на бубунту. Сломал копчик, но поставил.
Короче EOF и LOF для пайпов не работают. У меня /dev/input/event2 - оказалось мышкой. Если в терминале через cat отображать голые данные, то по отклику +/- нормально. Если же в проге открывать PIPE и читать через INPUT - то вообще полная жопа. Читает рывками, как-то очень криво. Пайпы не канают короче, во всяком случае FB-шная реализация.
Добавлено (24.08.2019, 13:40) ---------------------------------------------
Код твой работает, кстати. Но смущают меня эти нагромождения с мьютексами. Кого мы и от чего защищаем в мизерной программе не понятно.
Сообщение отредактировал DarkDemon - Суббота, 24.08.2019, 13:44 |
|
| |
haav | Дата: Суббота, 24.08.2019, 18:12 | Сообщение # 10 |
Генералиссимус
Группа: Администраторы
Сообщений: 1361
Статус: Offline
| Цитата Но смущают меня эти нагромождения с мьютексами. Кого мы и от чего защищаем в мизерной программе не понятно.
1) переменная bExit , которая может одномоментно читаться в разных потоках 2) вывод в терминал. Из разных потоков посыплется мусор в место вывода кроме нужной инфы. Потоки кстати создал специально, чтобы показать что инфа из "файла" читается и выводится независимо (асинхронно) и не будет тормозить основной поток программы.
---------------------------------------------------------------
Сообщения, не относящиеся к данной теме перенес сюда
Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
|
|
| |
mashakovmarat | Дата: Воскресенье, 25.08.2019, 18:06 | Сообщение # 11 |
Сержант
Группа: Пользователи
Сообщений: 36
Статус: Offline
| Цитата haav ( ) Я тут намолевал код, haav, приветствую!!!
Супер. Работает. Просто вы читали ie[1] и [2], а это время возникновения события. Оно не так быстро меняется. Дельты координат глубже ))), вот они бодренько показывают, что все работает.
В списке сишных функций, поддерживаемых FB (http://users.freebasic-portal.de/freebasicru/helprus/ProPgCruntime.html), находил в списке низкоуровневого ввода\вывода функции _open, _read, но не open_ или read_, которые вы используете. Может на html-е опечатка???
Спасибо большое. Буду пробовать на ARM-е запускать. О результатах отпишусь.
DarkDemon, благодарю за участие!Добавлено (29.08.2019, 15:40) ---------------------------------------------
Цитата mashakovmarat ( ) В списке сишных функций, поддерживаемых FB (http://users.freebasic-portal.de/freebasicru/helprus/ProPgCruntime.html), находил в списке низкоуровневого ввода\вывода функции _open, _read, но не open_ или read_, которые вы используете. Может на html-е опечатка??? :-) разобрался. Очень удобная тема.
|
|
| |
|