uClibc
ist ein Standard-C, das am besten für Linux-Umgebungen mit begrenzter Hardware wie Ressourcen geeignet ist, wie Sie vielleicht wissen, wenn Sie sich mit der Entwicklung eingebetteter Linux beschäftigen. Es ist eine Bibliothek. Unter normalem PC Linux werden Bibliotheken wie "glibc" verwendet, aber in verschiedenen Umgebungen werden solche leichtgewichtigen Bibliotheken verwendet.
Übrigens denke ich, dass Multithread und Multiprozess vorsichtig sind, weil sie beim Mischen gefährlich riechen. Wenn Sie jedoch aufmerksam sind und einfach versuchen, einen Daemon für eine Multithread-Implementierung zu erstellen, geraten Sie in eine Falle.
Bitte beachten Sie, dass die unten beschriebenen Fälle in "uClibc" und wahrscheinlich nicht auf dem oben genannten PC Linux zu finden sind. Es kann auch nur eine ältere Version sein.
Siehe den folgenden Code:
thread_test.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
void* do_something( void *object )
{
size_t i;
for ( i = 0; i < 5; ++i )
{
printf(
"Hello, this is another thread! "
"( times = %zd, tid = %p )\n",
i,
( void * ) pthread_self()
);
sleep( 2 );
}
return NULL;
}
int main()
{
size_t i;
pthread_t thread;
printf( "New thread will be created. ( tid = %p )\n", ( void * ) pthread_self() );
pthread_create( &thread, NULL, do_something, NULL );
for ( i = 0; i < 10; ++i )
{
printf( "The old thread keeps going on... ( tid = %p )\n", ( void * ) pthread_self() );
sleep( 1 );
}
pthread_join( thread, NULL );
printf( "threads are joined.\n" );
return 0;
}
Dieser Code ist ein gängiges Beispiel für Multithreading, bei dem der Hauptthread die Nachricht zehnmal anzeigt, während die Funktion "do_something" in einem anderen Thread ausgeführt wird und die Nachricht fünfmal angezeigt wird. Schließlich enden die beiden Threads mit pthread_join
.
Wie Sie sich vorstellen können, sieht die Ausgabe folgendermaßen aus:
stdout
New thread will be created. ( tid = 0x1111 )
The old thread keeps going on... ( tid = 0x1111 )
Hello, this is another thread! ( times = 0, tid = 0x1234 )
The old thread keeps going on... ( tid = 0x1111 )
The old thread keeps going on... ( tid = 0x1111 )
Hello, this is another thread! ( times = 1, tid = 0x1234 )
The old thread keeps going on... ( tid = 0x1111 )
Hello, this is another thread! ( times = 2, tid = 0x1234 )
The old thread keeps going on... ( tid = 0x1111 )
The old thread keeps going on... ( tid = 0x1111 )
Hello, this is another thread! ( times = 3, tid = 0x1234 )
The old thread keeps going on... ( tid = 0x1111 )
The old thread keeps going on... ( tid = 0x1111 )
Hello, this is another thread! ( times = 4, tid = 0x1234 )
The old thread keeps going on... ( tid = 0x1111 )
The old thread keeps going on... ( tid = 0x1111 )
threads are joined.
(Der Vorgang ist abgeschlossen)
Jetzt möchte ich diesen Prozess als Daemon im Hintergrund ausführen, daher ist er salzig und praktisch, daemon () (http://linuxjm.osdn.jp/html/LDP_man-pages/man3/daemon.3). Rufen Sie html) an und bitten Sie sie, zu deseamonisieren.
daemonized_thread.c
int main()
{
size_t i;
pthread_t thread;
// process should be daemonized here!
if ( daemon( 1, 1 ) )
{
fprintf( stderr, "daemonization failed." );
exit( 1 );
}
printf( "New thread will be created. ( tid = %p )\n", ( void * ) pthread_self() );
pthread_create( &thread, NULL, do_something, NULL );
for ( i = 0; i < 10; ++i )
{
printf( "The old thread keeps going on... ( tid = %p )\n", ( void * ) pthread_self() );
sleep( 1 );
}
pthread_join( thread, NULL );
printf( "threads are joined.\n" );
return 0;
}
Was ist dann mit der Ausgabe, die so aussieht und niemals endet:
stdout
New thread will be created. ( tid = 0x1111 )
Hello, this is another thread! ( times = 0, tid = 0x1234 )
Hello, this is another thread! ( times = 1, tid = 0x1234 )
Hello, this is another thread! ( times = 2, tid = 0x1234 )
Hello, this is another thread! ( times = 3, tid = 0x1234 )
Hello, this is another thread! ( times = 4, tid = 0x1234 )
(Der Prozess endet nicht)
Anscheinend blieb der Haupt-Thread um pthread_create ()
hängen und steckte fest.
Eine Suche nach "uClibc pthread daemon" scheint ziemlich problematisch zu sein und bringt Informationen zum Forum und zur Mailingliste:
Gemäß den Informationen in der Mailingliste unten ist die Ursache des Problems, dass "fork ()", das in "daemon ()" aufgerufen wird, das interne Symbol "fork ()" anstelle von "fork ()" in "libpthread" aufruft. Dies scheint darauf zurückzuführen zu sein, dass der Thread-Manager von "pthread" die PID des Haupt-Threads nach "fork ()" verliert (das ist es).
Die Lösung hierfür besteht darin, einen ähnlichen daemon ()
- Prozess selbst zu implementieren, wie z. B. die fork ()
des pthread
:
https://dev.openwrt.org/browser/trunk/package/fuse/patches/300-workaround-uclibc-pthread-breakage.patch?rev=13312
daemonized_thread_fixed.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <fcntl.h>
int my_daemon( int nochdir, int noclose )
{
int res;
int fd;
switch ( res = fork() )
{
case -1:
return 1;
case 0:
break;
default:
exit( 0 );
}
if ( ( res = setsid() ) == -1 )
{
return 1;
}
if ( !nochdir )
{
chdir( "/" );
}
if ( !noclose && ( fd = open( "/dev/null", O_RDWR, 0 ) ) != -1 )
{
dup2( fd, STDIN_FILENO );
dup2( fd, STDOUT_FILENO );
dup2( fd, STDERR_FILENO );
if ( fd > 2 )
{
close( fd );
}
}
return 0;
}
void* do_something( void *object )
{
size_t i;
for ( i = 0; i < 5; ++i )
{
printf(
"Hello, this is another thread! "
"( times = %zd, tid = %p )\n",
i,
( void * ) pthread_self()
);
sleep( 2 );
}
return NULL;
}
int main()
{
size_t i;
pthread_t thread;
if ( my_daemon( 1, 1 ) )
{
fprintf( stderr, "daemonization failed." );
exit( 1 );
}
printf( "New thread will be created. ( tid = %p )\n", ( void * ) pthread_self() );
pthread_create( &thread, NULL, do_something, NULL );
for ( i = 0; i < 10; ++i )
{
printf( "The old thread keeps going on... ( tid = %p )\n", ( void * ) pthread_self() );
sleep( 1 );
}
pthread_join( thread, NULL );
printf( "threads are joined.\n" );
return 0;
}
Anscheinend hat das funktioniert. Ich bin glücklich.