我有一个C程序,我正在写 . 这是它的作用:
-
使用mkfifo创建n fifos
-
打开它们进行读取(设置了O_NONBLOCK标志)
-
打开它们进行写入
-
产生一个线程
在线程中,循环运行:
-
为所有n个FIFO创建文件描述符的fd_set
-
调用select(n,&my_set,NULL,NULL,NULL)
-
对于每个为I / O准备的fd(FD_ISSET(fd,&my_set)):
-
从fd读取一个字符串(读取(fd,buf,buf_len))
-
打印字符串
-
如果string == "kill",将fd标记为dead并将其从列表中删除(n--)
-
如果n == 0,则终止该线程
在主程序中:
-
对于i = 0到n
-
用字符串写入fds [i](写(fds [i],buf,buf_len))
-
对于i = 0到n
-
用字符串"kill"写入fds [i]
-
加入我创建的主题
-
退出
我看到的行为是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(对不起,这有点令人发指)
谢谢,内森
2 回答
正如Lance Richardson所说,第一个问题是你需要传递最大文件描述符的数量加一,而不是文件描述符的数量 .
然后你必须清理监听器线程中的内务管理 - 我获得了大部分数据,但最终收听了6个文件描述符,而不是4个 . (报告的数字现在是最大的fd,而不是文件描述符的数量 . )
您还遇到一个问题,即您为每个管道写入字符串加空字节,然后是第二个字符串加上空字节 . 由于调度是非确定性的,因此主程序实际上将其字符串写入每个fifo,因此当侦听器线程读取它时,它会读取两个字符串 . 当我打印出长度时,我的总长度为41(
read_len
),但每个strlen()
的字符串长度为31.换句话说,第一次读取包括'kill'部分,但您没有注意到打印输出因为第一条消息末尾的尾随空值 . 因此,你在等待永远不会发生的事情 .select()调用中的第一个参数应该是编号最大的文件描述符加1,而不是fd_set中的文件描述符数 .
以下是我为解决此问题所做的更改: