2016-02-10 1 views
0

J'ai un problème avec read() bloquant le programme de mine en essayant de lire à partir de fifo. Je veux que mon programme lise des descripteurs de fichiers multiples et pendant que l'un contient des informations, il l'écrira sur la sortie standard.sélectionnez les blocs fifo à partir de la lecture

J'ai essayé d'utiliser select mais cela ne semble pas fonctionner.

main.c (il y a un nombre n du deuxième programme)

for(i=0;i<n;i++) 
{ 
    fd[i] = open(myfifo[i], O_RDWR); 
    printf("%s\n",myfifo[i]); 
} 
while(1) 
{ 
     for(i=0;i<n;i++) 
     { 
      FD_ZERO(&set); 
      FD_SET(fd[i], &set); 
      n = select(fd[i]+1, &set, NULL, NULL, NULL); 
      if (n > 0) 
      { 
       r = read(fd[i], &demon1, sizeof(demon1)); 
       if(r !=-1) 
       { 
        /*READ DATA*/ 
       } 
      } 
     }  
} 

deuxième programme (il y a un nombre n de ce programme)

void signal_handler(int signum) 
{ 
if (signum == SIGUSR1) 
{ 
    /*STAFF*/ 
    mkfifo(myfifo, 0666); 
    fd = open(myfifo, O_RDWR); 
    write(fd, &demon1 , sizeof(demon1)); 
    close(fd); 
} 
} 

chaque programme a fifo nommé myfifo1, myfifo2 .. etc. S'il vous plaît aider.

EDIT: Maintenant, j'ai ceci:

int max_fd; 
while(1) 
{ 
FD_ZERO(&set); 
for(i=0;i<n;i++) 
{ 
    FD_SET(fd[i], &set); 
    if (fd[i]>max_fd) max_fd = fd[i]; 
} 
n = select(max_fd+1, &set, NULL, NULL, NULL); 
if (n != 0) 
{ 
    int d; 
    for (d = 0; d<FD_SETSIZE; d++) 
    { 
     if (FD_ISSET(d,&set)) 
     { 
      r = read(d, &demon1, sizeof(demon1)); 
      if(r !=-1) 
      { 
       /*CODE*/ 
      } 
     } 
    } 
} 
} 

Reads correcte que sur le premier essai, plus tard il ne lit que la première FileDescriptor

apparemment, il y a une diffrence entre

//n = select(max_fd+1, &set, NULL, NULL, NULL); 
//if (n != -1) 

et

if (select(max_fd+1, &set, NULL, NULL, NULL) != -1) 

EDIT: Il semble fonctionner uniquement sur la machine virutale ubuntu .. ordinateur portable linux mint ne fonctionne pas.

+0

Vous utilisez 'select' correctement. Il ne devrait pas être appelé pour chaque fd. Le point principal de 'select' est qu'il peut surveiller plusieurs fds en un seul appel. Vous devez remplir 'set' avec tous les fds et faire un seul appel' select' pour chacun d'entre eux. – kaylum

+0

Vous ne devriez normalement pas ouvrir fifos de cette façon, vous devriez ouvrir pour lire ou écrire, pas lire et écrire sur le même descripteur. –

+0

avec le mode de blocage? Je ne pense pas que c'est la raison? – Thomas

Répondre

1

Non, vous devez construire un ensemble de lecture, puis faire un appel select:

// Create the set of descriptor to select on 
FD_ZERO(&set); 
max_fd = 0; 
for (i=0; i<n; i++) { 
    FD_SET(fd[i], &set);    // add the descriptor to the set 
    if (fd[i]>max_fd) max_fd = fd[i]; // register the highest descriptor 
} 

// Then select on the set of descriptors 
if (select(max_fd+1, &set, NULL, NULL, NULL)!=-1) { 
    // extract which descriptors are available for reading 
    for (int d=0; d<FD_SETSIZE; d++) { 
     if (FD_ISSET(d,&set)) { 
      // something to read in descriptor d 
     } 
    } 
} 
+0

Je pense qu'il devrait être si (select (max_fd + 1, & set, NULL, NULL, NULL)! = - 1), de toute façon ça ne marche pas. Maintenant, il lit seulement à partir du dernier descripteur – Thomas

+0

En fait, il lit seulement à partir du premier qui enverra msg – Thomas

+0

Quelque chose ne va pas ailleurs. Observez la valeur de set avant et après select. Si quelque chose est incohérent, trouvez le problème en conséquence. Si les valeurs sont cohérentes, quelque chose peut mal se passer sur la partie émettrice ... –