【问题标题】:Cursor jumping with curses.h library使用 curses.h 库进行光标跳跃
【发布时间】:2011-12-06 02:53:36
【问题描述】:

我有一个项目使用 curses 和套接字来制作一个会说话的程序。基本上主线程启动两个线程来管理屏幕的两半,另一个线程来管理通过网络的发送/接收。代码看起来很干净,但出于某种原因,光标有时会在屏幕上随机跳跃。通常它大约三排会开始在整个地方跳跃。我没有来自 curses 的 mv___() 函数,所以我很困惑为什么光标对我来说是流氓。

这里是两个线程调用来管理屏幕两侧的函数。关于可能导致此问题的任何想法?

void *display(int sub)
{
    int bufSize = 10;
    char* buf = (char*)calloc(bufSize, sizeof(char));

    while(read(displayPipe[sub][0], buf, 1) > 0)
    {
        sem_wait(&displaySem);

        waddch(subWin[sub], buf[0]);
        wrefresh(subWin[sub]);

        sem_post(&displaySem);
    }

    free(buf);

    return NULL;

}

这是从套接字读取的函数

void *netToPipe()
{       
    int bufSize = 10;
    char* buf = (char*)calloc(bufSize, sizeof(char));

    // read from talkfd
    while(read(talkfd, buf, 1) != EOF)
    {
        // print to the bottom of the screen
        if(write(displayPipe[1][1], buf, 1) < 0)
            (void)printf("Error writing to talkfd\n");
    }

    free(buf);

    return NULL;
}

这里是 main() 的结尾,它从键盘读取并写入屏幕底部(通过管道)和套接字。

while(1)
    {
        // get a key from the subwindow
        key = wgetch(subWin[0]);        

        // we are connected to a client
        if(talkfd > 0)  
        {
            // send across network
            write(talkfd, &key, 1);
            // copy to upper portion of the screen
            write(displayPipe[0][1], &key, 1);
        }
        // we are just talking to self
        else
        {
            // send to bottom of screen
            write(displayPipe[1][1], &key, 1);
            // send to top of screen
            write(displayPipe[0][1], &key, 1);  
        }
        refresh();

    } 

【问题讨论】:

  • @sarnold 我在这里只包括安装在我们的 linux 机器上的 curses.h 头文件。我不确定或不知道curses的线程感知版本。
  • 请注意C99 introduced Variable Length Arrays——如果您的项目要求 C99 没问题,您可以将 calloc() 替换为:char buf[bufSize];
  • 人力资源管理;我在packages.ubuntu.compackages.debian.orgsoftware.opensuse.org/121/en-- 上没有找到任何ncursest 线程感知变体,这让我想知道是否有任何发行版分发了线程感知变体?
  • 同时使用多线程程序和ncurses吗?这听起来很麻烦。要么在一个进程中完成所有事情,要么使用两个进程和两个终端......多线程终端代码听起来很不对。

标签: c multithreading sockets semaphore


【解决方案1】:

鉴于已对您的程序施加的大量限制,我认为您可以做的绝对最佳是将所有 curses 函数限制在单个线程中-- 所有输入、所有输出、所有重新绘制等。保持 IO 线程专用于网络 IO,绝不是任何基于curses 的控制台 IO。因为我关心的平台上的股票诅咒不支持多线程操作,所以仍然不能保证你可以用这种方式编写一个没有错误的程序,但这是你最好的选择。

一个类似的,更类似于 Unix 的方法是使用多个 进程 而不是线程。这样一来,受保护的内存就不会让不同的进程意外地在curses 全局或静态存储上乱涂乱画,您就有更好的机会编写无错误的软件。

当然,大多数 Unix-ish 方法会使用libeventlibev 在一个线程和一个进程中多路复用所有 IO。 (但这也可能与curses 一起工作有问题。这是一个令人惊叹的软件,它的根植于三年前......)

【讨论】:

  • 程序最终还是会跳转。我只能猜测它与多线程方面有关。然而,跳跃如此糟糕的部分原因是因为我是通过 ssh 远程连接的。直接登录系统有助于解决一些跳跃问题。
  • 人力资源管理;如果您在使用ssh 时遇到问题但本地工作正常,我想知道主机上的terminfo 数据库、您的TERM 环境变量和客户端机器上的终端是否都匹配?不匹配的终端信息可能导致..非最佳..终端绘图的使用。
猜你喜欢
  • 2021-12-21
  • 2021-03-15
  • 1970-01-01
  • 1970-01-01
  • 2018-02-10
  • 1970-01-01
  • 1970-01-01
  • 2015-09-06
  • 1970-01-01
相关资源
最近更新 更多