2017-05-16 3 views
1

Gibt es eine Möglichkeit, einen Socket fd aus Objekt des Typs struct sock im Kernel zu erhalten? Der schnelle Einblick in struct sock hilft nicht dabei, etwas zu finden, das wie Socket-Deskriptor aussieht. Grundsätzlich brauche ich, was socket() syscall zurückgibt, ist es nicht in "Socke" gespeichert?abgeleitet Socket fd von 'struct Sock'

Ich brauche fd an dem Punkt, bevor ein Paket IP-Stack trifft.

Danke.

+2

fd Zahlen existieren auf Basis pro Prozess nur, so ist es unklar, was tun müssen, wenn Sie nach einem fd im Kernel zu fragen. – Martin

+0

@Martin, danke für einen Kommentar. Wenn ich ein 'struct sock'-Objekt habe, möchte ich wissen, welchem ​​'fd' im Userspace es entspricht. – Mark

+1

Ich meine, du musst wahrscheinlich anders herum anfangen. Nehmen Sie die Dateideskriptortabelle eines bestimmten Prozesses, durchlaufen Sie sie und prüfen Sie, ob einige Datensätze auf den betreffenden Socket zeigen. Ein und derselbe Socket kann durch mehr fds in einer oder mehreren Benutzerraumaufgaben bezeichnet werden. (Sorry, keine detaillierte Antwort, wie ich es gerade jetzt machen könnte, da ich einige Details überprüfen müsste und jetzt keine Zeit mehr hätte, vielleicht später, wenn niemand schneller antworten wird.) – Martin

Antwort

3

Für jeden Prozess gibt es eine Tabelle von Datei-Deskriptoren, die Dateideskriptoren struct file Objekte abbildet. Sie können mit der Funktion iterate_fd() über diese Tabelle iterieren.

Für jede struct file können Sie bestimmen, welches struct sock Objekt entspricht sock_from_file() Funktion entspricht.

Insgesamt:

/* 
* Callback for iterate_fd(). 
* 
* If given file corresponds to the given socket, return fd + 1. 
* Otherwise return 0. 
* 
* Note, that returning 0 is needed for continue the search. 
*/ 
static int check_file_is_sock(void* s, struct file* f, int fd) 
{ 
    int err; 
    struct sock* real_sock = sock_from_file(f, &err); 
    if(real_sock == s) 
     return fd + 1; 
    else 
     return 0; 
} 
// Return file descriptor for given socket in given process. 
int get_fd_for_sock(struct sock* s, struct task* p) 
{ 
    int search_res; 
    task_lock(p); 
    // This returns either (fd + 1) or 0 if not found. 
    search_res = iterate_fd(p->files, 0, &check_file_is_sock, s); 
    task_unlock(p); 

    if(search_res) 
     return search_res - 1; 
    else 
     return -1; // Not found 
} 
+0

Beachten Sie, dass es durchaus möglich ist, dass es sein wird Kein Prozess, bei dem der Socket geöffnet ist, mehr als ein Prozess, bei dem der Socket geöffnet ist, und sogar Prozesse, die denselben Socket mehr als einmal geöffnet haben. –

+0

@Tsyvarev, danke für die Antwort. Habe ich recht, dass der Code, den Sie vorschlagen, nur im Prozesskontext funktionieren würde? Wie würde ich andernfalls einen 'task_struct'-Zeiger erhalten? Ich muss 'fd' an dem Punkt bekommen, bevor ein Paket den IP-Stack erreicht. – Mark

+0

Dies muss kein * Prozesskontext * sein. Sie können 'task_struct' zu einem früheren Zeitpunkt speichern und hier verwenden. Oder iteriere über alle Aufgaben, um eins zu finden, das ein gegebenes "Socken" -Objekt enthält. In jedem Fall brauchen Sie das 'task_struct'-Objekt, da ein Dateideskriptor ohne es * bedeutungslos * ist. Genau das ist im Kommentar zu Ihrer Frage und meiner Antwort angegeben. – Tsyvarev

Verwandte Themen