lesen von serieller Schnittstelle blockiert



  • Hallo,

    ich versuche gerade mit C anzufangen.

    Und schon bin ich an ein scheinbar unlösliches Problem gestoßen.

    Wenn ich eine serielle Schnittstelle öffne und mit read lese klappt das schon mal ganz gut. Das Problem ist aber dort dass read() aber nur zurckkehrt wenn auch wirklich Daten über die Schnittstelle reinkommen. Sobald man also noch in einer Dauerschleife was anderes machen möchte ist Feierabend.

    Daher bin ich zu iocntl() gekommen um vorher zu sehen ob Daten angekommen sind und erst dann mit read() die Daten zu empfangen.

    Problem dabei ist nur dass es nicht funktioniert.

    Wenn ich nach iocntl() mein read() starte blockiert wieder die Schleife. Als ob ich also kein iocntl() aufrufe. Wenn ich aber jetzt eine Ausgabe mit printf(".") schreibe klappt alles so wie es soll. Eben nur dass der ganze Bildschirm mit Punkten vollgespammt wird. Habe testweise mal printf(".\b") genommern damit der Punkt immer wieder überschrieben wird.

    habe auch mal stattdesen usleep(100) 0,1ms() aber es hilft auch nicht.
    Auch ein sleep(1) half auch nicht.

    Wie kann ich das Problem umgehen oder wie macht man soetwas richitg?

    Das soll erst mal ein Testprogramm zu sein um zu sehen was an der Seriellen Schnittstelle so abgeht. Wenn ich dann das richtige Programm schreibe muss ich sowieso auf Interrupt umsteigen. Aber das kommt später.

    Hier mal ein Beispiel um das ganze zu verdeutlichen:

    for ( ; ; )
        {
    	loop++;
    
    	/* SWB-Bus */
    	IOReturn=ioctl(fdSwb, FIONREAD, &serialBytes);
        /*das funktioniert:*/
        printf(".\b");
    //	/*das hier nicht:*/
    //  usleep(100); 
    	if (IOReturn<0)
    	{
    		perror("ioctl(swb)");	
    	}
    	if ((IOReturn==0)&&(serialBytes>0))
    	{
    		bytesSwb = read(fdSwb, &buffer, sizeof(buffer));
    		if (bytesSwb<0)
    		{
    			perror("read(Swb)");
    			serialSwbCount--;
    		}
    		if (bytesSwb>0)
    		{
    			memmove(bufferSwb+bufferSwbCount, buffer, bytesSwb);
    			bufferSwbCount+=bytesSwb;
    		}
    		if ((serialSwbCount>=serialSwbWait)&&(bufferSwbCount>0))
    		{
    			printf("\n%dSWB: ",serialSwbCount);
    			for (x = 0; x < (bufferSwbCount) ; x++)
    			{
    				c = bufferSwb[x];
    				printf("%02X ",c);
    			}
    			bufferSwbCount=0;
    			serialSwbCount=-1;
    		}
    	}
    
    	/* wait 1ms */
    	usleep(1000);
    	serialSwbCount++;
    	if (serialSwbCount>serialSwbWait)
    	{
    		serialSwbCount=0;
    	}
        }
    

    SIcherlich ist jetzt hier erstmal der Punkt if(bytesSwb==0) unberücksichtigt. Aber für mein Problem ist das erst mal unwichitg.

    Wen es interessiert gibt es den ganzen Quelltext meiner Experimente hier:
    github.com/ingof/smi-server dort dann im Ordner monitor die "smi-monitor.c"

    Wie mache ich das jetzt richtig? mit dem warten auf empangene Bytes?

    Habe riegndwo was von select() gelesen aber vermute dass das irgendwas mit threads zu tun hat und hier nicht weiterhilft. Und soweit bin ich auch noch nicht..

    Bin für jeden Hinweis dankbar.

    Gruß
    gnorf



  • Habe gerade herausgefunden dass ein zweites

    IOReturn=ioctl(fdSwb, FIONREAD, &serialBytes);
    

    vor dem

    bytesSwb = read(fdSwb, &buffer, sizeof(buffer));
    

    hilft.

    Aber schön ist was anderes, oder?



  • Der ioctl aufruf gibt dir die anzahl an zeichen, die noch im stream sind. Wenn sizeof(buffer) größer als der rückgabewert von ioctl ist, block read natürlich.



  • Danke,

    ich glaub das ist es gewesen.... 🙂

    Habe noch dazwischen einen neuen Buffer mit der richtigen Größe für read() erzeugt und dann lief es ohne das printf().
    Seltsamerweise habe ich diese Änderung nochmal rückgängig gemacht und der Fehler tritt nicht mehr auf. 😕

    Dachte dass read() alle vorhandenen Daten in den buffer kopiert und dann zurückkehrt. Dass das blockieren nur auftritt wenn keine Daten vorhanden sind


Anmelden zum Antworten