Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C语言的Linux上实现非阻塞控制台I/O? < P> > Linux中的“非阻塞控制台IO”如何在C?< /P> > P>这里有一个相关问题,使用C++ +< /P> < P>不完全确定您所说的“控制台IO”是指从STDIN读取的,还是从其他源读取的控制台应用程序?_C_Linux_Macos_Io_Nonblocking - Fatal编程技术网

如何在C语言的Linux上实现非阻塞控制台I/O? < P> > Linux中的“非阻塞控制台IO”如何在C?< /P> > P>这里有一个相关问题,使用C++ +< /P> < P>不完全确定您所说的“控制台IO”是指从STDIN读取的,还是从其他源读取的控制台应用程序?

如何在C语言的Linux上实现非阻塞控制台I/O? < P> > Linux中的“非阻塞控制台IO”如何在C?< /P> > P>这里有一个相关问题,使用C++ +< /P> < P>不完全确定您所说的“控制台IO”是指从STDIN读取的,还是从其他源读取的控制台应用程序?,c,linux,macos,io,nonblocking,C,Linux,Macos,Io,Nonblocking,如果您正在从STDIN读取数据,则需要跳过fread并使用read-and-write、poll或select来阻止调用。您可以使用setbuf禁用输入缓冲,这会导致fread返回EOF,但我从未尝试过。您确实没有。TTY控制台是一个非常有限的设备,您几乎不做非阻塞I/O。当您看到一些看起来像非阻塞I/O的东西时,例如在curses/ncurses应用程序中,您所做的事情称为原始I/O。在原始I/O中,没有字符解释,没有擦除处理等,您需要编写自己的代码,在执行其他操作时检查数据 在现代C程序中,

如果您正在从STDIN读取数据,则需要跳过fread并使用read-and-write、poll或select来阻止调用。您可以使用setbuf禁用输入缓冲,这会导致fread返回EOF,但我从未尝试过。

您确实没有。TTY控制台是一个非常有限的设备,您几乎不做非阻塞I/O。当您看到一些看起来像非阻塞I/O的东西时,例如在curses/ncurses应用程序中,您所做的事情称为原始I/O。在原始I/O中,没有字符解释,没有擦除处理等,您需要编写自己的代码,在执行其他操作时检查数据

在现代C程序中,通过将控制台I/O放入线程或轻量级进程,可以用另一种方式简化这一过程。然后,I/O可以以通常的阻塞方式继续进行,但数据可以插入到队列中,以便在另一个线程上进行处理

使现代化 这里有一个更详细的说明。

我在本月早些时候加入了书签,当时我认为我可能需要无阻塞、无缓冲的控制台输入,但我没有,因此无法保证它是否有效。就我的使用而言,我不在乎它在用户按enter键之前没有得到输入,所以我只是用来读取标准输入。去那里了解问题的详细解释,以及ncurses版本

我的代码需要从标准输入或文件中获取初始命令,然后在处理初始命令时观察cancel命令。我的代码是C++,但是你应该能够使用SCANF,其余的地方我使用C++输入函数GETLIN。 肉类是一种检查是否有任何可用输入的功能:

#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));
}
在输入线程中,新命令被添加到队列中,该队列由jobThread定期处理。inputThread看起来有点像这样:

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;
}
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;
}
这个函数可能在main中,但我使用的是现有的代码库,而不是反对它


对于我的系统,在发送新行之前没有可用的输入,这正是我想要的。如果要在键入时读取每个字符,则需要关闭stdin上的规范模式。有一些我没有尝试过的建议,但其余的都有效,所以应该有效。

使用ncurses或threads的另一个替代方法是使用,特别是其中允许您使用的部分。因此,模式是:

在任何其他描述符中使用标准DIN上的select 当select告诉您STDIN已准备好读取时,调用readline的rl\u callback\u read\u char 如果用户输入了完整的行,rl_callback_read_char将调用您的回调。否则它将立即返回,您的其他代码可以继续。
我想添加一个示例:

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

当然,您可以在tty上执行非阻塞IO。这就是大多数单线程文本ui程序的工作原理。答案实际上是错误的。即使fd 0连接到tty,也可以使用fcntl0、F|u SETFL、fcntl0、GETFL | O|u NONBLOCK-这通常是不推荐的,因为它会让其他使用标准输入法的人感到困惑,但它是有效的。我在评论之前读了三遍,一直都是以s/do/ca/的形式读的。虽然我不完全同意这个答案,但它是一致的…@eph,当这种情况发生时,你不恨吗?NP正如您所说,您可以使其非阻塞。不过,考虑到这个问题,我很确定提问者要求的是原始I/O。@ephemient我认为应该是F_GETFLIt看起来你颠倒了链接。抄送。举例。。。链接到Pete Kirkham的个人资料,反之亦然。很好的示例来源,做了我需要的。这个讨论C非阻塞键盘输入为我解决了问题:这是正确的答案。它涵盖了刚刚在GNU/Linux上测试的两种操作系统。请记住,此解决方案仍将缓冲输入。e、 g.您需要按enter键将输入传递到程序。为了更清楚,我将使用STDIN_FILENO而不是0作为文件描述符
Korays-MacBook-Pro:~ koraytugay$ ./a.out
fda 
You said: fda
Korays-MacBook-Pro:~ koraytugay$ ./a.out
Korays-MacBook-Pro:~ koraytugay$