GNU/Linux >> Linux Esercitazione >  >> Linux

Come si esegue l'I/O della console non bloccante su Linux in C?

Voglio aggiungere un esempio:

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

Quando esegui questo programma hai 4 secondi per fornire l'input allo standard in. Se non viene trovato alcun input, non si bloccherà e tornerà semplicemente.

2 esecuzioni di esempio:

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

Come Pete Kirkham, ho trovato cc.byexamples.com e ha funzionato per me. Vai lì per una buona spiegazione del problema, così come la versione ncurses.

Il mio codice doveva prendere un comando iniziale dall'input standard o da un file, quindi cercare un comando di annullamento mentre il comando iniziale veniva elaborato. Il mio codice è C++, ma dovresti essere in grado di usare scanf() e il resto dove uso la funzione di input C++ getline() .

La carne è una funzione che controlla se c'è qualche input disponibile:

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

Questo deve essere chiamato prima di qualsiasi funzione di input stdin Quando ho usato std::cin prima di utilizzare questa funzione, non ha mai più restituito true. Ad esempio, main() ha un ciclo simile a questo:

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

Nel thread di input, nuovi comandi venivano aggiunti a una coda, che veniva periodicamente elaborata dal jobThread . Il inputThread assomigliava un po' a questo:

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

Questa funzione probabilmente avrebbe potuto essere in main() , ma sto lavorando con una base di codice esistente, non contro di essa.

Per il mio sistema, non era disponibile alcun input fino a quando non veniva inviata una nuova riga, che era proprio quello che volevo. Se vuoi leggere ogni carattere quando viene digitato, devi disattivare la "modalità canonica" su stdin. cc.byexamples.com ha alcuni suggerimenti che non ho provato, ma il resto ha funzionato, quindi dovrebbe funzionare.


Linux
  1. Come trovare quale shell stai usando su Linux

  2. Come ottenere la larghezza della finestra della console Linux in Python

  3. Porte di completamento Linux e I/O?

  4. Come eseguo I/O di basso livello su un file di dispositivo Linux in Python?

  5. Debug della latenza I/O di Linux

Quanto swap dovresti usare in Linux?

Come verificare se sei nella sessione dello schermo o meno in Linux

Come bloccare le sessioni della console virtuale su Linux

Come modificare il tipo e la dimensione del carattere della console Linux

Come trovare quale scheda grafica hai in Linux?

Come cambiare la mappa dei tasti della console in Linux?