我正在写一个C程序。这是它的作用:
在线程中,循环运行:
在主程序中:
我看到的行为是select()将返回一次,长度为1,是列表中的第一个fd。第二次通过循环,选择将永远坐在那里。
这是我的输出:
thread created
Waiting on 4 file descriptors
> Wrote 'Hello to target 0 from writer 0' to 0
> Wrote 'Hello to target 0 from writer 1' to 1
> Wrote 'Hello to target 1 from writer 0' to 2
> Wrote 'Hello to target 1 from writer 1' to 3
> Sending kill to 0:0 (#0)
> Sending kill to 0:1 (#1)
> Sending kill to 1:0 (#2)
> Sending kill to 1:1 (#3)
< Got string: 'Hello to target 0 from writer 0'
Waiting on 4 file descriptors
^C
操作系统是Linux,以防万一。
链接到代码:https://dl.getdropbox.com/u/188590/fifotest.c (对不起,这有点令人发指)
谢谢, 森
答案 0 :(得分:4)
正如Lance Richardson所说,第一个问题是你需要传递最大文件描述符的数量加一,而不是文件描述符的数量。
然后你必须清理监听器线程中的内务管理 - 我获得了大部分数据,但最终收听了6个文件描述符,而不是4个。(报告的数字是现在是最大的fd,而不是文件描述符的数量。)
您还遇到一个问题,即您为每个管道写入字符串加空字节,然后是第二个字符串加上空字节。由于调度是非确定性的,因此主程序实际上将其字符串写入每个fifo,因此当侦听器线程读取它时,它会读取两个字符串。当我打印出长度时,我的总长度为41(read_len
),但每个strlen()
的字符串长度为31.换句话说,第一次读取包括'kill'部分,但是由于第一条消息末尾的尾部空值,您没有在打印输出中注意到。因此,你在等待永远不会发生的事情。
答案 1 :(得分:2)
select()调用中的第一个参数应该是编号最大的文件描述符加1,而不是fd_set中的文件描述符数。
以下是我为解决此问题所做的更改:
--- fifotest-1.c 2009-05-22 23:44:03.000000000 -0400
+++ fifotest.c 2009-05-22 23:34:00.000000000 -0400
@@ -34,19 +34,22 @@
sim_arg_t* ifs = arg;
uint32_t num_ifs;
uint32_t select_len;
+ int maxfd;
num_ifs = ifs->num_ifs;
while (num_ifs > 0) {
FD_ZERO (&set);
select_len = 0;
- for (i = 0; i < ifs->num_ifs; ++i) {
+ for (maxfd=0, i = 0; i < ifs->num_ifs; ++i) {
if (ifs->if_list[i].valid) {
FD_SET(ifs->if_list[i].fh, &set);
- ++select_len;
+ if (ifs->if_list[i].fh > maxfd)
+ maxfd = ifs->if_list[i].fh;
+ select_len++;
}
}
printf("Waiting on %d file descriptors\n", select_len);
- ret = select(select_len, &set, NULL, NULL, NULL);
+ ret = select(maxfd+1, &set, NULL, NULL, NULL);
if (ret < 0) {
fprintf(stderr, "Select returned error!\n");
continue;