2016-03-26 11 views
0

Ich möchte ein Modell der vollständig verbundenen Mesh-Topologie machen. Ich habe Eltern und Kinder, die miteinander kommunizieren. Daher muss jeder Prozess Daten aus mehreren Pipes lesen. Und ich weiß nicht, wie ich das machen soll.Lesen von Daten aus mehreren Rohren

Jeder Prozess hat "lokale ID" als Inkrement (0 - Eltern, 1,2,3 usw.).

Ich habe 2d Array von Rohren erstellt. Ein erster Array - Zielorte, zweite Arrays - Quellen:

struct pipes_t 
{ 
    int rdwr[2]; 
}; 

struct dataIO_t 
{ 
    int processes; // number of processes 
    int8_t lid; // prosecc local id (0,1,2 etc) 
    struct pipes_t pipes[MAX_LOCAL_ID+1][MAX_LOCAL_ID+1]; 
}; 

Funktion für Multicast-Nachricht zu senden:

int send(struct dataIO_t* data) { 
    for(int i = 0; i < data->processes; i++) 
     if(write(data->pipes[i][data->lid].rdwr[1], "Hello world\n", 12) != 1) 
      return 1; 
    return 0; 
} 

Wie Daten aus vielen Rohren von jedem Prozess, ohne Fäden lesen? Ich versuchte Funktion zu verwenden dup2 zum Anschluss alle Leitungen in einem, aber es war keine gute Idee:

int receive(struct dataIO_t* data) { 
    int fd[2]; 
    pipe(fd); 

    const int BSIZE = 100; 
    ssize_t nbytes; 
    char buf[BSIZE]; 

    for(int i = 0; i < data->processes; i++) 
     if(i != data->lid) 
      if (dup2(data->pipes[data->lid][i].rdwr[0], fd[0]) == -1) 
       return 1; 

    nbytes = read(fd[0], buf, BSIZE); 
    printf("Msg (%d): %s\n", data->lid, buf); 

    return 0; 
} 

Verbote: in dieser Übung kann ich nicht poll, select und gleiche Funktionen.

+0

Die Funktion die Sie suchen, ist 'poll'; Es wartet auf mehrere Dateideskriptoren und gibt zurück, welche zum Lesen oder Schreiben bereit sind. Es gibt auch 'select', was alt ist, und' epoll', was etwas komplizierter ist. –

+0

@ColonThirtyTwo Ich aktualisierte die Frage, ich kann diese Funktionen nicht verwenden –

+0

Nun, wenn Sie die sinnvollen Optionen nicht verwenden können (['select()'] (http://pubs.opengroup.org/onlinepubs/9699919799/ Funktionen/select.html) und ['Poll()'] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html) und Nicht-Standard-Verwandten), dann müssen Sie machen die nicht-blockierenden Lesedateideskriptoren (['fcntl()'] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html), 'F_GETFL',' F_SETFL' und 'O_NONBLOCK'), und Sie müssen jeden Dateideskriptor durchlaufen, um zu sehen, ob Daten zum Lesen verfügbar sind. –

Antwort

3

Sie sagen, Sie aus mehreren Datei-Deskriptoren lesen möchten, ohne Abstimmung, wählen usw.

Wie Sie entdeckt haben, können Sie nicht einfach aus einer von mehreren Rohren lesen und hoffen, dass es funktioniert, denn wenn es keine Daten, du wirst blocken.

Um dies zu lösen, können Sie alle Datei Deskriptoren setzen Sie als non-blocking lesen möchten, die eine Leseeinrichtung von ihnen sofort zurück, wenn keine Daten verfügbar sind.

In Pseudo-Code:

for each fd in fds 
    mode = fcntl(fd, F_GETFL); 
    fcntl(fd, F_SETFL, mode | O_NONBLOCK) 

forever 
    for each fd in fds 
     if read(fd) 
      process data 
    sleep a little to avoid 100% CPU usage 
+0

Funktioniert 'setsockopt()' an Pipedeskriptoren und nicht an Socketdeskriptoren? –

+0

@ JonathanLeffler: Guter Punkt, ich habe meinen Pseudo-Code aktualisiert, um 'fcntl()' zu verwenden, was definitiv funktioniert (in dem Ausmaß, in dem Pseudo-Code definitiv funktionieren kann!). –

+0

Sie sollten 'select' oder' poll' anstelle von busy-waiting verwenden. – jch