GNU/Linux >> Tutoriels Linux >  >> Linux

Comment faire des E/S de console non bloquantes sous Linux en C ?

Je veux ajouter un exemple :

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>

int main(int argc, char const *argv[])

{
    char buf[20];
    fcntl(0, F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK);
    sleep(4);
    int numRead = read(0, buf, 4);
    if (numRead > 0) {
        printf("You said: %s", buf);
    }
}

Lorsque vous exécutez ce programme, vous avez 4 secondes pour fournir une entrée à l'entrée standard. Si aucune entrée n'est trouvée, il ne se bloquera pas et reviendra simplement.

2 exemples d'exécution :

Korays-MacBook-Pro:~ koraytugay$ ./a.out
fda 
You said: fda
Korays-MacBook-Pro:~ koraytugay$ ./a.out
Korays-MacBook-Pro:~ koraytugay$ 

Comme Pete Kirkham, j'ai trouvé cc.byexamples.com, et cela a fonctionné pour moi. Allez-y pour une bonne explication du problème, ainsi que la version ncurses.

Mon code devait prendre une commande initiale à partir de l'entrée standard ou d'un fichier, puis surveiller une commande d'annulation pendant le traitement de la commande initiale. Mon code est C++, mais vous devriez pouvoir utiliser scanf() et le reste où j'utilise la fonction d'entrée C++ getline() .

La viande est une fonction qui vérifie s'il y a une entrée disponible :

#include <unistd.h>
#include <stdio.h>
#include <sys/select.h>

// cc.byexamples.com calls this int kbhit(), to mirror the Windows console
//  function of the same name.  Otherwise, the code is the same.
bool inputAvailable()  
{
  struct timeval tv;
  fd_set fds;
  tv.tv_sec = 0;
  tv.tv_usec = 0;
  FD_ZERO(&fds);
  FD_SET(STDIN_FILENO, &fds);
  select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
  return (FD_ISSET(0, &fds));
}

Cela doit être appelé avant toute fonction d'entrée stdin Lorsque j'ai utilisé std::cin avant d'utiliser cette fonction, elle ne retournait plus jamais true. Par exemple, main() a une boucle qui ressemble à ceci :

int main(int argc, char* argv[])
{ 
   std::string initialCommand;
   if (argc > 1) {
      // Code to get the initial command from a file
   } else {
     while (!inputAvailable()) {
       std::cout << "Waiting for input (Ctrl-C to cancel)..." << std::endl;
       sleep(1);
     }
     std::getline(std::cin, initialCommand);
   }

   // Start a thread class instance 'jobThread' to run the command
   // Start a thread class instance 'inputThread' to look for further commands
   return 0;
}

Dans le thread d'entrée, de nouvelles commandes étaient ajoutées à une file d'attente, qui était périodiquement traitée par le jobThread . Le inputThread ressemblait un peu à ceci :

THREAD_RETURN inputThread()
{
  while( !cancelled() ) {
    if (inputAvailable()) {
      std::string nextCommand;
      getline(std::cin, nextCommand);
      commandQueue.lock();
      commandQueue.add(nextCommand);
      commandQueue.unlock();
    } else {
        sleep(1);
    }
  }
  return 0;
}

Cette fonction aurait probablement pu être en main() , mais je travaille avec une base de code existante, pas contre elle.

Pour mon système, il n'y avait pas d'entrée disponible jusqu'à ce qu'une nouvelle ligne soit envoyée, ce qui était exactement ce que je voulais. Si vous souhaitez lire chaque caractère lors de la saisie, vous devez désactiver le "mode canonique" sur stdin. cc.byexamples.com a quelques suggestions que je n'ai pas essayées, mais le reste a fonctionné, donc ça devrait marcher.


Linux
  1. Rapports d'E/S à partir de la ligne de commande Linux

  2. Linux – Comment surveiller les E/S de disque dans un répertoire particulier ?

  3. Comment trouver le shell que vous utilisez sous Linux

  4. Comment arrêter le processus "sans interruption" sous Linux ?

  5. Comment créer une fenêtre sous Linux avec C++ ?

Quelle quantité d'échange devriez-vous utiliser sous Linux ?

Comment vérifier si vous êtes en session d'écran ou pas sous Linux

Comment verrouiller les sessions de la console virtuelle sous Linux

Comment changer le type et la taille de la police de la console Linux

Comment trouver quelle carte graphique avez-vous sous Linux ?

Comment purger les caches d'E/S disque sous Linux ?