Hallo Forum, in einem Programm das ich in C schreibe und das dann auf meinem Embedded Linux (Archlinux ARM Beaglebone Black) läuft, benutze ich system() um eine Checksumme zu überprüfen mittels system("sha1sum -c File.sha1"); Vorher wechsel ich in das entsprechende Verzeichnis usw. Ich weiß, dass ich auch die libs nehmen kann aber das wird halt alles aufwändiger. Und zeitlich wird es dann eng.. In meinem man system() auf dem System steht: RETURN VALUE The value returned is -1 on error (e.g., fork(2) failed), and the return status of the command otherwise. This latter return status is in the format specified in wait(2). Thus, the exit code of the command will be WEXITSTATUS(status). In case /bin/sh could not be executed, the exit status will be that of a command that does exit(127). If the value of command is NULL, system() returns nonzero if the shell is available, and zero if not. system() does not affect the wait status of any other children. Somit gehe ich davon aus das ich den Rückgabewert von sha1sum erhalte. Wenn ich den Befehl direkt aus der Console ausführe und dann echo $? mache bekomme ich 1 angezeigt wenn die Überprüfung nicht passt. In meinem C Programm bekomme ich in dem Fall 0 zurück. Genau dasselbe Problem habe ich mit tar. Wenn ich den Befehl mit system() aufrufe kommt immer 0 zurück. In der Console mein erwarteter Wert... Woran liegt es? Denke an dem sh -c noch dazwischen. Nur wie komme ich denn nun am besten an den Rückgabewert des aufgerufenen Programms in meinem C Programm? Würde es mit fork() und exec() funktionieren? Oder gibt es eine andere elegantere Lösung? Wie gesagt libs würde ich ungern verwenden müsste dann ja tar, sha1sum und eventuell auch nocht ncftp oder wenn ich auf sftp umschwenke unmengen an Code schreiben obwohl es die passenden Programme schon gibt.
Poste ein Minimalbeispiel, das dein Problem reproduziert.
Problem0815 schrieb: > Woran liegt es? Denke an dem sh -c noch dazwischen. Nur wie komme ich > denn nun am besten an den Rückgabewert des aufgerufenen Programms in > meinem C Programm? Indem Du das Programm direkt aufrufst - ohne "sh -c" und ohne cd-Befehl dazwischen. Wieso zeigst Du ein system("sha1sum -c File.sha1"); und erzählst im Text, dass Du vorher noch das Verzeichnis wechselst und dann auch noch irgendwo ein "sh -c" reinwurschtelst? Zeige bitte den system-Aufruf, den Du auch verwendest.
Problem0815 schrieb: > Wie gesagt libs würde ich ungern verwenden müsste dann ja tar, sha1sum > und eventuell auch nocht ncftp oder wenn ich auf sftp umschwenke > unmengen an Code schreiben obwohl es die passenden Programme schon gibt. Naja soooo kompliziert sieht das jetzt nicht aus: ftp://ftp.gnupg.org/gcrypt/binary/sha1sum.c Die main() Funktion hat grad mal 40 Zeichen. Das bisschen Dateien öffnen, Puffer bereitstellen, sha1_init(), sha1_write() und sha1_final() aufrufen - also daran sollte es jetzt nicht scheitern. "Unmengen an Code" sieht anders aus. ;-)
Frank M. schrieb: > Problem0815 schrieb: >> Woran liegt es? Denke an dem sh -c noch dazwischen. Nur wie komme ich >> denn nun am besten an den Rückgabewert des aufgerufenen Programms in >> meinem C Programm? > > Indem Du das Programm direkt aufrufst - ohne "sh -c" und ohne cd-Befehl > dazwischen. "sh -c" ruft system() selber auf
1 | ... |
2 | system() executes a command specified in command by calling /bin/sh -c command, and returns after the command has been completed. |
3 | ... |
4 | The value returned is -1 on error (e.g., fork(2) failed), and the return status of the command otherwise. |
5 | ... |
Quelle: http://linux.die.net/man/3/system
mar IO schrieb: > "sh -c" ruft system() selber auf Das weiß ich, das brauchst Du mir nicht zu erzählen. Es las sich nur anders, nämlich dass er im System-Call noch das Verzeichnis wechselt und auch noch ein "sh -c" reinpfriemelt. Er soll mal folgendes probieren: Datei x.sh: #! /bin/sh exit 2 Datei: x.c: #include <stdio.h> int main () { int rtc = system ("./x.sh"); printf ("%d\n", rtc >> 8); return 0; } Dann: cc x.c -o x.out chmod +x x.sh ./x.out Dann sollte die Zahl 2 ausgegeben werden. Wenn nicht, ist sein system() kaputt. P.S. Ja, rtc muss um 8 Bit geshiftet werden.
OK, hat sich erledigt... hatte als Rückgabe Variable eine int_fast8_t genommen... Ist natürlich zu klein. Mit int geht es.
Frank M. schrieb: > Ja, rtc muss um 8 Bit geshiftet werden. Besser (portabler) ist
1 | #include <sys/wait.h> |
2 | |
3 | ...
|
4 | |
5 | printf ("%d\n", WEXITSTATUS(rtc)); |
ZigZeg
sh -c benutze ich nicht. System aber. So war das gemeint. Desweiteren wechsel ich vorher das Verzeichnis da sha1sum anscheinend nur im aktuellen prüft. Mit absoluten Pfadangaben kommt es nicht klar. Daher wechsel ich in das Verzeichnis wo meine beiden Files zum überprüfen liegen und anschließend wieder zurück. Und unmengen an Code kommen jetzt nicht bei sha1sum aber wenn ich tar und gzip verwende bzw sftp/scp oder ncftpget / ncftpput. Dann wird es mehr..
Problem0815 schrieb: > hatte als Rückgabe Variable eine int_fast8_t genommen... Ist natürlich > zu klein. Dachte mir sowas schon, deshalb habe ich es im P.S. nochmal explizit erwähnt. Merke Dir einfach, dass fast alle Standard-Lib-Funktionen unter Unix oder Linux ein int als Returnwert verwenden. Witzigerweise hattest Du die Manualseiten von system() noch zitiert, wo auch die Angabe über den Return-Wert drinsteht. Lass solche "Optimierungen" wie Verwendung von "int_fast8_t" unter Unix oder Linux besser - jedenfalls dann, wenn Du Standard-Lib-Funktionen oder gar System-Calls verwendest. Solche "modernen" Typen gab es in den 70er Jahren noch gar nicht.
:
Bearbeitet durch Moderator
Nur bei ping geht es trotzdem nicht... Aber das hab ich mit popen und dann parsen gelöst..
Kai S. schrieb: > Besser (portabler) ist > printf ("%d\n", WEXITSTATUS(rtc)); Stimmt, ich wollte ihn aber explizit darauf hinweisen, dass rtc groß genug sein muss, um mehr als ein Byte aufzunehmen. Ich glaube nicht, dass ein WEXITSTATUS() ihn in die richtige Ecke geschubst hätte. Ausserdem: Mit einem int_fast8_t als rtc funktioniert auch WEXITSTATUS(rtc) nicht ;-)
Problem0815 schrieb: > Nur bei ping geht es trotzdem nicht... > > Aber das hab ich mit popen und dann parsen gelöst.. Geht auch mit ping. Warum sollte es da anders sein? cat x.c:
1 | #include <stdio.h> |
2 | #include <sys/wait.h> |
3 | |
4 | int
|
5 | main () |
6 | {
|
7 | int rtc; |
8 | |
9 | rtc = system ("ping -c 1 192.168.1.1 >/dev/null 2>&1"); // den gibt es bei mir nicht |
10 | printf ("rtc = %d\n", WEXITSTATUS(rtc)); |
11 | |
12 | rtc = system ("ping -c 1 127.0.0.1 >/dev/null 2>&1"); // den gibt es immer ;-) |
13 | printf ("rtc = %d\n", WEXITSTATUS(rtc)); |
14 | return 0; |
15 | }
|
# cc x.c -o x.out # ./x.out rtc = 1 rtc = 0 Und was hat ping mit popen() zu tun?
Problem0815 schrieb: > Desweiteren wechsel ich vorher das Verzeichnis da sha1sum anscheinend > nur im aktuellen prüft. Mit absoluten Pfadangaben kommt es nicht klar. Das glaube ich nicht: # sha1sum /etc/passwd 03ee23731b71180ffc93169a82f8a47b11868321 /etc/passwd Klappt einwandfrei. Keine Ahnung, welche Welt Du Dir da zurechtschusterst.
Okay,... manchmal zweifel ich an mir selber. Ping geht jetzt auch... Hatte weil ich halt den Fehler hatte, ping mit popen aufgerufen und dann die pipe in einen Puffer eingelesen und dann geparsed nach 100% loss bzw not rechable usw..
Nein ich habe eine Datei test.sha1 in einem Ordner und die zu überprüfende Datei auch in dem Ordner. Und damit ich nicht in der .sha1 Datei den absoluten Pfadnamen drin haben muss (wird nämlich auf einem Windowsrechner erstellt) wechsel ich in den Ordner wo beide Dateien liegen.
Also ich habe: test.sha1 und Latest.hex (Beispieldateien...) Und wenn ich jetzt in test.sha1 sowas drin habe: 03ee23731b71180ffc93169a82f8a47b11868321 Latest.hex weil es auf einem Windows PC erstellt wurde geht es nicht unter Linux mit: system("sha1sum -c /Downloads/Test/test.sha1"); Ich müsste daher entweder unter Windows den Pfad mit in die Datei schreiben.. (den ich eventuell nicht weiß) oder aber ich wechsel unter Linux in den Ordner wo beide Datein liegen und rufe dort dann: system("sha1sum -c test.sha1"); auf..
Problem0815 schrieb: > Nein ich habe eine Datei test.sha1 in einem Ordner und die zu > überprüfende Datei auch in dem Ordner. > > Und damit ich nicht in der .sha1 Datei den absoluten Pfadnamen drin > haben muss (wird nämlich auf einem Windowsrechner erstellt) wechsel ich > in den Ordner wo beide Dateien liegen. Sag das doch gleich, dass in der sha1-Datei die Pfade fehlen ;-) Stünden die Pfade nämlich drin, klappt das einwandfrei: # sha1sum /etc/passwd >/tmp/a # cat /tmp/a 03ee23731b71180ffc93169a82f8a47b11868321 /etc/passwd chroot-eis-iv# sha1sum -c /tmp/a /etc/passwd: OK chroot-eis-iv# echo $? 0
Mit Ordner wechseln meine ich das Arbeitsverzeichnis ändern... Ich weiß nur nicht wie das sich mit Multi Threading verhält... Wenn ich in einem Thread das Arbeitsverzeichnis ändere, ist das in den anderen auch geändert??
Wenn ja muss ich mir da noch was überlegen.. Bzw. wohl critical sections oder so nutzen. Gibts doch bestimmt auch unter Linux..
Problem0815 schrieb: > Mit Ordner wechseln meine ich das Arbeitsverzeichnis ändern... > > Ich weiß nur nicht wie das sich mit Multi Threading verhält... > > Wenn ich in einem Thread das Arbeitsverzeichnis ändere, ist das in den > anderen auch geändert?? naja anderen Systemen (MS) kann man bei erzeugen eine Prozesses das Arbeitsverzeichnis mitgeben. So etwas wird es doch wohl auch für Linux geben.
Problem0815 schrieb: > weil es auf einem Windows PC erstellt wurde geht es nicht unter Linux > mit: > > system("sha1sum -c /Downloads/Test/test.sha1"); > > Ich müsste daher entweder unter Windows den Pfad mit in die Datei > schreiben.. (den ich eventuell nicht weiß) oder aber ich wechsel unter > Linux in den Ordner wo beide Datein liegen und rufe dort dann: > system("sha1sum -c test.sha1"); auf.. Doch, ginge mit: system("cd /Downloads/Test && sha1sum -c /Downloads/Test/test.sha1"); Dann müsstest Du nicht in Deinem C-Programm hin- und herwechseln, weil nur Dein Kind den cd durchführt. Wichtig ist die Trennung der beiden Befehle mit "&&" statt wie allgemein üblich mit ";". Nur so hast Du einen auswertbaren, d.h. vertrauenswürdigen rtc.
Was man so alles dazu lernt :-) Naja bin ja noch Frischling bei Linux Systemprogrammierung.. Bisher nur PICs. Habe mir auch extra das Buch von Helmut Herold besorgt :)
Problem0815 schrieb: > Mit Ordner wechseln meine ich das Arbeitsverzeichnis ändern... > > Ich weiß nur nicht wie das sich mit Multi Threading verhält... > > Wenn ich in einem Thread das Arbeitsverzeichnis ändere, ist das in den > anderen auch geändert?? Machs nicht so kompliziert. Du schaffst Dir so nur unnötige Komplexität. Unter Unix/Linuix sollte man das KISS-Prinzip ("Keep it small and simple") immer beachten. Schreib den cd-Befehl einfach mit in den system-Aufruf, wie ich es ein Posting drüber angegeben habe. Dann bleibt Dein Programm im ursprünclichen Verzeichnis und Dein Kind springt hinüber.
Problem0815 schrieb: > Was man so alles dazu lernt :-) Ich arbeite seit Mitte der Achtziger mit Unix-Systemen, habe sie auf der Uni kennengelernt. Damals war es noch Unix System-V auf VME-Bus-Systemen (Motorola 68020). Ich bin also seit 30 Jahren mit Unix, dann später mit Linux altgeworden. Bei einem kannst Dir aber sicher sein: Auch dann lernt man immer noch dazu :-) Unix-/Linux ist so mächtig durch das Bereitstellen vieler kleiner Tools, dass man selbst komplexe Aufgaben mit ein paar Shell-Befehlen lösen kann... wenn man weiß, wie man sie zu kombinieren hat ;-)
:
Bearbeitet durch Moderator
es muss doch auch etwas wie CreateProcess unter Linux geben. Also auch Programme unter anderen user-rechte starten usw. Oder die stdin, stout, stderr als filehandle bekommen.
Peter II schrieb: > es muss doch auch etwas wie CreateProcess unter Linux geben. Natürlich, in vielen Variationen. > Also auch Programme unter anderen user-rechte starten usw. > Oder die stdin, stout, stderr als filehandle bekommen. Gibt es alles. Microsoft war auch unheimlich stolz auf ihren mächtigen CreateProcess(), als sie ihn mit Windows-NT einführten und damit auch endlich etwas ähnliches geschaffen haben, was es unter Unix schon seit über 20 Jahren gab. Witzig, dass Du es so siehst, dass Unix (bzw. Linux) auch etwas haben muss, was Du bei Windows als selbstverständlich erachtest. Die Realität ist anders herum. Du ahnst gar nicht, was Microsoft so alles von Unix übernommen hat. (*) Ja, ich war damals bei einer Präsentations-Show von Windows-NT selbst dabei. Die freuten sich damals wie die kleinen Kinder, dass sie endlich ein "echtes" OS geschaffen haben. Sie waren auch unheimlich stolz darauf, dass sie mit NT auch endlich POSIX-kompatibel waren und damit die Auflagen des US-Verteidigungsministeriums mit sicherem Gewissen erfüllen konnten. Nur für einen UNIX-Kenner waren das damals olle Kamellen. (**) Was auch kaum jemand weiß: Microsoft hatte damals sogar ein eigenes Unix-System, nämlich Xenix. Wurde aber nicht weiter verfolgt.
:
Bearbeitet durch Moderator
Frank M. schrieb: > Natürlich, in vielen Variationen. nenn doch mal eine? Oder meinst du die Krücke, wo man eine fork machen, sich dann eine anderen Benutzer gibt. Die eigenen Handles umbiegt. Und dann den andere Prozess startet? und wie bekommt man dann die Handles in den alten Prozess zurück...
Habs gerade umgebaut :-) und läuft. Vielen Dank.
Peter II schrieb: > Frank M. schrieb: >> Natürlich, in vielen Variationen. > > nenn doch mal eine? > > Oder meinst du die Krücke, wo man eine fork machen, sich dann eine > anderen Benutzer gibt. Die eigenen Handles umbiegt. Und dann den andere > Prozess startet? und wie bekommt man dann die Handles in den alten > Prozess zurück... Die Vielfalt liegt tatsächlich in der Kombination der Möglichkeiten. Dabei ist nicht unbedingt fork() nötig. popen() ist zum Beispiel genau das richtige, um ein Kind zu starten und sich mit den stdio-Filedescriptoren des Kindes zu verbinden. Dann ist einfache Kommunikation über stdio-Funktionen möglich... denn es ist genau dasselbe, als wenn Du in der Shell eine Pipe zwischen zwei Prozessen durch "|" erzeugst. Das Beispiel mit der Krücke verstehe ich nicht. Wenn Dir das zu umständlich ist, schreibe alles nötige in eine eigene Funktion und nenne sie CreateProcess(). ;-) > und wie bekommt man dann die Handles in den alten Prozess zurück... Diese Frage verstehe ich nicht. Allein schon, dass Du die Windows-Sprache ("Handles") verwendest und nicht die richtige Bezeichnung ("File-Descriptor") dafür wählst, zeugt davon, dass Du nur rudimentäres Verständnis aufweist. Wie sollen wir uns beide dann über die Möglichkeiten von Unix/Linux "unterhalten"? ;-) (Ja, ich weiß: Du willst einen Streit vom Zaun brechen. Ich muss Dich aber enttäuschen und werde nicht drauf eingehen.)
Problem0815 schrieb: > Habs gerade umgebaut :-) und läuft. Freut mich! Und noch viel Spaß mit Linux! :-)
Frank M. schrieb: > denn es ist genau > dasselbe, als wenn Du in der Shell eine Pipe zwischen zwei Prozessen > durch "|" erzeugst. und wie bekommst du damit stderr und stdout getrennt? (also nicht einfach in Dateien schreiben) > > und wie bekommt man dann die Handles in den alten Prozess zurück... > Diese Frage verstehe ich nicht. wenn ich von dem Programm die stderr und stdout Daten brauche, dann brauche ich die handels oder File-Descriptoren. man müsste halt 2 pipes verwenden, das wüsste ich nicht wie das gehen soll.
Peter II schrieb: > Frank M. schrieb: >> denn es ist genau >> dasselbe, als wenn Du in der Shell eine Pipe zwischen zwei Prozessen >> durch "|" erzeugst. > > und wie bekommst du damit stderr und stdout getrennt? (also nicht > einfach in Dateien schreiben) stdout und stderr sind unter Unix/Linux immer getrennt. Was soll ich da also noch trennen? ;-) > man müsste halt 2 pipes verwenden, das wüsste ich nicht wie das gehen > soll. Wenn Du mehr als eine Pipe brauchst, dann musst Du tatsächlich den Weg über fork(), Verbinden der Kind-FDs mit eigenen FDs (das geht mit dup()) und anschließendem exec() gehen.(*) Ist aber auch nicht sooo kompliziert. Und ist auch keine Krücke. Das ist gewollt so. Ich habe mal vor Jahren einen Text-Editor geschrieben, der mir einen beliebigen Prozess in einem Editor-Fenster öffnete. Das konnte make zum Compilieren sein, aber auch zum Beispiel eine Shell. Alles, was ich in das Editor-Fenster tippte, ging an die Shell und wurde ausgewertet/ausgeführt, alles was an Output (von der Shell oder deren Kindern) zurückkam, wurde ins Editor-Fenster zurückgeschrieben und war dort ganz normal editierbar wie Text. Wie gesagt: Geht alles. Auch dass stderr-Ausgaben im Editor-Fenster rot eingefärbt werden ;-) Aufgaben löst man unter Unix/Linux, indem man viele kleine Tools miteinander sinnvoll kombiniert. Bei Windows macht man das eher anders: man ruft ein Monstrum auf, welches man über viele viele Parameter (z.B. in C: Unmengen von Structs, die zu füllen sind) steuert. Man kann darüber streiten, was sinnvoller ist. (*) Lies dazu auch: http://www.oser.org/~hp/labor5s/node54.html
:
Bearbeitet durch Moderator
Frank M. schrieb: > Man kann darüber streiten, was sinnvoller ist. bei Linux merkt man aber scheinbar, das es so nicht immer sinnvoll ist. Immerhin erfinden sie gerade soetwas wie den Dienstmanager unter Windows mit ihren SystemD neu.
Frank M. schrieb: > (*) Lies dazu auch: > http://www.oser.org/~hp/labor5s/node54.html und das soll keine Krücke sein? Klar kann ich auch mit ASM eine XML parsen, aber in der heutigen zeit erwartet man halt das so etwas schon fertig vorhanden ist. KISS ist zwar schön, aber übertreiben muss man es nicht.
Achsoo, jetzt verstehe ich auch die Frage:
> und wie bekommt man dann die Handles in den alten Prozess zurück...
Du schließt die Filedescriptoren 0, 1, 2 (eigentlich fileno(stdin) usw.)
einfach nicht vor dem exec(). Dann gehen sie auch nicht verloren.
Das mit dem Schließen der Standard-FDs macht man eigentlich nur, wenn
man sie als Pipe und gleichzeitig als Standard-FDs verwenden will.
Hi, Problem0815 schrieb: > Was man so alles dazu lernt :-) > > Naja bin ja noch Frischling bei Linux Systemprogrammierung.. > Bisher nur PICs. > > Habe mir auch extra das Buch von Helmut Herold besorgt :) Besorgen reicht nicht. Wer Erfolg haben will, muß es auch lesen. ;-) SCNR, Karl
Peter II schrieb: > und das soll keine Krücke sein? Nein, das ist keine Krücke. Schreibe alle nötigen Aufrufe in eine Funktion und nenne sie meinetwegen MyUltimateFunctionOfCreateProcess(). > KISS ist zwar schön, aber übertreiben muss man es nicht. Du hast leider nichts verstanden. Ich hatte es bereits befürchtet. Daher von meiner Seite EOD.
Hallo Peter, Peter II schrieb: > nenn doch mal eine? fork(2) > Oder meinst du die Krücke, wo man eine fork machen, sich dann eine > anderen Benutzer gibt. Die eigenen Handles umbiegt. Und dann den andere > Prozess startet? und wie bekommt man dann die Handles in den alten > Prozess zurück... Was sollte daran eine "Krücke" sein? Das ist eine sehr leistungsfähige und flexible Lösung. Daß Du sie offenbar nicht verstanden hast und sie darum als "Krücke" bezeichnest, spricht nicht gerade für Deine Fähigkeiten. Liebe Grüße, Karl
Karl Käfer schrieb: > Was sollte daran eine "Krücke" sein? Das ist eine sehr leistungsfähige > und flexible Lösung. Daß Du sie offenbar nicht verstanden hast und sie > darum als "Krücke" bezeichnest, spricht nicht gerade für Deine > Fähigkeiten. Lass Dich nicht auf einen Streit ein. Nur das will er. Er füllt halt lieber die Daten für LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo um dann endlich nach wilden Allokationen, Copy&Pastes aus irgendwelchen MSDN-Sites die ersehnte Funktion CreateProcess() aufrufen zu können, ohne dass sie einen Error wirft. ;-) Und ehrlich gesagt: Ich weiß nicht, ob/wie man eine (oder gar mehrere) Pipes zu einem Kind-Prozess unter Windows per CreateProcess() aufbauen könnte. Das Boolean bInheritHandles wird einem da wohl nicht weiterhelfen. Unter Unix/Linux weiß ich es aber sehr wohl, weil mir die Schritte dahin absolut plausibel und nachvollziehbar erscheinen. Jedem das seine. Ich arbeite sowohl mit Unix, Linux als auch mit Windows. Alle Systeme haben ihre Daseinsberechtigung. Was man bei dem einen System gut bzw. schlecht findet, kann ein Anderer anders sehen.
So vielleicht könnt Ihr mir nocheinmal helfen. Ich rufe in meiner main() 4 Threads auf. Jeder Thread ist eine state-machine. die für immer laufen soll. Also beinhalten die Threads jeweils eine while(1){Sachen die gemacht werden.} Nachdem die Threads erstellt und aufgerufen wurden geht meine main selber in eine while(1); Läuft also bis der Beaglebone abschmiert... Mein Problem ist das diese while(1); meine CPU Auslastung auf 100% jagt und dann irgendwann der watchdog auslöst. (watchdog service ist auch ein thread). Wie lege ich denn die main() am besten auf Eis? Mit einem sehr langen sleep(10000)? Oder gibt es einen extra Befehl für so etwas?
Habe jetzt einen Thread weniger aufgemacht und die state-machine des Watchdogs in die main() geschoben. Jetzt hab ich nur noch 11% CPU mit allem. Würde mcih aber trotzdem interessieren wie man sowas machen könnte?
Problem0815 schrieb: > Nachdem die Threads erstellt und aufgerufen wurden geht meine main > selber in eine while(1); Sowas tut man nicht, wenn man den Processor nicht für sich allein hat ;-) > Wie lege ich denn die main() am besten auf Eis? Mit einem sehr langen > sleep(10000)? Oder gibt es einen extra Befehl für so etwas? Ja, zum Beispiel mit while (1) sleep (100000); oder Du überwachst in der main-Funktion den Status der Threads (Watchdog) - was-weiss-ich. Frage: Müssen es wirklich Threads sein? Interagieren die Threads irgendwie miteinander? Oder warum hast Du die Teilaufgaben nicht einfach als Sub-Prozesse gestartet, um dann als Mutter nach erfolgreichem Erzeugen der Kinder einfach in Frieden zu sterben?
:
Bearbeitet durch Moderator
Ja tun sie. 1. Der eine wenn knopf gedrückt wurde andere Threads anhalten die auf die SD schreiben wollen und SD unmounten. Wenn dann wieder Knopf gedrückt SD mounten und Threads weiterlaufen lassen. 2. Pin abfrage bzw. Interrupt mit epoll() wenn der Pin auf 0 geht dann Daten über SPI senden/empfangen auf SD schreiben. 3. UMTS Verbindung aufbauen, Daten runterladen, überprüfen entpacken einlesen. Noch mehr Daten runterladen, überprüfen (wenn gültig Thread 4 freigeben). Dann Daten packen (die Thread 2 geschriben hat) und hochladen. UMTS aus. Warten eine bestimmte Zeit. 4. Daten waren gültig, Pin toggeln und über SPI rausschicken, Pin toggeln. Warten bis Thread 3 erneut freigibt. 5. bzw. die main() Watchdog füttern. Und da die Threads (zumindest 1,2,3,4) synchronisiert werden müssen hab ich es mit Threads gelöst. Habe aber ein anderes Problem nun. Nummer 2 belastet das System ganz gewaltig. Weil ich Angst habe, das ich die Flanke verpasse Frage ich andauernd den Wert des Pins ab. Das scheint aber etwas zu viel des guten...
1 | void * |
2 | state_get_Mess_Data (void * Give_Thread_Struct) |
3 | {
|
4 | Thread * Thread_Struct = (Thread *) Give_Thread_Struct; |
5 | Config * Config_PTR = Thread_Struct->Config_PTR; |
6 | SPI_Par * SPI_Param = Thread_Struct->SPI_Param; |
7 | int_fast8_t ret; |
8 | while (1) |
9 | {
|
10 | ret = get_interrupt_gpio_fast ("/sys/class/gpio/gpio27/value", 10, |
11 | EPOLLET); |
12 | while (!((ret == 2) |
13 | && (get_value_gpio_fast ("/sys/class/gpio/gpio27/value") == 0)) |
14 | || (ret == 0)) |
15 | {
|
16 | // printf ("Waiting for DSP ready!\n");
|
17 | }
|
18 | while (pthread_mutex_lock (&SPI_in_use_mutex)) |
19 | ;
|
20 | while (get_Mess_Data_SPI (SPI_Param, Config_PTR, &rx_to_ASCII_int) < 0) |
21 | ;
|
22 | while (pthread_mutex_unlock (&SPI_in_use_mutex)) |
23 | ;
|
24 | }
|
25 | return (NULL); |
26 | }
|
Wie könnte man sowas verbessern? Die Funktionen get_value_gpio und get_interrupt_gpio sehen so aus:
1 | int_fast8_t
|
2 | get_value_gpio_fast (char const * const Target2) //Alternativ get_interrupt_gpio() verwenden wenn auf Flanken getriggert werden kann und der Wert nicht interessiert! Wegen userspace langsam!! Wenn schneller benötigt muss ein Treiber geschrieben werden oder direkt von Adressen gelesen werden mit mmap()! |
3 | {
|
4 | FILE* TMP2 = NULL; |
5 | int_fast8_t ret = 0; |
6 | int val = 0; |
7 | TMP2 = fopen (Target2, "r"); |
8 | if (TMP2) |
9 | {
|
10 | ret = fscanf (TMP2, "%i", &val); |
11 | fclose (TMP2); |
12 | if (!ret) |
13 | {
|
14 | printf ("Cant read correct value!"); |
15 | TMP2 = NULL; |
16 | return (-2); |
17 | }
|
18 | TMP2 = NULL; |
19 | return ((int_fast8_t) val); |
20 | }
|
21 | printf ("Cant get value File doesnt exist!"); |
22 | return (-1); |
23 | }
|
1 | int_fast8_t
|
2 | get_interrupt_gpio_fast (char const * const Target2, int timeout, |
3 | uint32_t trigger_event) //Achtung blocking!! Also extra thread oder process! //TODO Falls der Interrupt schneller bereit sein muss Pfad mit GPIO direkt übergeben also ohne allokieren usw.. |
4 | {
|
5 | int_fast8_t ret = 0; |
6 | int val = 0; |
7 | int pin = open (Target2, O_RDWR | O_NONBLOCK); |
8 | if (pin > 0) |
9 | {
|
10 | int epollins = epoll_create1 (0); |
11 | if (epollins >= 0) |
12 | {
|
13 | struct epoll_event ev; |
14 | struct epoll_event events; |
15 | ev.events = trigger_event; |
16 | ev.data.fd = pin; |
17 | ret = epoll_ctl (epollins, EPOLL_CTL_ADD, pin, &ev); |
18 | if (!ret) |
19 | {
|
20 | ret = (int_fast8_t) read (pin, NULL, 1); |
21 | ret = epoll_wait (epollins, &events, 1, timeout); |
22 | if (ret > 0) |
23 | {
|
24 | ret = (int_fast8_t) lseek (pin, 0, SEEK_SET); |
25 | if (ret >= 0) |
26 | {
|
27 | ret = (int_fast8_t) read (pin, &val, 1); |
28 | if (ret) |
29 | {
|
30 | close (pin); |
31 | close (epollins); |
32 | if (val == 49) |
33 | return (1); |
34 | else
|
35 | return (0); |
36 | }
|
37 | printf ("Cant read correct value!\n"); |
38 | close (epollins); |
39 | close (pin); |
40 | return (-5); |
41 | }
|
42 | printf ("Error @ lseek!\n"); |
43 | close (epollins); |
44 | close (pin); |
45 | return (-4); |
46 | }
|
47 | else if (ret == 0) |
48 | {
|
49 | printf ("Timeout!\n"); |
50 | close (epollins); |
51 | close (pin); |
52 | return (2); |
53 | }
|
54 | printf ("Error @ epoll_wait! %i\n", errno); |
55 | close (pin); |
56 | close (epollins); |
57 | return (-3); |
58 | }
|
59 | printf ("Error @ epoll_ctl! %i\n", errno); |
60 | close (epollins); |
61 | close (pin); |
62 | return (-2); |
63 | }
|
64 | printf ("Error @ epoll_create! %i\n", errno); |
65 | close (pin); |
66 | return (-6); |
67 | }
|
68 | printf ("No PIN for Interrupt!\n"); |
69 | return (-1); |
70 | }
|
Hm, ist wvdial nicht Thread sicher? Wenn ich es in keinem extra Thread laufen lasse geht es. Wenn ich es in einem extra Thread über vfork() und dann execl() starte ist irgendwann mein UMTS Modem also /dev/ttyUSB3 geblockt. Also wvdial kann es nicht mehr öffnen weil es busy sein soll. Ist es aber eigentlich nicht. Und jetzt hängt es in einer Endlos schleife.. Ich starte halt wvdial warte dann 20 sekunden überprüfe dann mit einem ping ob google erreichbar ist. Wenn nicht wird system("killall wvdial") aufgerufen und dann nach 20 sekunden wieder erneut gestartet wie oben beschrieben. Wenn ping erfolgreich macht er weiter.
Also auch wenn es kein extra Thread ist mache ich die abfolge so (vfork usw. da mir ja wvdial sonst für immer alles blockt) und es Funktioniert. Oder aber irgendwas wird mit den fd gemacht bei multiplen Threads. Aber ich hoffe mal das es so passt..
Hm, da passt mehreres noch nicht. Alles einzeln geht. Aber wenn in mehreren Threads gibts durcheinander. Speziell mit den fd.
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.