2016-03-26 29 views
0

Tam bağlantılı bir kafes topolojisi modeli yapmak istiyorum. Birbirini pipo kullanarak birbirine bağlayan ebeveynler ve çocuklar var. Dolayısıyla her işlem birkaç borudan veri okumak zorundadır. Ve bunu nasıl yapacağımı bilmiyorum.Birden çok kanaldan veri oku

Her işlemin "local id" değeri artım (0 - üst, 1,2,3 vb.) Olarak bulunur.

2d dizi boru oluşturdum. Bir ilk dizi - uçuş, ikinci diziler - kaynaklar: çok noktaya mesaj göndermek için

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]; 
}; 

Fonksiyon:

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; 
} 

Nasıl parçacığı olmadan herhangi süreçten birçok boru veri okumak için? ben birinde bağlantı için tüm boruları işlevi dup2 kullanmaya çalıştı ama o kötü bir fikir olduğunu:

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; 
} 

Yasaklar: Bu uygulamadaki ben poll, select ve aynı işlevleri kullanamazsınız.

+0

Aradığınız işlevi 'poll' olduğu; Birkaç dosya tanıtıcısını bekler ve hangisinin okuyup yazılmaya hazır olduğunu döndürür. Ayrıca eski olan “select” ve “epoll” da biraz daha karmaşık. –

+0

@ColonelThirtyTwo Soruyu güncelledim, bu işlevleri kullanamıyorum –

+0

Mantıklı seçenekleri kullanamıyorsanız (['select()'] (http://pubs.opengroup.org/onlinepubs/9699919799/ işlevler/select.html) ve ['poll()'] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html) ve standart olmayan akrabalar), sonra yapmanız gerekir okunmamış dosya tanıtıcıları (['fcntl()'] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html), "F_GETFL", "F_SETFL" ve "O_NONBLOCK"), ve okunacak herhangi bir veri olup olmadığını görmek için her bir dosya tanıtıcısını daraltmanız gerekecek. –

cevap

3

Sen anket kullanmadan çoklu dosya tarif kısımlarından okumak istediğiniz seçin vb keşfettim olabileceğiniz gibi

, sadece birkaç borulardan birinden okuyamıyor ve varsa, bunun sebebi işe yarar demek veri yok, engellersiniz.

Bunu çözmek için, okumak istediğiniz tüm dosya tanıtıcılarını engellemeyi engelleme olarak ayarlayabilirsiniz; bu, herhangi bir veri yoksa hemen okunacak demektir. 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

'setsockopt()' yuva tanımlayıcıları yerine boru tanımlayıcıları üzerinde çalışır mı? –

+0

@JonathanLeffler: İyi bir nokta, sözde kodumu, kesinlikle çalıştığım fcntl() 'yi kullanmak için güncelledim (sözde kodun kesinlikle çalışabileceği ölçüde!). –

+0

Meşgul beklemek yerine 'select' veya' poll' kullanmalısınız. – jch

İlgili konular