【问题标题】:How to do console input like in the "top" linux command?如何在“top”linux命令中进行控制台输入?
【发布时间】:2012-12-28 15:33:21
【问题描述】:

因此,linux top 命令具有带有控制台输出的实时循环(没什么花哨的),但它使用非阻塞控制台输入,不会在命令行中显示键入的字符。它是怎么做的?有没有它的库,他们使用线程吗?我需要编写一个具有相同风格的 linux 应用程序(通过 ssh 使用),但我不知道如何输入(单独线程中的 cin 不是解决方案,top 使用其他东西)。

【问题讨论】:

  • 你是怎么解决的?如果答案对您有所帮助,请接受。如果您自己发现了一些东西,您可以自己发布答案。这样,如果人们将来有相同(或相似)的问题,您的问题可能会有很大帮助。
  • @Chad:发布有关正在解决的问题的评论时没有答案。我首先发表了一条评论,后来我用答案替换了它。
  • @Chad:而且它更具社交性,因为 OP 希望我们为他投入时间,当然是免费的,但他似乎对帮助未来的访客不感兴趣。
  • 我发表评论时没有答案。问题已解决,因为感谢评论我知道它是哪个库。

标签: c++ c linux input console


【解决方案1】:

一种解决方案是使用curses 的实现。

我不知道top是怎么做到的。

【讨论】:

  • 好吧:ldd /usr/bin/top 显示 libncurses.so.5 => /lib64/libncurses.so.5。所以top 使用 ncurses。
【解决方案2】:

另一种选择,不使用诅咒:

#include <stdio.h>
//#include <unistd.h>
#include <termios.h>
//#include <sys/ioctl.h>
//#include <sys/time.h>
//#include <sys/types.h>
#include <fcntl.h>

//------------------------------------------------------------------------------
// getkey() returns the next char in the stdin buffer if available, otherwise
//          it returns -1 immediately.
//
int getkey(void)
{
    char ch;
    int error;
    struct termios oldAttr, newAttr;
    int oldFlags, newFlags;
    struct timeval tv;
    int fd = fileno(stdin);
    tcgetattr(fd, &oldAttr);
    newAttr = oldAttr;
    oldFlags = fcntl(fd, F_GETFL, 0);

    newAttr.c_iflag = 0; /* input mode */
    newAttr.c_oflag = 0; /* output mode */
    newAttr.c_lflag &= ~ICANON; /* line settings */
    newAttr.c_cc[VMIN] = 1; /* minimum chars to wait for */
    newAttr.c_cc[VTIME] = 1; /* minimum wait time */

    // Set stdin to nonblocking, noncanonical input
    fcntl(fd, F_SETFL, O_NONBLOCK);
    error=tcsetattr(fd, TCSANOW, &newAttr);

    tv.tv_sec = 0;
    tv.tv_usec = 10000; // small 0.01 msec delay
    select(1, NULL, NULL, NULL, &tv);

    if (error == 0)
        error=(read(fd, &ch, 1) != 1); // get char from stdin

    // Restore original settings
    error |= tcsetattr(fd, TCSANOW, &oldAttr);
    fcntl(fd, F_SETFL, oldFlags);

    return (error ? -1 : (int) ch);
}

int main()
{
    int c,n=0;
    printf("Hello, world!\nPress any key to exit. I'll wait for 4 keypresses.\n\n");
    while (n<4)
    {
        //printf("."); // uncomment this to print a dot on each loop iteration
        c = getkey();
        if (c >= 0)
        {
            printf("You pressed '%c'\n", c);
            ++n;
        }
    }
}

很抱歉,我不能完全相信这一点,因为很多年前我就把它从网上撤下了。我想我已经对其进行了一些调整,但与我得到它的地方相比,它几乎没有变化。不幸的是,我没有添加说明我在哪里找到它的评论。

【讨论】:

  • 看起来不错。它需要一些库来编译还是只需要标准库?
  • @user1873947 - 没有特殊的库,只有 C 标准库和 CRT。我在我的答案中添加了文件顶部的#includes,并注释掉了我认为函数本身实际上不需要的那些,但将它们留在那里以防我错了。
  • @user1873947 - 我不知道...它适用于使用 GCC 4.7.2 的 CentOS 5.8 上的我。我很确定我是从我以前使用的 Solaris 机器上按原样移植的,但那是三年前的事了。编写一个简单的 main() 来测试这一点并不难。
  • @user1873947 - 示例 main() 添加到上面的帖子中。
  • @Spidey - 我认为您可以使用newAttr.c_lflag &amp;= ~(ICANON | ECHO); 而不是newAttr.c_lflag &amp;= ~ICANON;,但您必须更改getkey() 函数的整个策略,该函数(如所写)无条件保存和恢复标准输入终端模式,这将在返回之前重新打开回声。此链接显示了如何在不使用 curses/ncurses 的情况下询问密码(不使用 echo):forums.fedoraforum.org/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-07
  • 1970-01-01
  • 1970-01-01
  • 2022-06-14
  • 2017-08-23
  • 2010-11-08
相关资源
最近更新 更多