GNU/Linux >> Belajar Linux >  >> Linux

Bagaimana Anda melakukan non-blocking console I/O di Linux di C?

Saya ingin menambahkan contoh:

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

Saat Anda menjalankan program ini, Anda memiliki waktu 4 detik untuk memberikan input ke standar. Jika tidak ada input yang ditemukan, input tidak akan diblokir dan hanya akan dikembalikan.

2 contoh eksekusi:

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

Seperti Pete Kirkham, saya menemukan cc.byexamples.com, dan berhasil untuk saya. Pergi ke sana untuk penjelasan yang baik tentang masalah, serta versi ncurses.

Kode saya perlu mengambil perintah awal dari input standar atau file, lalu perhatikan perintah batal saat perintah awal diproses. Kode saya adalah C++, tetapi Anda harus dapat menggunakan scanf() dan sisanya di mana saya menggunakan fungsi input C++ getline() .

Daging adalah fungsi yang memeriksa apakah ada input yang tersedia:

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

Ini harus dipanggil sebelum fungsi input stdin Ketika saya menggunakan std::cin sebelum menggunakan fungsi ini, tidak pernah mengembalikan true lagi. Misalnya, main() memiliki loop yang terlihat seperti ini:

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

Di utas input, perintah baru ditambahkan ke antrean, yang diproses secara berkala oleh jobThread . inputThread terlihat sedikit seperti ini:

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

Fungsi ini mungkin ada di main() , tetapi saya bekerja dengan basis kode yang sudah ada, bukan menentangnya.

Untuk sistem saya, tidak ada input yang tersedia hingga baris baru dikirim, yang memang saya inginkan. Jika Anda ingin membaca setiap karakter saat diketik, Anda harus mematikan "mode kanonik" di stdin. cc.byexamples.com memiliki beberapa saran yang belum saya coba, tetapi sisanya berhasil, jadi seharusnya berhasil.


Linux
  1. Linux – Bagaimana Cara Memantau Disk I/o Di Direktori Tertentu?

  2. Linux dan port penyelesaian I/O?

  3. Bagaimana cara membersihkan cache I/O disk di Linux?

  1. Bagaimana Anda memulai Linux?

  2. Pelajari Dasar-dasar Cara Kerja Pengalihan I/O (Input/Output) Linux

  3. Di linux, bagaimana Anda memeriksa apakah sebuah disk terfragmentasi?

  1. Pelaporan I/O dari baris perintah Linux

  2. Cara Menemukan Shell Yang Anda Gunakan di Linux

  3. Cara mendapatkan lebar jendela konsol Linux dengan Python