2009-06-30 6 views
0

Je dois surveiller un port série et traiter ses données. En tant que programme de test, j'utilisais select pour un seul port. La fonction d'exécution est la suivante:Select() ne fonctionne pas dans le thread

void <ProtocolClass>::run() 
{ 
    int fd = mPort->GetFileDescriptor(); 
    fd_set readfs; 
    int maxfd=1; 
    int res; 
    FD_ZERO(&readfs); 
    FD_SET(fd,&readfs); 
    struct timeval Timeout; 
    Timeout.tv_usec=0; 
    Timeout.tv_sec=3; 


    //BYTE ack_message_frame[ACKNOWLEDGE_FRAME_SIZE]; 
    while(true) 
    { 
     usleep(10); 
     res=select(maxfd,&readfs,NULL,NULL,NULL); 
     if(res<0) 
      perror("\nselect failed"); 
     else if(res==0) 
       puts("TIMEOUT"); 
     else if(FD_ISSET(fd,&readfs)) 
     {//IF INPUT RECEIVED 
      qDebug("************RECEIVED DATA****************"); 
     FlushBuf(); 
     qDebug("\nReading data into a read buffer"); 
     int bytes_read=mPort->ReadPort(mBuf,1000); 
     mFrameReceived=false; 
     for(int i=0;i<bytes_read;i++) 
     { 
      qDebug("%x",mBuf[i]); 
     } 



     //if complete frame has been received, write the acknowledge message frame to the port. 
     if(bytes_read>0) 
     { 
      qDebug("\nAbout to Process Received bytes"); 
      ProcessReceivedBytes(mBuf,bytes_read); 
      qDebug("\n Processed Received bytes"); 
      if(mFrameReceived) 
     { 
     int no_bytes=mPort->WritePort(mAcknowledgeMessage,ACKNOWLEDGE_FRAME_SIZE); 
      }//if frame received 
     }//if bytes read > 0 
     } //if input received 
    }//end while 
} 

Mais le problème est qu'il n'a pas semblé fonctionner comme rien ne se passe. Quelqu'un peut-il suggérer la bonne façon de le faire. Je veux utiliser select par thread. Est-ce faisable. Pouvez-vous me donner un exemple de code pour le faire. J'ai cherché le net mais les exemples sont très basiques impliquant juste la fonction principale. Il n'y a pas d'exemples spécifiques à C++. J'utilise des threads Qt en passant.

Merci

Répondre

5

Je pense que je sais quel est le problème.

FD_ZERO(&readfs); 
FD_SET(fd,&readfs); 

Les lignes ci-dessus doivent figurer dans la boucle while. Parce que, select call réinitialisera la position du bit 'fd' dans la structure readFs. Ainsi, la prochaine fois que select est appelé, il sait ce que les descripteurs de fichiers doivent interroger, car tous sont réinitialisés ici.

La correction proposée par stefaanv devrait également être inclus

+0

merci l'homme, cela a fonctionné. Mais pourquoi est-ce si ?????????? – rocknroll

+0

L'appel select bloque-t-il définitivement? je ne pense pas, c'est le cas le code aurait dû travailler avec la forme de la solution stefaanv pour une lecture au moins pouvez-vous le tester? La raison de havig FD_SET dans la boucle while est; select call manipule la structure readFs et peut réinitialiser la position du bit correspondant à fd s'il n'y a pas de données disponibles, donc la sélection suivante est appelée la position du bit correspondant à fd sera désactivée. c'est-à-dire que le select ne va pas interroger votre fd. – Warrior

2

première chose que je remarque: maxfds doit être fd + 1. Est-ce que cette aide?

+0

essayé que l'homme, il n'a pas travaillé – rocknroll

+0

cela a fonctionné couplé avec la suggestion donnée ci-dessous. Merci stefaanv – rocknroll

1

Je suis d'accord avec stefaanv, vous devez passer dans le descripteur de fichier +1 pour sélectionner(). Pour cette raison, il ne surveille même pas votre descripteur de fichier pour les données. En outre, j'ai remarqué que vous n'avez jamais passé votre valeur de délai d'attente à select(), donc il bloque indéfiniment jusqu'à ce que quelque chose soit disponible.