概述为什么read()会永远阻塞
我正面临着一个令人困惑的问题,最近才开始。
我有一个程序使用一个线程写入一个文件,另一个线程从该文件读取。 两个线程都使用不同的文件描述符。 写入器线程使用O_WRONLY标志打开文件,读取器线程以O_RDONLY模式打开文件。 就逻辑而言,读者线程不知道写者线程正在做什么,并且两者都可以使用不同的文件。
写入器线程以固定的间隔连续写入文件(数据来自高达20Mbit / s的设备stream)。
读者线程也定期读取文件。
Python将0写入文件
Bash脚本捕获input,运行命令并打印到文件
Python – stdout总是“可用”?
Ant在回应文件时不会创buildNL
最快的方式来计算目录大小
这是阅读器循环:
while (tot < sz) { LOG(VB_file,LOG_DEBUG,LOC + QString(\”read(%1) — begin\”).arg(sz-tot)); ret = read(fd2,(char *)data + tot,sz – tot); LOG(VB_file,LOC + QString(\”read(%1) -> %2 end\”).arg(sz).arg(ret)); if ((sz – tot) != ret) { LOG(VB_file,LOC + QString(\”errno = %1\”).arg(errno)); } if (ret < 0) { if (errno == EAGAIN) { LOG(VB_file,LOC + QString(\”read(%1) -> %2 EAGAIN\”).arg(sz).arg(ret)); usleep(1000); continue; } LOG(VB_GENERAL,LOG_ERR,LOC + \”file I/O problem in \’safe_read()\’\” + ENO); errcnt++; numfailures++; if (errcnt == 3) break; } else if (ret > 0) { tot += ret; } […snipped…] }
您可以看到,我在读取被调用之前显示日志,并在返回之后立即显示日志。 不时读,将被称为,它永远不会回来…
2014-02-19 11:24:10.156417 D TFW(/external/recordings/1001_20140219002351.mpg:64): write(65424) cnt 1 total 5076 2014-02-19 11:24:10.156466 D TFW(/external/recordings/1001_20140219002351.mpg:64): total written so far: 26934760 bytes 2014-02-19 11:24:10.156514 D fileRingBuf(/external/recordings/1001_20140219002351.mpg): read(65536) — begin 2014-02-19 11:24:10.190769 D fileRingBuf(/external/recordings/1001_20140219002351.mpg): read(65536) -> 60968 end 2014-02-19 11:24:10.190781 I RingBuf(/external/recordings/1001_20140219002351.mpg): safe_read(…@1698944,65536) -> 65536,took 60 ms (8.73813Mbps) 2014-02-19 11:24:10.190786 D RingBuf(/external/recordings/1001_20140219002351.mpg): total read so far: 26930304 bytes 2014-02-19 11:24:10.190795 I fileRingBuf(/external/recordings/1001_20140219002351.mpg): read(65536) — begin 2014-02-19 11:24:10.195917 D fileRingBuf(/external/recordings/1001_20140219002351.mpg): read(65536) -> 4456 end 2014-02-19 11:24:10.195927 D fileRingBuf(/external/recordings/1001_20140219002351.mpg): errno = 0 2014-02-19 11:24:10.206445 D TFW(/external/recordings/1001_20140219002351.mpg:64): write(65424) cnt 1 total 1692 2014-02-19 11:24:10.206489 D TFW(/external/recordings/1001_20140219002351.mpg:64): total written so far: 27000184 bytes 2014-02-19 11:24:10.256103 D fileRingBuf(/external/recordings/1001_20140219002351.mpg): read(61080) — begin 2014-02-19 11:24:10.256499 D TFW(/external/recordings/1001_20140219002351.mpg:64): write(47376) cnt 1 total 40984 2014-02-19 11:24:10.262073 D TFW(/external/recordings/1001_20140219002351.mpg:64): total written so far: 27047560 bytes 2014-02-19 11:24:10.273385 D TFW(/external/recordings/1001_20140219002351.mpg:64): write(65424) cnt 1 total 940 2014-02-19 11:24:10.385495 D TFW(/external/recordings/1001_20140219002351.mpg:64): total written so far: 27112984 bytes
你可以在这里看到作者写了26934760字节的磁盘。 到目前为止读取已经读取了26930304个字节,所以我们是来自EOF的4456个字节。 然后尝试64kB读取,读取几乎立即返回4456字节。 到现在为止还挺好。 立即尝试另一个读取61080字节(65536-4456)。
很快,写入器线程再次写入文件。 64kB读取现在正在等待,并且不会再出现30多秒。
那么为什么一个阅读会突然永远阻塞的任何特定的想法?
编辑:通过查看行为,如果在发生新写入之前立即重试读取 *** 作,则在读取到达EOF并返回之前,封锁总是会发生。 在这种情况下,读取将不会退出几秒钟(通常是20+)
以不妨碍其他进程修改的方式读取文件
linux的aio(不是posix)的例子?
在使用Perl的windows中进行文件input和读取时遇到问题
创build未刷新的文件输出缓冲区
如何从“a +”模式打开的文件读取?
好…
我发现了这个问题,以及如何解决这个问题。
正如在原始问题中提到的那样,一旦读取到达EOF,堵塞似乎总是发生,提前返回并立即重试读取(在文件发生新的写入之前)。
在这种情况下,read()将不会退出几秒钟(通常超过20秒)
所以解决的办法是记录到目前为止我们已经读了多少字节,以便知道它在文件中的位置,然后调用fstat来检查文件的大小。 从这个角度来看,如果我们已经在文件末尾,请确保我们不会调用read(),或者请求read()来获取比文件中更多的字节。
struct stat sb; off_t current_pos = internalreadpos; while (tot < sz) { off_t toread = sz – tot; bool read_ok = true; // check that we have some data to read,// so we never attempt to read past the end of file // if fstat errored or isn\’t a regular file,default to prevIoUs behavior ret = fstat(fd2,&sb); if (ret == 0 && S_ISREG(sb.st_mode)) { if (current_pos >= sb.st_size) { // We\’re at the end,don\’t attempt to read read_ok = false; LOG(VB_file,LOC + \”not reading,reached EOF\”); } else { toread = min(sb.st_size – current_pos,toread); if (toread < (sz-tot)) { LOG(VB_file,LOC + QString(\”About to reach EOF,reading %1 wanted %2\”) .arg(toread).arg(sz-tot)); } } } if (read_ok) { LOG(VB_file,LOC + QString(\”read(%1) — begin\”).arg(toread)); ret = read(fd2,toread); LOG(VB_file,LOC + QString(\”read(%1) -> %2 end\”).arg(toread).arg(ret)); } if (ret < 0) { if (errno == EAGAIN) continue; LOG(VB_GENERAL,LOC + \”file I/O problem in \’safe_read()\’\” + ENO); errcnt++; numfailures++; if (errcnt == 3) break; } else if (ret > 0) { tot += ret; current_pos += ret; } if (oldfile) break; if (ret == 0) // EOF returns 0 { if (tot > 0) break; zerocnt++; // 0.36 second timeout for livetvchain with usleep(60000),// or 2.4 seconds if it\’s a new file less than 30 minutes old. if (zerocnt >= (livetvchain ? 6 : 40)) { break; } }
总结
以上是内存溢出为你收集整理的为什么read()会永远阻塞全部内容,希望文章能够帮你解决为什么read()会永远阻塞所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
请登录后查看评论内容