3

select、FD_ISSET、read などを使用して ttyUSB ポートから読み取る linux c コードに問題があります。私のモデムは入力に FTDI シリアル - USB ケーブルを使用しています。問題は、USB ケーブルが取り外されたときに選択がブロック解除されることです。それを防ぐ方法はありますか?

count = 0;
while ( g_running ) {
   FD_ZERO(&readFdSet);
   maxfd = 0;
   numTransPorts = 0;
   logger( DEBUG, "Begin g_running loop - %d", count );
   for ( i = 0; i < MAX_CONFIG_PORTS; i++ ) {
      if ( configPorts[i].commType == 1 && configPorts[i].pttyHost != NULL ) {
         FD_SET( configPorts[i].pttyHost->fd, &readFdSet );
         logger( DEBUG, "FD_SET - fd=%d, index=%d", configPorts[i].pttyHost->fd, i );
         if ( configPorts[i].pttyHost->fd >= maxfd ) {
            maxfd = configPorts[i].pttyHost->fd;
         }
         numTransPorts++;
      }
   }
   maxfd++; // add one because select check a range to n-1 file descriptors
   if ( maxfd != 0 ) { // indicates no ports are available
      logger( DEBUG, "Calling select() with %d ports and maxfd of %d", numTransPorts, maxfd );
      logger( INFO, "Waiting for input ..." );
      select( maxfd, &readFdSet, NULL, NULL, NULL ); // blocking until one available
      if( result == -1 ){
         logger( INFO, "select() error. errno: %d", errno );
      } else if ( result > 0 ){
         for ( i = 0; i < MAX_CONFIG_PORTS; i++ ) {
            if ( FD_ISSET( configPorts[i].pttyHost->fd, &readFdSet ) ) { // input is available
               logger( INFO, "Input on port %s", configPorts[i].pttyHost->serialPath );
               result = serialPortRead( buffer, configPorts[i].pttyHost->fd );
               if ( result <= 0 ) {
                  // there was an error due to the file descriptor. It
                  // probably indicates that the tty ports are no longer available
               }
            }
         }
      } else {
         logger ( INFO, "select() returns 0" );
      }
   }
   count++;
}

シリアルポート読み取り:

int serialPortRead( char *buf, int serialHandle ) {
   //char ch;
   char *ptr;
   int res = 0;
   int bytesRead = 0;
   int i;

   logger( TRACE, "TRACE: serialPortRead() with fd = %d", serialHandle );

   ptr = buf;

   // try 3 times
   for ( i = 0; i < 3; i++ ) {
      while ( (res = read( serialHandle, ptr, 1 )) > 0 ) { // read 1 byte at a time
         if ( *ptr == 0x0d ) { //there is 0x0d as a terminate byte from ECR
            break;
         }
         ptr += res;
      }
      if ( res < 0 && errno == EAGAIN ) {
         continue;
      } else {
         break;
      }
   }

   *ptr = 0x00; // set 0x00 as a terminate byte
   //   pthread_mutex_unlock(&g_serial_trans_mutex);
   if ( res < 0 ) {
      // if res is -1, there is an error
      bytesRead = -1;
      logger( DEBUG, "serialPortRead error. errno = %d", errno );
   } else {
      bytesRead = (int) (ptr - buf);
      logger( DEBUG, "serialPortRead %d bytes", bytesRead );
   }

   return bytesRead;
}

USB ケーブルが取り外されると、select() はブロックを解除し、入力が利用可能であることを意味し、FD_ISSET は true を返します。serialPortRead の read() は、0 バイトが読み取られた状態で戻ります。次に、select() にループバックし、入力が利用可能であると再度​​ブロックを解除します。したがって、select() の無限ループが発生し、FD_ISSET は true を返し、fd は決してクリアされず、read は 0 を返します。どうすればこれを修正できますか? 私が期待する動作は、実際に読み取るものが何もないときに選択が誤ってブロック解除されないことですか?

注: select がブロックを解除すると、正の数が返されます

4

1 に答える 1

5

select()読み取る情報があるため、が返されます。この場合、ファイル記述子が「ファイルの終わり」に達したという事実です。これは をread()返すことで示され0ます。

read()を返すときは0、対応するファイル記述子を閉じる必要があります。

于 2012-06-05T14:28:49.190 に答える