2012-04-08 2 views
4

Kurze Version der Frage: Welchen Parameter muss ich an den clone Systemaufruf auf x86_64 Linux-System übergeben, wenn ich einen neuen TLS-Bereich für den Thread zuweisen möchte Ich erschaffe.Wie man einen neuen TLS-Bereich mit Klon Systemaufruf zuweist

Lange Version:

ich an einem Forschungsprojekt arbeite und für etwas, was ich bin das Experimentieren mit I-Threads mit dem clone Systemaufruf erstellen möchten, anstatt pthread_create zu verwenden. Ich möchte jedoch auch lokalen Thread-Speicher verwenden können. Ich plane derzeit nicht, viele Threads zu erstellen, daher wäre es in Ordnung, für jeden Thread, den ich mit dem Clone-Systemaufruf erstelle, einen neuen TLS-Bereich zu erstellen.

ich für clone auf der man-Seite gesucht und es hat die folgenden Informationen über den Flag für die TLS-Parameter:

CLONE_SETTLS (since Linux 2.5.32) 
    The newtls argument is the new TLS (Thread Local Storage) descriptor. 
    (See set_thread_area(2).) 

Also ich für set_thread_area auf der man-Seite geschaut und folgende bemerkt, die vielversprechend aussahen :

When set_thread_area() is passed an entry_number of -1, it uses a 
free TLS entry. If set_thread_area() finds a free TLS entry, the value of 
u_info->entry_number is set upon return to show which entry was changed. 

Doch nach dieser etwas experimentieren scheint es, dass set_thread_area nicht in meinem System (Ubunut 10,04 auf x86_64-Plattform) umgesetzt wird. Wenn ich den folgenden Code ausführen bekomme ich einen Fehler, der sagt: set_thread_area() failed: Function not implemented

#include <stdlib.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <errno.h> 
#include <sys/syscall.h> 
#include <sys/types.h> 
#include <linux/unistd.h> 

#include <asm/ldt.h> 

int main() 
{ 
    struct user_desc u_info; 
    u_info.entry_number = -1; 
    int rc = syscall(SYS_set_thread_area,&u_info); 
    if(rc < 0) { 
    perror("set_thread_area() failed"); 
    exit(-1); 
    } 

    printf("entry_number is %d",u_info.entry_number); 
} 

auch, dass ich sah, als ich Strace das sehen, was passiert, wenn pthread_create genannt wird, dass ich keine Anrufe zu set_thread_area sehen. Ich habe mir auch den nptl pthread-Quellcode angeschaut, um zu verstehen, was sie tun, wenn sie Threads erstellen. Aber ich verstehe es noch nicht vollständig und ich denke, es ist komplexer als das, was ich versuche, weil ich nicht etwas brauche, das bei der pthread-Implementierung so robust ist. Ich nehme an, dass der Systemaufruf set_thread_area für x86 ist und dass es einen anderen Mechanismus gibt, der für x86_64 verwendet wird. Aber im Moment konnte ich nicht herausfinden, was es ist, also hoffe ich, dass diese Frage mir helfen wird, einige Ideen zu bekommen, was ich mir ansehen muss.

Antwort

5

ich an einem Forschungsprojekt arbeite und für etwas, das ich mit experimentiere ich möchte Threads erstellen den Anruf Klon-System anstelle der Verwendung pthread_create

Im überaus unwahrscheinliches Szenario, wo Ihre neue thread nie ruft alle libc-Funktionen auf (entweder direkt oder durch Aufrufen von etwas anderem, das libc aufruft; dies beinhaltet auch die dynamische Symbolauflösung über PLT), dann können Sie den gewünschten TLS-Speicher als den Parameter new_tls an clone übergeben.

Sie sollten alle Verweise auf set_thread_area ignorieren - sie gelten nur für 32-Bit/ix86-Fall.

Wenn Sie planen libc in Ihrem verwenden neu erstellten Thread, sollten Sie verlassen Ihr Ansatz: libcerwartet TLS eine bestimmte Art und Weise eingerichtet werden, und es gibt keine Möglichkeit für Sie um ein solches Setup zu arrangieren, wenn Sie clone direkt anrufen.Ihr neuer Thread wird intermittierend abstürzen, wenn libc entdeckt, dass Sie TLS nicht ordnungsgemäß eingerichtet haben. Das Debuggen solcher Abstürze ist äußerst schwierig, und die einzige zuverlässige Lösung ist ... pthread_create zu verwenden.

+0

danke für die Information, ja ich plane, Aufrufe an libc. Aus Neugier, für welche Art von Dingen benutzt libc den TLS-Bereich? Da es auch Programme gibt, die pthread_create (single threaded) nicht verwenden, ist es in diesem Fall wichtig, den TLS-Bereich einzurichten, den libc benötigt. –

+0

Einige Dinge libc verwendet es für: function pointer für beschleunigte syscalls (x86), stack canary (wenn stack protector), pid cache (verwendet von getpid), tid cache (zum Identifizieren des Besitzers von Sperren), errno (was Thread ist -lokal). Ich bin mir sicher, dass es mehr Anwendungen gibt, an die ich auch nicht denke. –

0

Die andere Antwort ist absolut richtig, da das Einrichten eines Threads außerhalb der Kontrolle von libc garantiert zu einem bestimmten Zeitpunkt Probleme verursacht. Sie können es tun, aber Sie können sich nicht länger auf die Dienste von libc verlassen, definitiv nicht auf eine der pthread_* Funktionen oder Thread-lokalen Variablen (definiert als solche mit __thread oder thread_local).

Sie können eines der für TLS (GS und FS) verwendeten Segmentregister sogar auf x86-64 setzen. Der Systemaufruf, nach dem gesucht werden soll, lautet prctl(ARCH_SET_GS, ...).

Sie können ein Beispiel zum Vergleich der Einrichtung von TLS-Registern auf i386 und x86-64 in sehen.