FIFO写满之后的问题

singlaive 2011-10-04 04:07:50
在我测试的linux机器上,FIFO的容量是64K。建了一个FIFO(mkfifo,非阻塞方式)之后,write很多次直至满。此时去读一次FIFO,理论上,读了一条记录出来,就会空出至少一条记录的空间,这时候我再尝试write的话,应该成功。

实际情况却不是这样的:假如在此前write的时候,每次比如写入500字节的记录;当读取了一次之后,再尝试写入依然失败。于是在一个loop中,再读一条,再尝试写一次,如此连续8次,第9次才能够写入成功。此前已经一共读取了8次,也就是读了大约4K的字节出来。为什么会这样?

附加信息1:如果第一次读取之后尝试写入的时候,写入的不是500字节,而是很小的数目比如说2字节,那么就直接写入成功了。
附加信息2:4K正好是内存的一个页面大小……有关联么?

由于是用C做的测试,所以就发这来了。如果有更合适的版面,麻烦版主劳力移过去。
...全文
2024 15 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
glbfor_gtw 2011-10-06
  • 打赏
  • 举报
回复
楼主可以检测下errno 看看到底是什么错误。。
q2300393960 2011-10-06
  • 打赏
  • 举报
回复
????????
quwei197874 2011-10-05
  • 打赏
  • 举报
回复
学习了
singlaive 2011-10-04
  • 打赏
  • 举报
回复
可有什么方发能直接获知当前fifo的剩余空间?

有在书上看到过 fcntl(fd, F_GETPIPE_SZ)可以,但是是在linux 2.6.35之后才被支持。
singlaive 2011-10-04
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 keiy 的回复:]

个人感觉:
内存分配首先以页为单位,然后是簇
FIFO释放时,会以页为单位,所以取出一条记录并不释放内存,要满1页才行
至于写入2字节,它可以写,因为它原来空间以簇为单位,1,2簇空间应该可以写入
只是感觉.要看了源码才了解
[/Quote]

此话可有出处?
查不到。
qq120848369 2011-10-04
  • 打赏
  • 举报
回复
hen attempting to read from an empty pipe or FIFO:

* If no process has the pipe open for writing, read() shall return 0 to indicate end-of-file.

* If some process has the pipe open for writing and O_NONBLOCK is set, read() shall return -1 and set errno to [EAGAIN].

* If some process has the pipe open for writing and O_NONBLOCK is clear, read() shall block the calling thread until some data is
written or the pipe is closed by all processes that had the pipe open for writing.

When attempting to read a file (other than a pipe or FIFO) that supports non-blocking reads and has no data currently available:

* If O_NONBLOCK is set, read() shall return -1 and set errno to [EAGAIN].

* If O_NONBLOCK is clear, read() shall block the calling thread until some data becomes available.

* The use of the O_NONBLOCK flag has no effect if there is some data available.

The read() function reads data previously written to a file. If any portion of a regular file prior to the end-of-file has not
been written, read() shall return bytes with value 0. For example, lseek() allows the file offset to be set beyond the end of
existing data in the file. If data is later written at this point, subsequent reads in the gap between the previous end of data
and the newly written data shall return bytes with value 0 until data is written into the gap.

Upon successful completion, where nbyte is greater than 0, read() shall mark for update the st_atime field of the file, and shall
return the number of bytes read. This number shall never be greater than nbyte. The value returned may be less than nbyte if the
number of bytes left in the file is less than nbyte, if the read() request was interrupted by a signal, or if the file is a pipe
or FIFO or special file and has fewer than nbyte bytes immediately available for reading. For example, a read() from a file asso‐
ciated with a terminal may return one typed line of data.

read也是一样的规则。
Vincent_Song 2011-10-04
  • 打赏
  • 举报
回复
恩,可以使用相关函数监控一下,或者使用查询方式,有空了再写,而不是直接写!
qq120848369 2011-10-04
  • 打赏
  • 举报
回复
Write requests to a pipe or FIFO shall be handled in the same way as a regular file with the following exceptions:

* There is no file offset associated with a pipe, hence each write request shall append to the end of the pipe.

* Write requests of {PIPE_BUF} bytes or less shall not be interleaved with data from other processes doing writes on the same
pipe. Writes of greater than {PIPE_BUF} bytes may have data interleaved, on arbitrary boundaries, with writes by other pro‐
cesses, whether or not the O_NONBLOCK flag of the file status flags is set.

* If the O_NONBLOCK flag is clear, a write request may cause the thread to block, but on normal completion it shall return nbyte.

* If the O_NONBLOCK flag is set, write() requests shall be handled differently, in the following ways:

* The write() function shall not block the thread.

* A write request for {PIPE_BUF} or fewer bytes shall have the following effect: if there is sufficient space available in the
pipe, write() shall transfer all the data and return the number of bytes requested. Otherwise, write() shall transfer no
data and return -1 with errno set to [EAGAIN].

* A write request for more than {PIPE_BUF} bytes shall cause one of the following:

* When at least one byte can be written, transfer what it can and return the number of bytes written. When all data previ‐
ously written to the pipe is read, it shall transfer at least {PIPE_BUF} bytes.

* When no data can be written, transfer no data, and return -1 with errno set to [EAGAIN].

When attempting to write to a file descriptor (other than a pipe or FIFO) that supports non-blocking writes and cannot accept the
data immediately:

* If the O_NONBLOCK flag is clear, write() shall block the calling thread until the data can be accepted.

* If the O_NONBLOCK flag is set, write() shall not block the thread. If some data can be written without blocking the thread,
write() shall write what it can and return the number of bytes written. Otherwise, it shall return -1 and set errno to
[EAGAIN].

总结这方面的实际编程,就是一律使用非阻塞描述符:

1,写操作:检查返回值,如果是-1并且EAGAIN,那么缓冲所有数据,如果大于0,检查与请求值的差,缓冲未写入数据。

2,读操作:检查返回值,如果是-1并且EAGAIN,那么就是没数据读,如果大于0,检查与请求值的差,以便继续读。
qq120848369 2011-10-04
  • 打赏
  • 举报
回复
这些IPC的特点就是TNND写满了会阻塞,读空了会阻塞,于是setnonblock得到错误是最和谐的。

具体到编程开发上,可以用select,poll,epoll来监听读,于是你知道可以读了。监听写,于是你知道IPC有容量了,可以写东西进去了。

如果write返回错误且errno==EAGAIN或者返回值小于请求值,把剩余的数据存到你自己的buffer里,注册写事件,等到写事件的时候再write。

柯本 2011-10-04
  • 打赏
  • 举报
回复
个人感觉:
内存分配首先以页为单位,然后是簇
FIFO释放时,会以页为单位,所以取出一条记录并不释放内存,要满1页才行
至于写入2字节,它可以写,因为它原来空间以簇为单位,1,2簇空间应该可以写入
只是感觉.要看了源码才了解



70,026

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧