resetowanie urządzenia USB

W dniu 05.03.2018 o 08:32, Jarosław Sokołowski pisze:

Zostawię tylko info dla potomnych, bo odpowiedzi Jarka są tradycyjnie bezużyteczne:

Z manuala funkcji read i write: On error, -1 is returned, and errno is set appropriately.

I tego wspomniane funkcje read/write nie robią jeśli urządzenie zniknie.

Reply to
Zbych
Loading thread data ...

Prawda. Mówię o sytuacji "domyślnej" i ftdi.

Reply to
Adam Wysocki

Jeśli mówisz o inode, to tak, ale dowiązanie nazwy do inode znika od razu, gdy jest usunięte.

Reply to
Adam Wysocki

Spodziewałbym się EIO. Ciekawe, czemu tak się nie dzieje (nie sprawdzałem, bo teraz nie mam jak, ale wierzę).

Reply to
Adam Wysocki

Ja zazwyczaj używam IO w wersji nieblokującej (O_NONBLOCK), z ciekawości muszę sprawdzić czy bez tej flagi też jest problem z sygnalizacją błędów.

Reply to
Zbych

Problem nie jest w prymitywach read/write, bo one nie wiedzą, że piszą do urządzeń to raz. Dwa to jest konsekwencja VFS, trzymania otwartego uchwytu w kontekście VFS io. Zjawisko, które powoduje opisywany problem jest bardziej skomplikiwany, nie jest wadą ale kkonsekwecja użycia wartswy API gdzie mamy read//write Ominięcie tego problemu to komunikacja zurządzeniem nie przez read/write ale bezpośrednio z driverem urządzenia (i tracąc wszystkie inne zalety użycia warstwy gdzie mamy read/write).

Reply to
Marek

W sumie nie powinno to nic zmieniać. Spodziewałbym się, że po odpięciu urządzenia select() zwróci odczytywalność, a read() zwróci 0 (ale nie sprawdzałem).

Tak się składa, że mam teraz na tapecie program, który gada z ttyACM (moduł cdc_acm) blokującym I/O (naprzemiennie pisze do portu i czeka na odpowiedź). Po odpięciu kabelka blokujący read() zwrócił 0 (EOF), a późniejszy tcdrain (wywołujący ioctl TCSBRK) -1 (errno = EIO).

Dodatkowy test pokazał, że gdy read() zwróci EOF, to kolejny read() również zwraca EOF, ale kolejny write() zwraca -1 z errno = EIO. Kołacze mi się po głowie, że w przypadku socketów zachowanie read() było inne (gdy zwrócił EOF, to kolejny read() zwracał błąd), ale głowy za to uciąć nie dam -- może mi się coś przywidziało.

Nie wiem czy cokolwiek zmienia fakt, że urządzenie nie jest podłączone bezpośrednio, tylko przez "przejęcie" portu w VirtualBox (ten Linux chodzi w wirtualce na Windows 7). Niby nie powinien.

Reply to
Adam Wysocki

Byle nie tak :)

formatting link

Reply to
Adam Wysocki

Zacząłem to jeszcze raz sprawdzać i na ubuntu 14 (kernel 4.4.0) mam tak:

  1. write zwraca błąd i errno=5 (EIO, Input/output error) jeśli urządzenie zniknie, niezależnie czy używam trybu blokującego czy nie.
  2. read w trybie blokującym czeka na dane, jak wypnę w trakcie czekania wtyczkę to przerywa czekanie zwracając 0, czego nie traktuję jako błąd. Kolejne wywoływania read zwracają cały czas 0
  3. read w trybie nieblokującym zwraca mi błąd i errno=11 (EAGAIN, Resource temporarily unavailable) gdy wtyczka jest wpięta i nie ma danych do odbioru czyli zachwuje się prawidłowo. Ale za to zwraca 0 (brak błędu) jak wtyczkę wypnę.

Testy z read powtórzyłem też na ubuntu 16 z kernelem 4.4, zachowanie identyczne.

Problem polega na tym, że mam urządzenia z który tylko czytam dane (skanery, klawiatury) i takie zachowanie read jest delikatnie mówiąc irytujące.

Reply to
Zbych

Wartość 0 oznacza EOF ("koniec pliku", zamknięte połączenie, koniec strumienia danych). To coś innego niż brak danych (bo wtedy jak sam zauważasz blokujący read poczeka, a nieblokujący zwróci EAGAIN).

Hmm, jak dla mnie jest prawidłowe. Po prostu read() nie ma prawa zwrócić

0, jeżeli urządzenie jest podłączone i działa, ale nie ma danych. Wartość 0 oznacza, że kanał komunikacyjny został zamknięty i dane się skończyły (to nie to samo, co chwilowy brak danych, które mogą przyjść później, bo strumień jest otwarty; gdy read() zwróci 0, to dane już nie przyjdą).
Reply to
Adam Wysocki

Skoro write potrafi zwrócić kod 'Input/output error', to spodziewałbym się takiego samego kodu błędu po read. To nie jest chwilowy brak danych, który później się pojawią.

Reply to
Zbych

Taka już jest konwencja read(). Chwilowy brak danych jest sygnalizowany przez blokowanie lub EAGAIN, permanentny brak danych przez 0 (EOF). EOF oznacza "zakończ pracę, bo więcej już nie odczytasz". Czy jest to błąd, czy normalna sytuacja, to zależy od założeń.

Zakładam, że wywodzi się to stąd, że read() / write() oryginalnie służą do zapisu / odczytu plików. Gdy czytasz z pliku, to ten plik kiedyś się skończy i nie jest to błąd, podczas gdy nieudany zapis do pliku zawsze jest błędem. Przy strumieniach z urządzeń jest podobnie.

Po prostu odłączenie urządzenia jest traktowane jako koniec strumienia, a nie błąd I/O.

Reply to
Adam Wysocki

Przykład z plikiem chyba nie jest najlepszy, bo EOF "teraz" nie znaczy, że "za chwilę" się tam nic nie pojawi do dalszego czytania. Najprostszy przykład to logi. EOF w przypadku czytania logów to na pewno nie jest błąd, po którym nie masz innego wyjścia jak zamknięcie pliku.

Reply to
Zbych

Zazwyczaj jednak pliki czyta się od początku do końca, a po końcu zamyka. Sytuacja, w której program przewiduje, że plik jeszcze urośnie, jest nietypowa. Większość narzędzi Linuksowych standardowo tak się zachowuje. Jak chcesz przeczytać log "od początku do anulowania" (a nie "od początku do końca tego, co w nim aktualnie jest") to przecież nie używasz cat, tylko tail -f.

Zresztą taki "follow" rodzi problem, jeśli plik zostanie w międzyczasie przycięty, bo wskaźnik pliku nie przesuwa się do początku.

Inna sprawa, że nie da się usunąć pliku, który jest aktualnie otwarty (można usunąć dowiązanie, ale inode zostaje do momentu zamknięcia), więc takie zachowanie read() dla pliku ma sens. Czy ma dla urządzenia... widzę argumenty i za, i przeciw, i pewnie można się kłócić i dyskutować, jak powinno być, ale obecny stan jest taki, że read() zachowuje się tak, a nie inaczej... podejrzewam, że ktoś to przemyślał.

Reply to
Adam Wysocki

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.