Toon posts:

[C|Unix] Van twee streams tegelijk lezen

Pagina: 1
Acties:

Verwijderd

Topicstarter
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?

  • Super_ik
  • Registratie: Maart 2001
  • Nu online

Super_ik

haklust!

door te pollen?

8<------------------------------------------------------------------------------------
Als ik zo door ga haal ik m'n dood niet. | ik hou van goeie muziek


Verwijderd

Topicstarter
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().

[ Voor 48% gewijzigd door Verwijderd op 17-07-2004 14:26 ]


  • igmar
  • Registratie: April 2000
  • Laatst online: 12-05 15:46

igmar

ISO20022

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().
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.

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23-05 18:13
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.

Verwijderd

Topicstarter
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);
}

  • igmar
  • Registratie: April 2000
  • Laatst online: 12-05 15:46

igmar

ISO20022

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.
Buffering is uit te zetten, en dat is in dit soort situaties zelfs wenselijk.

  • igmar
  • Registratie: April 2000
  • Laatst online: 12-05 15:46

igmar

ISO20022

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);
}
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.

  • Robtimus
  • Registratie: November 2002
  • Laatst online: 11:06

Robtimus

me Robtimus no like you

Misschien kun je dan poll gebruiken. Vantevoren moet je het revents van de structs op 0 zetten. De return waarde:
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.
Naderhand ga je dus van alle structs de revents velden af om te kijken welke een event heeft veroorzaakt.

More than meets the eye
There is no I in TEAM... but there is ME
system specs


Verwijderd

Topicstarter
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.
Wat klopt er niet dan? Als er data beschikbaar is valt mijn programma toch uit de while-loop?

  • igmar
  • Registratie: April 2000
  • Laatst online: 12-05 15:46

igmar

ISO20022

Verwijderd 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?
Het nut daarvan ontging me even :) Het lezen van een serieele poort kan niet zonder meer, maar de source bekijken van bv een UPS monitor zou genoeg info moeten geven.

Verwijderd

Topicstarter
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 ]


  • igmar
  • Registratie: April 2000
  • Laatst online: 12-05 15:46

igmar

ISO20022

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);
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

Topicstarter
Inderdaad. Als ik het verander in
C:
1
retval=select(1+fileno(scanner), &rfds, NULL, NULL, &tv);

werkt het wel naar behoren.

  • Robtimus
  • Registratie: November 2002
  • Laatst online: 11:06

Robtimus

me Robtimus no like you

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");
    }
Daar zit toch een klein foutje in: wat als retval negatief is (dus een error) ?
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


  • Super_ik
  • Registratie: Maart 2001
  • Nu online

Super_ik

haklust!

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.

8<------------------------------------------------------------------------------------
Als ik zo door ga haal ik m'n dood niet. | ik hou van goeie muziek


Verwijderd

Topicstarter
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.

  • Super_ik
  • Registratie: Maart 2001
  • Nu online

Super_ik

haklust!

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