FreeBasic
Главная
Вход
Регистрация
Четверг, 28.03.2024, 15:48Приветствую Вас Гость | RSS
[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Форум » Freebasic » Вопросы по языку FreeBasic » Как выполнять неблокирующее чтение файла /dev/input/event???
Как выполнять неблокирующее чтение файла /dev/input/event???
mashakovmaratДата: Четверг, 22.08.2019, 19:04 | Сообщение # 1
Сержант
Группа: Пользователи
Сообщений: 36
Репутация: 0
Статус: Offline
Думаю, теперь могу  сформулировать свою проблему максимально точно.
Необходимо организовать неблокирующее чтение файла /dev/input/event.
У меня, разумеется, Linux. Платформа ARM.
Вроде как есть решения на СИ, но, судя по всему, FB не может выполнить требуемой задачи при использовании функций библиотек СИ, им - Фрибейсиком, поддерживаемых.


Сообщение отредактировал mashakovmarat - Четверг, 22.08.2019, 19:07
 
DarkDemonДата: Пятница, 23.08.2019, 03:46 | Сообщение # 2
Полковник
Группа: Друзья
Сообщений: 188
Репутация: -2
Статус: Offline
Понимаешь, во всём разумном мире чтение файлов и так неблокирующее.
Нужно разобраться что за файл такой чудесный. Вслепую твою проблему не решить,
надо щупать руками. Скинул бы хотя бы код, почитали бы, мне он не нужен, нет планшета,
а ошибку узреть могу, вдруг там совсем банальная какая-нибудь хрень.

Цитата mashakovmarat ()
Вроде как есть решения на СИ, но, судя по всему, FB


Большую часть того, что может си, FB - тоже может. И уж самую базу ввода-вывода - стопудово.


Сообщение отредактировал DarkDemon - Пятница, 23.08.2019, 03:46
 
haavДата: Пятница, 23.08.2019, 07:10 | Сообщение # 3
Генералиссимус
Группа: Администраторы
Сообщений: 1361
Репутация: 49
Статус: Offline
Цитата DarkDemon ()
Большую часть того, что может си, FB - тоже может. И уж самую базу ввода-вывода - стопудово.




Леха, х.з. как там под ARM компиль работает. 

Цитата mashakovmarat ()
/dev/input/event.


В данном каталоге всякие EOF работать не будут , потому что по сути ты не с файлами на жестком диске работаешь , а с оперативкой. Хотя линуксоиды все считают файлами. Для определения конца "файла" , используется метод получения ошибки при чтении. То есть читаешь пока не будет ошибки , как произошла ошибка, значит конец "файла". 

В остальном подсказать\помочь не смогу. Я уже писал, что у меня ARM нет , а так гадать бесполезно.


Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
mashakovmaratДата: Пятница, 23.08.2019, 13:26 | Сообщение # 4
Сержант
Группа: Пользователи
Сообщений: 36
Репутация: 0
Статус: 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
Репутация: -2
Статус: 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
Репутация: 49
Статус: Offline
Цитата mashakovmarat ()
Вроде как есть решения на СИ


А где это решение?

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

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


Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
mashakovmaratДата: Пятница, 23.08.2019, 17:49 | Сообщение # 7
Сержант
Группа: Пользователи
Сообщений: 36
Репутация: 0
Статус: 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
Репутация: 49
Статус: 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
Репутация: -2
Статус: 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
Репутация: 49
Статус: Offline
Цитата
Но смущают меня эти нагромождения с мьютексами. Кого мы и от чего защищаем
в мизерной программе не понятно.


1) переменная bExit , которая может одномоментно читаться в разных потоках
2) вывод в терминал. Из разных потоков посыплется мусор в место вывода кроме нужной инфы. Потоки кстати создал специально, чтобы показать что инфа из "файла" читается и выводится независимо (асинхронно) и не будет тормозить основной поток программы.

---------------------------------------------------------------

Сообщения, не относящиеся к данной теме перенес сюда


Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
mashakovmaratДата: Воскресенье, 25.08.2019, 18:06 | Сообщение # 11
Сержант
Группа: Пользователи
Сообщений: 36
Репутация: 0
Статус: 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-е опечатка???

:-) разобрался.
Очень удобная тема.
 
Форум » Freebasic » Вопросы по языку FreeBasic » Как выполнять неблокирующее чтение файла /dev/input/event???
  • Страница 1 из 1
  • 1
Поиск: