Hallo Forum, in meinem uClinux wird eine uart Schittstelle abgefragt. nun habe ich die Funktionen select(), setitimer() und sleep(). Alle verwenden den systemcall SIGALRM (14), glaube ich. Nun wird ja bei select() nicht unbedingt gewartet bis der SIGALRM kommt (timout). nun geht das Programm weiter und es wird setitimer() aufgerufen. ist der SIGALRM von select noch activ und kommt dem vom Timer zuvor gibts einen Konflikt. So zumindest meine erklärung warum select() in dieser Kombination nicht mehr sauber funktioniert. Kann das sein, und wenn ja, hat jemand eine Idee wie man sleep(), select() und setitimer() entkoppeln kann ohne jedesmal zu warten bis der vorher initzierte SIGALRM gekommen ist? Vielen Dank im Voraus Feu
Ralph Feuchter schrieb: > Hallo Forum, > in meinem uClinux wird eine uart Schittstelle abgefragt. nun habe ich > die Funktionen select(), setitimer() und sleep(). Alle > verwenden den systemcall SIGALRM (14), glaube ich. select() hat nichts mit SIGALRM am Hut. > Nun wird ja bei select() nicht unbedingt gewartet bis der SIGALRM kommt > (timout). nun geht das Programm weiter und es wird setitimer() > aufgerufen. ist der SIGALRM von select noch activ und kommt dem vom Timer > zuvor gibts einen Konflikt. Das kann eigentlich niht sein. > So zumindest meine erklärung warum select() in dieser Kombination nicht > mehr sauber funktioniert. Was heißt denn "nicht mehr sauber"? Was passiert? Sind noch andere Signale im Spiel? Bedenke, daß select() wie jeder system call generell durch Signale unterbrochen wird. > Kann das sein, und wenn ja, hat jemand eine Idee wie man sleep(), > select() und setitimer() entkoppeln kann ohne jedesmal zu warten bis der > vorher initzierte SIGALRM gekommen ist? Funktionen, die intern SIGALRM nutzen, werden nicht einfach einen Timer übrig lassen, der dann irgendwann auf einmal noch ein Signal generiert. Probleme mit sleep() und setitimer() dürften eigentlich nur auftreten, wenn du mit setitimer() einen Timer definierst, und bevor der abgelaufen ist, sleep() aufrufst. Vielleicht kannst du nanosleep() verwenden. Das ist ein eigener system call und greift nicht auf SIGALRM zurück.
vielen Dank für die schnelle Antwort. Arbeiter schrieb: > Probleme mit sleep() und setitimer() dürften eigentlich nur auftreten, > wenn du mit setitimer() einen Timer definierst, und bevor der abgelaufen > ist, sleep() aufrufst. das schein tatsächlich das Problem zu sei. mit setitimer setze ich einen Timer der eine while schleife abbricht falls read() nicht den gewünschten string empfangen hat. Kommt der string an ist der timer noch aktiv. den wollte ich mit void timer_stop(void) { struct itimerval it_val; it_val.it_value.tv_sec = 0; it_val.it_value.tv_usec = 0; it_val.it_interval.tv_sec = 0; //only once (no interval it_val.it_interval.tv_usec = 0; setitimer(ITIMER_REAL, &it_val, NULL); } stoppen, aber scheinbar funktioniert das nicht so. die Funktion die den Timer startet + Handler: volatile int timer_status; int timer_start(sec, usec, interv_sec, interv_usec) { struct itimerval it_val; if (SIG_ERR == signal(SIGALRM, (void (*) (int)) timer_exp)) { perror("Unable to catch SIGALRM"); // exit(1); } timer_status = 1; it_val.it_value.tv_sec = sec; it_val.it_value.tv_usec = usec; it_val.it_interval.tv_sec = interv_sec; //only once (no interval it_val.it_interval.tv_usec = interv_usec; setitimer(ITIMER_REAL, &it_val, NULL); return timer_status; } void timer_exp(void) //interupt handler { printf("--- timeout ---.\n"); timer_status = 0; } Vielleicht liegt es auch daran, dass ich die structur in der Stop-funktion neu definiere. ich weiss aber nicht, wie ich es anders machen soll da der Timer von einer Funktion aus gestartet wird. auf den konflikt mit select() bin ich gekommen, da der damit definierte select-timeout auch unkontrolliert getriggert wird. Was vielleicht noch wichtig ist, ich sende mehrere Commandos nacheinander. wobei jedesmal select(), setitimer() und sleep() vorkommt. den tip mit nanosleep()werde ich einbaun. danke!
Ralph Feuchter schrieb: > mit setitimer setze ich einen > Timer der eine while schleife abbricht falls read() nicht den > gewünschten string empfangen hat. Einen Timer zu verwenden, um einen read() abzubrechen, ist suboptimal. Wenn Du select() verwendest, dann weisst Du auch, wann wieviel im Input zur Verfügung steht. Das kannst Du auf jeden Fall sicher abholen, ohne dass der read() hängenbleibt. Desweiteren gibt es gerade für UARTs unter UNIX/Linux die Möglichkeit, einen read() auf ein TTY komfortabel in einen Timeout laufen zu lassen, d.h. den read() vorzeitig zu beenden, wenn nix kommt. Das Timeout kann in Zehntelsekunden (deciseconds) eingestellt werden. Schau Dir die man page für termios(3) an, z.B.: http://linux.die.net/man/3/termios Beachte insbesondere die Bemerkungen zu VMIN und VTIME.
Frank M. schrieb: > Wenn Du select() verwendest, dann weisst Du auch, wann wieviel im Input > zur Verfügung steht. Das kannst Du auf jeden Fall sicher abholen, ohne > dass der read() hängenbleibt Schon klar, aber die Schnittstelle ist ja langsamer als die ganze Ausleseprozedur. select() wird getriggert bei VMIN=0 mit dem ersten byte was ankommt, glaube ich. und um den ganzen Rest noch abzuholen der durch die Schnittstelle kommt, muss ich ja mehrere male read() auffordern um alles abzuholen. Wenn ich weiss wie gross der string ist kann ich das mit einem einzigsten read() und VTIME machen. Dazu brauche ich aber die buffergrösse. Also für lange Datensätze geht das nicht. Oder meinst du ich solle select() jedesmal vorm read() Aufruf bemühen. Jetzt mache ich es nur einmal um zu merken, wenn das modem anfängt zu antworten.
Ralph Feuchter schrieb: > auf den konflikt mit select() bin ich gekommen, da der damit definierte > select-timeout auch unkontrolliert getriggert wird. > > Was vielleicht noch wichtig ist, ich sende mehrere Commandos > nacheinander. wobei jedesmal select(), setitimer() und sleep() vorkommt. Wie schon gesagt wurde: Jeder blockierende System Call, also auch select() wird durch Signale unterbrochen. Wenn du also noch von vorher irgendwo einen Timer hast, der gerade dann abläuft, wenn select() wartet, dann fliegst du der Funktion raus. Das hat dann aber nichts speziell mit SIGALRM zu tun, sondern würde bei jedem anderen Signal genauso passieren. Wenn der Aufruf mit -1 zurückkehrt und errno == EINTR ist, dann ist select() durch ein Signal unterbrochen worden, und du mußt es nochmal aufrufen.
Ralph Feuchter schrieb: > Schon klar, aber die Schnittstelle ist ja langsamer als die ganze > Ausleseprozedur. Eben. Mach einen read() von jeweils einem Byte mit VMIN=0 und VTIME=x (>0) und alles ist gut. Wenn Du befürchtest, dass dadurch die verbratene CPU-Zeit in die Höhe schnellt, kann ich Dich beruhigen: bei den niedrigen Übertragungsgeschwindigkeiten passiert da gar nichts.
vielen Dank für den tip mit EINTR ==1 und -1; werde es implementieren, aber nochmal zurück zur Frage (vielleicht ist sie auch zu basal), wie kann ich einen timer der einmal losgelaufen ist wieder stoppen ohne das er später im Programmablauf was anrichtet. Durch eine anderen Funktion alle it_value = 0 setzen hilft nicht so richtig, glaube ich.
Ralph Feuchter schrieb: > wie > kann ich einen timer der einmal losgelaufen ist wieder stoppen ohne das > er später im Programmablauf was anrichtet. Durch eine anderen Funktion > alle it_value = 0 setzen hilft nicht so richtig, glaube ich. Das ist keine Frage des Glaubens. Zitat aus man setitimer: A timer which is set to zero (it_value is zero or the timer expires and it_interval is zero) stops.
klar, dann sollte es eigentlich gehen. werde mal Frank M. schrieb: > read() von jeweils einem Byte mit VMIN=0 und VTIME=x > (>0) ausprobieren und melde mich wieder vielen Dank
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.