Forum: PC-Programmierung pthread linux


von Vlad T. (vlad_tepesch)


Lesenswert?

Hi,
Ich bin grad ein wenig am verzweifeln an threadprogrammierung für eine 
Fritzbox(7170)-Anwendung.

Ich habe folgenden Code:
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <string.h>
4
#include <inttypes.h>
5
#include <stdbool.h>
6
7
#include <time.h>
8
#include <pthread.h>
9
10
11
#ifdef _WIN32
12
#  include <windows.h>
13
#  define sleepMs(x) do{Sleep(x);}while(0)
14
#else
15
#  include <unistd.h>
16
static void sleepMs(uint32_t ms)
17
{
18
  struct timespec sleepTime;
19
  struct timespec remainingSleepTime;
20
  sleepTime.tv_sec  = ms/1000;
21
  sleepTime.tv_nsec = (ms%1000)*1000000;
22
  nanosleep(&sleepTime,&remainingSleepTime);
23
}
24
#endif
25
26
27
void* receiveThread(void* arg)
28
{
29
  while(23){
30
    printf("iam the thread loop\n");
31
    sleepMs(2000);
32
  }
33
}
34
35
int main(void)
36
{
37
  pthread_t thread = {0};
38
  int rc;
39
  printf("enter main\n");
40
41
  rc = pthread_create( &thread, NULL, &receiveThread, NULL);
42
  if(rc){
43
   perror("could not create THread\n");
44
  }
45
  printf("started thread\n");
46
47
  while(1)
48
  {
49
    printf("iam the main loop\n");
50
    sleepMs(1000);
51
  }
52
  return EXIT_SUCCESS;
53
}


unter windows läuft er wie erwaretet.
ich benutze visual studio 2008 express mit einer windows pthread 
bibliothek (die leider die sleep funktionen nicht kennt, deswegen die 
unterscheidung)

auf der Fritzbox läuft das ganze dann so, dass ich nur die ausschriften 
der main-loop bekomme.
1
root@fritz:/var/media/ftp/uStor11# ./helloworld
2
enter main
3
started thread
4
iam the main loop
5
iam the main loop
6
iam the main loop
7
iam the main loop

kan nmir hier jemand weiterhelfen?
Ich hau mich jetzt erst mal aufs Ohr.

MfG
Vlad

: Verschoben durch Admin
von Tim T. (tim_taylor) Benutzerseite


Lesenswert?

Könnte ein Problem im Threading des Linuxkernels auf deiner Fritzbox 
sein, auf 3 verschiedenen Linuxsystemen (Desktop, Atom, NAS) lies sich 
dein Code wie zu erwarten Ausführen.

Ansonsten wie hast du kompiliert?

gcc -lpthreads source.c -o binary
oder
gcc -D_REENTRANT -lpthreads source.c -o binary
oder
gcc -pthreads source.c -o binary

von Vlad T. (vlad_tepesch)


Lesenswert?

Tim T. schrieb:
> Könnte ein Problem im Threading des Linuxkernels auf deiner Fritzbox
> sein, auf 3 verschiedenen Linuxsystemen (Desktop, Atom, NAS) lies sich
> dein Code wie zu erwarten Ausführen.
oh mann, wieso habe ich das befürchtet.
Die anderen Tools laufen doch auch.

Tim T. schrieb:
> Ansonsten wie hast du kompiliert?
>
> gcc -lpthreads source.c -o binary
> oder
> gcc -D_REENTRANT -lpthreads source.c -o binary
> oder
> gcc -pthreads source.c -o binary

was wäre denn richtig? Was sind die Unterschiede?

hab gerade das Makefile nicht zur hand, aber ich glaube so:
gcc -lpthreads source.c -o binary
die anderen beiden auf gar keinen Fall.

von Holger (Gast)


Lesenswert?

Vlad Tepesch schrieb:
> rc = pthread_create( &thread, NULL, &receiveThread, NULL);

Das & vor dem receiveThread muß weg. receiveThread als solches ist ja 
schon der Functionpointer.

Gruß Holger

von Vlad T. (vlad_tepesch)


Lesenswert?

Holger schrieb:
> Das & vor dem receiveThread muß weg. receiveThread als solches ist ja
> schon der Functionpointer.

das sollte egal sein, oder?

von Tim T. (tim_taylor) Benutzerseite


Lesenswert?

Vlad Tepesch schrieb:
> Tim T. schrieb:
>> Könnte ein Problem im Threading des Linuxkernels auf deiner Fritzbox
>> sein, auf 3 verschiedenen Linuxsystemen (Desktop, Atom, NAS) lies sich
>> dein Code wie zu erwarten Ausführen.
> oh mann, wieso habe ich das befürchtet.
> Die anderen Tools laufen doch auch.
>
> Tim T. schrieb:
>> Ansonsten wie hast du kompiliert?
>>
>> gcc -lpthreads source.c -o binary
>> oder
>> gcc -D_REENTRANT -lpthreads source.c -o binary
>> oder
>> gcc -pthreads source.c -o binary
>
> was wäre denn richtig? Was sind die Unterschiede?
>
> hab gerade das Makefile nicht zur hand, aber ich glaube so:
> gcc -lpthreads source.c -o binary
> die anderen beiden auf gar keinen Fall.

Variante 1 linkt einfach nur pthreads dazu.
Variante 2 ist wie Variante 1 nur das zusätzlich die Threadsicheren 
Standardbibliotheken benutzt werden.
Variante 3 sollte die Kurzform von Variante 2 sein.

Also richtig wäre Variante 3 bzw. 2.

Und das mit dem Funktionspointer ist egal.

von Holger (Gast)


Lesenswert?

Vlad Tepesch schrieb:
> das sollte egal sein, oder?

Stimmt ... ich konnte es gar nicht glauben. Mit dem & würde man ja 
eigentlich eine Pointer auf einen Funktionspointer übergeben - was in 
dem Fall ja erstmal falsch wäre. Müsste dann ja aber auch vom Compiler 
angemeckert werden.
Es geht tatsächlich beides - warum auch immer... wenn ich einer Variable 
einen Funktionspointer zuweise schreibe ich ja auch

var_func = function;

und nicht

var_func = &function;

(Am Ende geht das auch? Hab ich jetzt nicht überprüft.)

von Vlad T. (vlad_tepesch)


Lesenswert?

Tim T. schrieb:
> Variante 2 ist wie Variante 1 nur das zusätzlich die Threadsicheren
> Standardbibliotheken benutzt werden.
> Variante 3 sollte die Kurzform von Variante 2 sein.
>
> Also richtig wäre Variante 3 bzw. 2.
ah - ok, das werde ich heut abend mal ausprobieren.
dann wundert es mich aber, dass das ganze nicht abstürzt, oder müll 
ausgegeben wird, wenn die stdlib (in dem Fall wird ja nur das printf 
benutzt) nicht threadsafe ist.


Holger schrieb:
> (Am Ende geht das auch? Hab ich jetzt nicht überprüft.)

na klar geht das auch.
Ein Argument zu übergeben ist doch syntaktisch eine Zuweisung an den 
Parameter.

Ich benutze lieber das &, da das explizit aussagt, dass hier die Adresse 
von etwas zurückgegeben wird.

von Bernhard M. (boregard)


Lesenswert?

Vlad Tepesch schrieb:
> dann wundert es mich aber, dass das ganze nicht abstürzt, oder müll
> ausgegeben wird, wenn die stdlib (in dem Fall wird ja nur das printf
> benutzt) nicht threadsafe ist.

Das passiert ja nur, wenn der Taskwechsel erfolgt, während der eine 
Thread gerade in der printf ist und nach dem Taskwechsel der andere 
Thread auch in der printf ist oder hineingeht, und ein (globaler) 
Zustand der printf verändert wird. Es ist also relativ unwahrscheinlich, 
daß das passiert. Deshalb bleiben solche Fehler auch lange unentdeckt 
und sind schwer zu finden.

von Vlad T. (vlad_tepesch)


Lesenswert?

Ich glaube aber nicht, dass das Problem ist.
Es müsste ja wenigstens irgend ein Lebenszeichen von dem Thread kommen.

Ich denke, ich werde heut abend mal die anderen Kompilerparameter testen 
und bei Miserfolg die Frage nochmal im ipphone in der AVM-Ecke stellen

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Tim T. schrieb:

> Ansonsten wie hast du kompiliert?
>
> gcc -lpthreads source.c -o binary
> oder
> gcc -D_REENTRANT -lpthreads source.c -o binary

-l-Optionen vor den eigentlichen Objekten (bzw. Quelldateien) sind
witzlos.  -l-Optionen gehören immer nach hinten.

von Vlad T. (vlad_tepesch)


Lesenswert?

mensch Jörg, warum hast du das jetzt schon wieder verschoben?
es geht nicht um PC-Programmierung, sondern um ein Embeddedsystem auf 
einen Mipsel-µC mit ucLinux

Auf PCs scheint es kein Problem zu geben.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Vlad Tepesch schrieb:
> mensch Jörg, warum hast du das jetzt schon wieder verschoben?

Mensch Vlad, warum nimmst du an, dass alles, was dir an der Moderation
nicht passt, durch mich erfolgt ist?

> Auf PCs scheint es kein Problem zu geben.

Dann hat entweder dein Kernel auf dem Gerät eine Macke, oder du bist
im Compilieren zwischen beiden halt nicht konsistent.  Wenn Threads
angeboten werden, sollten sie unabhängig von der Hardwareplattform
mit gleichem API funktionieren.

Die Linux-Experten (die du für die Beantwortung dieser Frage brauchst)
wirst du aber ohnehin eher hier in diesem Forum finden, auch wenn deine
Zielplattform ein MIPS ist.

von Tim T. (tim_taylor) Benutzerseite


Lesenswert?

Jörg Wunsch schrieb:
> Tim T. schrieb:
>
>> Ansonsten wie hast du kompiliert?
>>
>> gcc -lpthreads source.c -o binary
>> oder
>> gcc -D_REENTRANT -lpthreads source.c -o binary
>
> -l-Optionen vor den eigentlichen Objekten (bzw. Quelldateien) sind
> witzlos.  -l-Optionen gehören immer nach hinten.

Das steht zwar immernoch in gewissen O'Reilly Büchern, hat aber 
ansonsten nichts zu sagen, nur die Reihenfolge der Libs untereinander 
ist von Bedeutung.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Tim T. schrieb:
> Das steht zwar immernoch in gewissen O'Reilly Büchern, hat aber
> ansonsten nichts zu sagen, nur die Reihenfolge der Libs untereinander
> ist von Bedeutung.

Wenn du nicht weißt, warum das in "gewissen O'Reilly Büchern" steht,
dann verbreite bitte wenigstens kein Halbwissen.

Es spielt nämlich nur so lange keine Rolle, wie sämtliche via -l
referenzierten Bibliotheken dynamisch gelinkt werden(*).  Sowie sich
dahinter eine statische Bibliothek versteckt, spielt die Reihenfolge
sehr wohl wieder eine Rolle.

(*) Selbst da wäre ich mir nicht völlig sicher, ob nicht-GNU-Linker
(zum Beispiel auf Solaris) da genauso reagieren.

Auch auf einem System, was im Wesentlichen mit dynamischen Bibliotheken
arbeitet, kann es Gründe geben, warum bestimmte Bibliotheken nicht
als dynamische Bibliothek vorliegen.  Ob dem so ist, kann man der
Linker-Kommandozeile aber nicht ansehen.

Spätestens, wenn man aus irgendeinem Grunde mal komplett statisch
linkt (via -static), wäre ohnehin Schluss mit lustich.

von Tim T. (tim_taylor) Benutzerseite


Lesenswert?

Stimmt, das statische Linken hatte ich nicht bedacht, ansonsten passts.

Und warum das in gewissen O'Reilly Büchern steht dürfte daran liegen das 
es so im Manual steht, was aber hierzu auch keine Begründung liefert.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Tim T. schrieb:
> dürfte daran liegen das es so im Manual steht

Weil der Linker die Bibliotheken nur zur Auflösung von an dieser
Stelle noch vorhandnene "global undefined"-Referenzen benutzt.

Wenn man die Bibliotheken vor den Objekten linkt, ist noch gar nichts
(außer "main", aus dem crt0.o) "global undefined", folglich wird dann
nichts gelinkt.

Dass es bei dynamischen Bibliotheken — zumindest beim GNU-Linker —
anders läuft liegt daran, dass er diese beim Nennen auf der Kommando-
zeile tatsächlich in die Liste der zur Laufzeit hinzuzulinkenden
shared libs aufnimmt und damit deren Symboltabellen komplett
übernimmt.  Aber wie geschrieben: ich würde mich nicht drauf
verlassen, dass das jeder Linker so tut.

> was aber hierzu auch keine Begründung liefert.

Selbstverständlich liefert es die:

     The linker will search an archive only once, at the location
     where it is specified on the command line.  If the archive
     defines a symbol which was undefined in some object which
     appeared before the archive on the command line, the linker will
     include the appropriate file(s) from the archive.  However, an
     undefined symbol in an object appearing later on the command line
     will not cause the linker to search the archive again.

von Tim T. (tim_taylor) Benutzerseite


Lesenswert?

Jörg Wunsch schrieb:
> Selbstverständlich liefert es die:
>
>      The linker will search an archive only once, at the location
>      where it is specified on the command line.  If the archive
>      defines a symbol which was undefined in some object which
>      appeared before the archive on the command line, the linker will
>      include the appropriate file(s) from the archive.  However, an
>      undefined symbol in an object appearing later on the command line
>      will not cause the linker to search the archive again.

Hmm, diesen Passus habe ich im aktuellen Manual nicht gefunden, 
eventuell einen Tip wo ich suchen muss?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Tim T. schrieb:
> Hmm, diesen Passus habe ich im aktuellen Manual nicht gefunden,
> eventuell einen Tip wo ich suchen muss?

Ich hatte nur in die lokal installierte info-Seite geguckt,
Beschreibung der Option -l.

von Vlad T. (vlad_tepesch)


Lesenswert?

Vlad Tepesch schrieb:
> Ich denke, ich werde [...] die Frage nochmal im ipphone in der AVM-Ecke stellen

hab das wie angekündigt da mal gepostet
http://www.ip-phone-forum.de/showthread.php?t=245425&p=1806050

es scheint an compilerflags im Makefile gelegen zu haben
jetzt läuft es wie erwartet

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Vlad Tepesch schrieb:
> es scheint an compilerflags im Makefile gelegen zu haben

Fazit: die benutzten Compiler-/Linkeroptionen auch gleich mit posten.

von Vlad T. (vlad_tepesch)


Lesenswert?

Jörg Wunsch schrieb:
> Fazit: die benutzten Compiler-/Linkeroptionen auch gleich mit posten.

wie üblich lag der fehler in dem teil, den man nicht postet.
wobei ich noch rauskriegen muss, an welcher option es genau gelegen hat.

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
Noch kein Account? Hier anmelden.