Ik heb dus een kassa-programma. Nu leest hij bijvoorbeeld het productnummer in via het toetsenbord, maar dat moet in de toekomst ook met een barcode-scanner kunnen. Deze scanner zit aangesloten op de seriele poort. Nu weet ik natuurlijk niet of de gebruiker de scanner wil gebruiken of het toetsenbord. Als ik van het toetsenbord lees, blocked mijn programma waardoor ik niet tegelijk van de COM-poort kan lezen, en vice versa. Hoe los ik dit op?
door te pollen?
8<------------------------------------------------------------------------------------
Als ik zo door ga haal ik m'n dood niet. | ik hou van goeie muziek
Hoe kijk ik of er data te lezen is op een stream zonder te blocken?
Edit: normaal zou het kunnen met poll() of select(), maar ik heb mijn bestand geopend met fopen() en niet met open().
Edit: normaal zou het kunnen met poll() of select(), maar ik heb mijn bestand geopend met fopen() en niet met open().
[ Voor 48% gewijzigd door Verwijderd op 17-07-2004 14:26 ]
Daar hebben ze de functie fileno() voor bedacht, waarme je de fd van een stream kan opvragen. Het enige wat je niet moet doen is fread() en read() door elkaar gebruiken.Verwijderd schreef op 17 juli 2004 @ 14:18:
Hoe kijk ik of er data te lezen is op een stream zonder te blocken?
Edit: normaal zou het kunnen met poll() of select(), maar ik heb mijn bestand geopend met fopen() en niet met open().
Daarmee ben je er helaas nog niet, want functies als fread/fscanf doen zelf aan buffering. Het kan dus voorkomen dat de onderliggende filedescriptor geen data beschikbaar heeft maar je nog wel data kan lezen met fread/scanf.
Ik heb nu onderstaande code. Als ik iets intyp en op enter druk, geeft select() iets ongelijk aan 0 terug en sluit het programma af. Als ik een streepjescode in scan gebeurt er echter niks.
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| #define SCANNER "/dev/ttyS0" int main() { FILE * scanner; fd_set rfds; struct timeval tv; int retval; scanner=fopen(SCANNER, "r"); do { FD_ZERO(&rfds); FD_SET(fileno(scanner), &rfds); FD_SET(0, &rfds); // stdin tv.tv_sec=1; tv.tv_usec=100000; retval=select(2, &rfds, NULL, NULL, &tv); } while (retval==0); } |
Buffering is uit te zetten, en dat is in dit soort situaties zelfs wenselijk.Soultaker schreef op 17 juli 2004 @ 17:17:
Daarmee ben je er helaas nog niet, want functies als fread/fscanf doen zelf aan buffering. Het kan dus voorkomen dat de onderliggende filedescriptor geen data beschikbaar heeft maar je nog wel data kan lezen met fread/scanf.
select() geeft het aantal descriptors terug in de set die teruggeven wordt. Indien er dus data beschikbaar is zal dat aantal ongelijk zijn aan nul. Je condities kloppen dus niet. Verder is fopen() op een device over het algemeen niet aan te raden.Verwijderd schreef op 17 juli 2004 @ 19:35:
Ik heb nu onderstaande code. Als ik iets intyp en op enter druk, geeft select() iets ongelijk aan 0 terug en sluit het programma af. Als ik een streepjescode in scan gebeurt er echter niks.
C:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #define SCANNER "/dev/ttyS0" int main() { FILE * scanner; fd_set rfds; struct timeval tv; int retval; scanner=fopen(SCANNER, "r"); do { FD_ZERO(&rfds); FD_SET(fileno(scanner), &rfds); FD_SET(0, &rfds); // stdin tv.tv_sec=1; tv.tv_usec=100000; retval=select(2, &rfds, NULL, NULL, &tv); } while (retval==0); }
Misschien kun je dan poll gebruiken. Vantevoren moet je het revents van de structs op 0 zetten. De return waarde:
Naderhand ga je dus van alle structs de revents velden af om te kijken welke een event heeft veroorzaakt.On success, a positive number is returned, where the number returned is the number of structures which have non-zero revents fields (in other words, those descriptors with events or errors reported). A value of 0 indicates that the call timed out and no file descriptors have been selected. On error, -1 is returned, and errno is set appropriately.
More than meets the eye
There is no I in TEAM... but there is ME
system specs
Wat klopt er niet dan? Als er data beschikbaar is valt mijn programma toch uit de while-loop?igmar schreef op 17 juli 2004 @ 21:02:
[...]
select() geeft het aantal descriptors terug in de set die teruggeven wordt. Indien er dus data beschikbaar is zal dat aantal ongelijk zijn aan nul. Je condities kloppen dus niet. Verder is fopen() op een device over het algemeen niet aan te raden.
Het nut daarvan ontging me evenVerwijderd schreef op 17 juli 2004 @ 21:13:
Wat klopt er niet dan? Als er data beschikbaar is valt mijn programma toch uit de while-loop?
Met poll() werkt het wel. Toch vreemd dat select() het dan niet doet.
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| #include <stdio.h> #include <sys/poll.h> int main() { FILE * fp; char buf[15]; struct pollfd pfd; int retval; fp=fopen("/dev/ttyS0", "r"); pfd.fd=fileno(fp); pfd.events=POLLIN; pfd.revents=0; retval=poll(&pfd, 1, 1000); if (retval) { printf("Joepie de poepie, er is data!\n"); } else { printf("Nee, helaas...\n"); } fclose(fp); return 0; } |
[ Voor 9% gewijzigd door Verwijderd op 18-07-2004 12:38 ]
2 is niet goed : n is de grootste filedescriptor in een van de sets + 1. Je fopen zal waarschijnlijk 4 teruggeven, en 4 + 1 == 5. Indien je de waarde te laag neemt zal select() niet alle descriptors in de set meenemen. Pak dus de waarde van laatst geopende filedescriptor, en tel daar 1 bij op. Gewoonweg een grote waarde invullen werkt ook, alleen is dit kwa performance niet aan te raden.Verwijderd schreef op 17 juli 2004 @ 19:35:
Ik heb nu onderstaande code. Als ik iets intyp en op enter druk, geeft select() iets ongelijk aan 0 terug en sluit het programma af. Als ik een streepjescode in scan gebeurt er echter niks.
C:
1 retval=select(2, &rfds, NULL, NULL, &tv);
Inderdaad. Als ik het verander in
werkt het wel naar behoren.
C:
1
| retval=select(1+fileno(scanner), &rfds, NULL, NULL, &tv); |
werkt het wel naar behoren.
Daar zit toch een klein foutje in: wat als retval negatief is (dus een error) ?Verwijderd schreef op 18 juli 2004 @ 12:38:C:
1 2 3 4 5 6 7 retval=poll(&pfd, 1, 1000); if (retval) { printf("Joepie de poepie, er is data!\n"); } else { printf("Nee, helaas...\n"); }
Je moet checken op 3 waarden: < 0 is error, 0 is timeout, > 0 is data beschikbaar.
[ Voor 6% gewijzigd door Robtimus op 18-07-2004 18:42 ]
More than meets the eye
There is no I in TEAM... but there is ME
system specs
je drukt op enter, en dan exit je programma, oftewel, dan wordt je buffer pas doorgegeven en uitgelezen
die scanner vult je buffer wel, maar geeft geen enter. daardoor wordt de data niet doorgegeven en verwerkt.
die scanner vult je buffer wel, maar geeft geen enter. daardoor wordt de data niet doorgegeven en verwerkt.
8<------------------------------------------------------------------------------------
Als ik zo door ga haal ik m'n dood niet. | ik hou van goeie muziek
Dat is niet waar. De karakters van je toetsenbord worden inderdaad gebufferd en pas verstuurd als je op enter drukt. Dit is ook uit te zetten. Alle andere devices en bestanden hebben geen enter nodig om uitgelezen te worden.
owneej? welles een compoort ofzo ge-fopent?
8<------------------------------------------------------------------------------------
Als ik zo door ga haal ik m'n dood niet. | ik hou van goeie muziek
Pagina: 1