GNU/Linux >> Tutoriales Linux >  >> Linux

¿Cómo se realiza la E/S de la consola sin bloqueo en Linux en C?

Quiero agregar un ejemplo:

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

Cuando ejecuta este programa, tiene 4 segundos para proporcionar la entrada a la entrada estándar. Si no se encuentra ninguna entrada, no se bloqueará y simplemente regresará.

2 ejemplos de ejecución:

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

Al igual que Pete Kirkham, encontré cc.byexamples.com y funcionó para mí. Vaya allí para obtener una buena explicación del problema, así como la versión de ncurses.

Mi código necesitaba tomar un comando inicial de la entrada estándar o un archivo, luego buscar un comando de cancelación mientras se procesaba el comando inicial. Mi código es C++, pero debería poder usar scanf() y el resto donde uso la función de entrada de C++ getline() .

La carne es una función que comprueba si hay alguna entrada 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));
}

Esto tiene que llamarse antes de cualquier función de entrada estándar cuando usé std::cin antes de usar esta función, nunca volvió a ser verdadero. Por ejemplo, main() tiene un ciclo que se ve así:

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

En el hilo de entrada, se agregaron nuevos comandos a una cola, que fue procesada periódicamente por el jobThread . El inputThread se parecía un poco a esto:

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

Esta función probablemente podría haber estado en main() , pero estoy trabajando con un código base existente, no contra él.

Para mi sistema, no había entrada disponible hasta que se envió una nueva línea, que era justo lo que quería. Si desea leer cada carácter cuando se escribe, debe desactivar el "modo canónico" en stdin. cc.byexamples.com tiene algunas sugerencias que no he probado, pero el resto funcionó, así que debería funcionar.


Linux
  1. Cómo encontrar qué Shell está utilizando en Linux

  2. ¿Cómo detener el proceso 'ininterrumpible' en Linux?

  3. ¿Cómo purgar cachés de E/S de disco en Linux?

  4. ¿Cómo se crea una ventana en Linux con C++?

  5. ¿Cómo cambiar el mapa de teclas de la consola en Linux?

¿Cuánto intercambio debería usar en Linux?

Cómo verificar si está en sesión de pantalla o no en Linux

Cómo bloquear sesiones de consola virtual en Linux

Cómo cambiar el tipo y tamaño de fuente de la consola de Linux

¿Cómo encontrar qué tarjeta gráfica tienes en Linux?

¿Cómo realizo E/S de bajo nivel en un archivo de dispositivo Linux en Python?