简体   繁体   English

如果我使用fread会出错,而使用read则不会出错

[英]get error if i use fread, while no error using read

I'm trying to make some experiments on disk I/O using cache and not using it. 我正在尝试使用缓存而不是使用缓存对磁盘I / O进行一些实验。 In order to perform a read directly from the disk, I open the file with the O_DIRECT flag (defining the variable DISK_DIRECT). 为了直接从磁盘执行读取,我使用O_DIRECT标志(定义变量DISK_DIRECT)打开文件。

Now the two branches of the if beneath, should perform the same operation, with the difference that one is helped by the cache and the other not. 现在,如果在下面,则if的两个分支应该执行相同的操作,不同之处在于一个由缓存帮助,另一个不由缓存帮助。 The files to which I try to access are stored on disk and they do not change over time. 我尝试访问的文件存储在磁盘上,并且它们不会随时间变化。 Also the two branches access to the same files. 同样,两个分支访问相同的文件。

At some point here, when I use fread I get ferror() to be true. 在这里的某个时候,当我使用fread时,我会得到ferror()为真。 While when I use read everything goes fine. 当我使用read时,一切都很好。

I'm sure they access the same files. 我确定他们访问相同的文件。 Do you have any idea why this could happen? 您知道为什么会发生这种情况吗?

EDIT 编辑

Ok, i'm posting here an minimal example. 好的,我在这里发布一个最小的示例。 the code i use is: 我使用的代码是:

#include <iostream>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <fstream>
#include <sstream>


using namespace std;

typedef float fftwf_complex [2] ;

void fetch_level(unsigned long long tid, unsigned short level, fftwf_complex* P_read, fftwf_complex* P_fread, int n_coeff_per_level, FILE** files_o_direct, fstream* & files) {

  int b_read;
  fseek(files_o_direct[level],(long int) (tid * sizeof(fftwf_complex)*n_coeff_per_level), SEEK_SET);


  b_read = fread(reinterpret_cast<char*>(P_fread),sizeof(fftwf_complex), n_coeff_per_level,files_o_direct[level]);

  if(b_read == 0){ 
    cerr << "nothing read\n";

  }

  files[level].seekg((streamoff) (tid * sizeof(fftwf_complex)*n_coeff_per_level), files[level].beg);

  files[level].read(reinterpret_cast<char*>(P_read), 
            sizeof(fftwf_complex) * n_coeff_per_level);

}

void open_files (fstream* & files){

  for(int i=0; i<1;i++) {
    std::ostringstream oss;
    oss << "./Test_fread_read/1.txt.bin";

    files[i].open(oss.str().c_str(),
          std::ios::in | std::ios::out | 
          std::ios::binary | std::ios::ate);
    if (!files[i])
      {
    cerr << "fstream could not open " << oss.str() << endl;
      }
  }
}

void open_files_o_direct (FILE** files_o_direct, int* fd){

  for(unsigned int i=0;i<1; i++){
    std::ostringstream oss;
    oss << "./Test_fread_read/1.txt.bin";
    fd[i]=open(oss.str().c_str(), O_RDONLY | O_DIRECT);
    files_o_direct[i] = fdopen(fd[i], "rb");

    if(!files_o_direct[i])
      cerr << "Could not open " << oss.str() << endl;

  }
}

int close_files(FILE** files_o_direct, int* fd, fstream* & files) {

  for(unsigned int i=0; i<1; i++){
    //#if defined (DISK_DIRECT)
    if(files_o_direct[i])
      close(fd[i]);
    //#else
    if(files[i].is_open())
      files[i].close();
    //#endif
  }

  return 0;
}

int main(){

  FILE**files_o_direct = new FILE* [256];
  fstream* files = new fstream [256];
  int * fd = new int [256];


  fftwf_complex * P_read =  new fftwf_complex [1];
  fftwf_complex * P_fread =  new fftwf_complex [1];

  open_files_o_direct(files_o_direct, fd);
  open_files(files);

fetch_level(2, 0, P_read, P_fread, 1, files_o_direct, files);
  cout << "P_read: " << P_read[0][0] << " P_fread: " << P_fread[0][0] << endl;
  cout << "P_read: " << P_read[0][1] << " P_fread: " << P_fread[0][1] << endl;
fetch_level(7, 0, P_read, P_fread, 1, files_o_direct, files);
  cout << "P_read: " << P_read[0][0] << " P_fread: " << P_fread[0][0] << endl;
  cout << "P_read: " << P_read[0][1] << " P_fread: " << P_fread[0][1] << endl;
fetch_level(8, 0, P_read, P_fread, 1, files_o_direct, files);
  cout << "P_read: " << P_read[0][0] << " P_fread: " << P_fread[0][0] << endl;
  cout << "P_read: " << P_read[0][1] << " P_fread: " << P_fread[0][1] << endl;


  close_files(files_o_direct, fd, files);

  delete [] P_read;
  delete [] P_fread;
  delete [] files;
  delete [] files_o_direct;

  return 0;
}

and the file which is accessed is: 所访问的文件是:

0.133919 0.0458176 
1.67441 2.40805 
0.997525 -0.279977 
-2.39672 -3.076 
-0.0390913 0.854464 
-0.0176478 -1.3142 
-0.667981 -0.486272 
0.831051 0.282802 
-0.638032 -0.630943 
-0.669854 -1.49762 

which is stored in a binary format and that can be download from here: 1.txt.bin . 它以二进制格式存储,可以从此处下载:1.txt.bin

The output i get is: 我得到的输出是:

nothing read
P_read: 0.997525 P_fread: 0
P_read: -0.279977 P_fread: 0
nothing read
P_read: 0.831051 P_fread: 0
P_read: 0.282802 P_fread: 0
nothing read
P_read: -0.638032 P_fread: 0
P_read: -0.630943 P_fread: 0

The problem persists even if i change the type of fftwf_complex from float[2] to simple float. 即使我将fftwf_complex的类型从float [2]更改为简单float,问题仍然存在。 If i remove the fseek line everything works correctly. 如果我删除fseek行,一切正常。

This if (b_read == 0) , will be true at the end of the file, and you will enter this branch if (b_read == 0) ,则在文件末尾为true,您将进入此分支

if(ferror(this->files_o_direct[level]))
    fseek(this->files_o_direct[level], 0, SEEK_END); //ftell here returns 4800000 
cerr << "nothing read\n";

even if ferror returns 0, the end of the file was reached anyway 即使ferror返回0,也无论如何都到达了文件的末尾

fseek(this->files_o_direct[level], 0, SEEK_END);

makes no sense, and "nothing read\\n" will be output either or not ferror returns nonzero. 是没有意义的,而且"nothing read\\n"将被输出或者不能ferror返回非零值。

From the manual page 手册页

fread() does not distinguish between end-of-file and error, and callers must use feof(3) and ferror(3) to determine which occurred. fread()不能区分文件结尾和错误,调用者必须使用feof(3)和ferror(3)来确定发生了什么。

so you have to check feof and if it is false you use ferror . 因此,您必须检查feof ,如果它是假的,则使用ferror

For who ever may have the same problem here there is the answer: 对于可能遇到相同问题的人,这里有答案:

The O_DIRECT flag may impose alignment restrictions on the length and address of user-space buffers and the file offset of I/Os. O_DIRECT标志可能对用户空间缓冲区的长度和地址以及I / O的文件偏移量施加对齐限制。 In Linux alignment restrictions vary by filesystem and kernel version and might be absent entirely. 在Linux中,对齐限制因文件系统和内核版本而异,并且可能完全不存在。 However there is currently no filesystem-independent interface for an application to discover these restrictions for a given file or filesystem. 但是,当前没有应用程序独立于文件系统的接口来发现给定文件或文件系统的这些限制。 Some filesystems provide their own interfaces for doing so, for example the XFS_IOC_DIOINFO operation in xfsctl(3). 某些文件系统为此提供了自己的接口,例如xfsctl(3)中的XFS_IOC_DIOINFO操作。

  Under Linux 2.4, transfer sizes, and the alignment of the user buffer and the file offset must all be multiples of the logical block size of the filesystem. Since Linux 2.6.0, alignment to the logical block size of the underlying storage (typically 512 bytes) suffices. The logical block size can be determined using the ioctl(2) BLKSSZGET operation or from the shell using the command: blockdev --getss 

linux reference page linux参考页

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM