我注意到当我使用open + lseek查询设备的大小时,一切正常,但是当我对设备进行stat时,得到的不是实际设备大小,而是零。该设备是干净的,没有任何文件系统,并且该设备的首字节以“1234567890ABC”之类的文本开头。怎么了?

代码:

#include <sys/stat.h>
#include <dirent.h>

bool
GetFileSize(const char* pPath, uint64_t& Size)
{
    pPath = "/home/sw/.bashrc";
    pPath = "/dev/sda";

    struct stat buffer;
    if (stat(pPath, &buffer))
    {
        printf("Failed to stat file. Error: %s. FilePath: %s\n", strerror(errno), pPath);
        return false;
    }

    printf("File size by stat: %" PRIu64 " WTF?\n", buffer.st_size);

    //
    // Note: It's strange, but stat::st_size from the stat call is zero for devices
    //

    int File = open(pPath, O_RDONLY);
    if (File < 0)
    {
        printf("Failed to open file. Error: %s. FilePath: %s\n", strerror(errno), pPath);
        return false;
    }

    long off = lseek(File, 0, SEEK_END);
    if (off == (off_t)-1)
    {
        printf("Failed to get file size. Error: %s. FilePath: %s\n", strerror(errno), pPath);
        close(File);
        return false;
    }
    close(File);

    printf("File size by lseek: %" PRIu64 "\n", off);
    fflush(stdout);

    Size = off;
    return true;
}

输出:
File size by stat: 0 Huh?
File size by lseek: 34359738368

如果我将stat用于常规文件,则一切正常(用“/dev/sda”注释掉):
File size by stat: 4019 Huh?
File size by lseek: 4019

最佳答案

细节在于魔鬼...对于初学者来说,Unix设计的基本原理是:一切都是文件,很好explained here

第二个是stat(2)调用为您提供存储在文件系统中的设备专用文件的inode统计信息,该文件的大小为零(将其视为lstat(2))。如果您的块设备上有文件系统,则可以使用statfs(2)getfsstat(2)statvfs(2)以与文件系统/设备无关的方式获取有关该文件的信息。

处理特殊文件(通常位于/dev中)始终是系统特定的,并且手册页位于第4节中。因此,如果您想直接操作设备,则应在此处详细阅读。例如,在Linux中,man 4 hd将向您展示如何与IDE块设备进行编程交互。而man 4 sd将为您提供如何与scsi光盘等进行交互的方式。

第三,系统调用不应在功能上或功能上与它们不一致。

希望这有所帮助。

关于c - 为什么stat::st_size 0 for devices but at the same time lseek defines the device size correctly?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55164462/

10-16 01:09