c - select() 返回无效参数

标签 c unix select pipe

我成功地从另一个线程的管道中读取数据,并打印输出(恰好在 ncurses 窗口中)。

出于各种原因,我需要一次执行一个字符,并且我在 FD 上使用 select() 作为管道的读取端,以及一些其他 FD(如标准输入)。

我的想法是仅在管道即将被读取时才尝试从管道读取,而不是处理任何输入。这似乎在起作用——至少开始了。 select() 设置 fd_set,如果是 FD_ISSET,我会从 FD 读取 1 个字节。但是 select() 说是一次太多了,read() 阻塞了。

所以我的问题是 - 为什么 select() 会报告 fd 已准备好读取,如果后续的 read() 阻塞?

(大约)当管道的另一端连接到一个 fork 进程时,同样的代码可以正常工作,如果有帮助的话。

我可以根据要求发布代码,但它是沼泽标准。设置一个 fd_set,复制它,选择副本,如果设置了 FD,则调用一个从同一 FD 读取字节的函数...否则恢复 fd_set 副本

编辑:应要求,代码如下:

设置我的 fd_set:

fd_set fds;
FD_ZERO(&fds); 
FD_SET(interp_output[0], &fds);
FD_SET(STDIN_FILENO, &fds);
struct timeval timeout, tvcopy; timeout.tv_sec=1;
int maxfd=interp_output[0]+1; //always >stdin+1
fd_set read_fds;
FD_COPY(&fds, &read_fds);

在循环中:

if (select(maxfd, &read_fds, NULL, NULL, &timeout)==-1) {perror("couldn't select"); return;}
if (FD_ISSET(interp_output[0], &read_fds)) {
    handle_interp_out();
} else if (FD_ISSET(STDIN_FILENO, &read_fds)) {
//waddstr(cmdwin, "stdin!"); wrefresh(cmdwin);
    handle_input();
}

FDCOPY(&fds, &read_fds);

handle_interp_out():

void handle_interp_out() {
    int ch;
    read(interp_output[0], &ch, 1);
    if (ch>0) {
            if (ch=='\n') { if (cmd_curline>=cmdheight) cmdscroll(); wmove(cmdwin, ++cmd_curline, 1); }
            else waddch(cmdwin, ch);
            wrefresh(cmdwin);
    }
}

编辑 2:写入代码只是用 fdopen(interp_output[1], "w") 打开的 FILE* 上的 fprintf - 这是在不同的线程中。我所要做的只是我的“提示>”——它正确地打印了所有内容,但又进行了一次它不应该进行的迭代。我关闭了缓冲,这给我带来了其他问题。

编辑 3:这已成为我调用 select() 的问题。看起来,它立即返回 -1 并且 errno 被设置为“无效参数”。 read() 不知道这一点,只是继续前进。我的 select() 有什么问题?我更新了代码并更改了标题以更准确地反射(reflect)问题...

编辑 4:所以现在我完全糊涂了。不知何故,.tv_sec=1 的超时值不好。通过摆脱它,代码工作得很好。如果有人有任何理论,我洗耳恭听。我会将其保留为 NULL,除非该线程需要定期进行更新。

最佳答案

为了绝对保证读取永远不会阻塞,您必须在 fd 上设置 O_NONBLOCK。

您的选择错误几乎可以肯定是因为您没有设置整个时间结构。你只是在设置秒数。另一个字段将包含从堆栈中拾取的垃圾数据。

使用结构初始化。这将保证其他字段设置为 0。

看起来像这样:

struct timeval timeout = {1, 0};

此外,在您的选择循环中,您应该知道 Linux 会将剩余时间写入超时值。这意味着下一次循环不会为 1 秒,除非您将该值重置为 1 秒。

关于c - select() 返回无效参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4364474/

相关文章:

unix - 使用 xargs 从文档中查找行

mysql - SQL - 如何搜索包含反斜杠的字符串

sql - Firebird存储过程内的"select..into"

java - 从 Java 运行 apachetop

通过 awk 插入 CSV 列

c - 在 C 中处理文本文件的异常行为

c - 返回包含 C 中本地指针的结构

python - 如何通过 python/pandas 中另一个数据框的值来标记数据框列的最有效方式?

C - 读取整个文件最后带有垃圾

c - 数组比较算法