GNU/Linux >> Znalost Linux >  >> Linux

Jak děláte neblokující I/O konzoly na Linuxu v C?

Chci přidat příklad:

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

Když spustíte tento program, máte 4 sekundy na zadání vstupu do standardního vstupu. Pokud nebude nalezen žádný vstup, nebude blokován a jednoduše se vrátí.

2 ukázkové provedení:

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

Stejně jako Pete Kirkham jsem našel cc.byexamples.com a fungovalo to pro mě. Jděte tam, kde najdete dobré vysvětlení problému, stejně jako verzi ncurses.

Můj kód potřeboval vzít počáteční příkaz ze standardního vstupu nebo souboru a poté sledovat příkaz zrušení, zatímco byl počáteční příkaz zpracován. Můj kód je C++, ale měli byste být schopni použít scanf() a zbytek, kde používám vstupní funkci C++ getline() .

Maso je funkce, která kontroluje, zda je k dispozici nějaký vstup:

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

Toto musí být voláno před jakoukoli vstupní funkcí stdin, když jsem použil std::cin před použitím této funkce se již nikdy nevrátila true. Například main() má smyčku, která vypadá takto:

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

Ve vstupním vláknu byly přidány nové příkazy do fronty, která byla pravidelně zpracovávána jobThread . inputThread vypadalo trochu takto:

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

Tato funkce pravděpodobně mohla být v main() , ale pracuji s existující kódovou základnou, ne proti ní.

Pro můj systém nebyl k dispozici žádný vstup, dokud nebyl odeslán nový řádek, což bylo přesně to, co jsem chtěl. Pokud chcete při psaní přečíst každý znak, musíte vypnout "kanonický režim" na stdin. cc.byexamples.com má nějaké návrhy, které jsem nezkoušel, ale zbytek fungoval, takže by to mělo fungovat.


Linux
  1. Jak získat šířku okna konzoly Linux v Pythonu

  2. Linux a porty pro dokončení I/O?

  3. Jak vyčistit diskové I/O mezipaměti v Linuxu?

  1. Jak vytvoříte okno v Linuxu s C++?

  2. Jak provedu I/O nízké úrovně na souboru zařízení Linux v Pythonu?

  3. Jak změnit mapu kláves konzole v Linuxu?

  1. Naučte se základy toho, jak funguje přesměrování I/O (vstup/výstup) v systému Linux

  2. Ladění linuxové I/O latence

  3. Jak v linuxu zkontrolujete, zda je disk fragmentovaný?