Linux 基于块的存储

Linux 基于块的存储,linux,filesystems,io,b-tree,Linux,Filesystems,Io,B Tree,我想将几个条目存储到一个文件中(针对读取进行了优化),一个好的数据结构似乎是一个B+树。它提供了一个O(log(n)/log(b))访问时间,其中b是一个块中的条目数 有很多文章等都在描述B+树,但我在理解基于块的存储系统时仍然有一些困难。也许有人能给我指出正确的方向或回答几个问题: (所有通用)文件系统是否在新块的开头创建新文件?那么,我可以确定seek(0)会将读/写头设置为设备块大小的倍数吗 我只应该使用像pread(fd,buf,n*BLOCK\u SIZE,p*BLOCK\u SIZE

我想将几个条目存储到一个文件中(针对读取进行了优化),一个好的数据结构似乎是一个B+树。它提供了一个O(log(n)/log(b))访问时间,其中b是一个块中的条目数

有很多文章等都在描述B+树,但我在理解基于块的存储系统时仍然有一些困难。也许有人能给我指出正确的方向或回答几个问题:

  • (所有通用)文件系统是否在新块的开头创建新文件?那么,我可以确定seek(0)会将读/写头设置为设备块大小的倍数吗
  • 我只应该使用像
    pread(fd,buf,n*BLOCK\u SIZE,p*BLOCK\u SIZE)
    (n,p是整数)这样的调用来确保我总是读取完整的块,这对吗
  • 将()块大小的字节读入数组还是将它们读入mmap()中更好?或者,如果我映射了许多块,而只访问了几个块,那么这仅仅是一种区别吗?什么更好
  • 我应该通过在每个块的末尾添加填充字节来避免键生成多个块吗?我是否也应该通过在数据之间添加填充字节来对叶节点执行相同的操作
  • 非常感谢,
    克里斯托夫

  • 对。否则会导致FS设计中不必要的复杂化
  • 选项(作为“仅”的替代)是
  • 在Windows内存中,映射文件的工作速度比文件API(ReadFile)快。我猜在Linux上是一样的,但是你可以自己进行测量
  • 对。否则会导致FS设计中不必要的复杂化
  • 选项(作为“仅”的替代)是
  • 在Windows内存中,映射文件的工作速度比文件API(ReadFile)快。我猜在Linux上是一样的,但是你可以自己进行测量
  • 支持延迟分配的文件系统不会在光盘上的任何位置创建新文件。许多较新的文件系统支持将非常小的文件打包到自己的页面中,或与元数据共享这些文件(例如,reiser将非常小的文件放入inode?)。但对于较大的文件,大多数情况下,是的

  • 您可以这样做,但操作系统页面缓存将始终读取整个数据块,并将您请求的位复制到应用程序的内存中

  • 这取决于您使用的是直接IO还是非直接IO

  • 如果您使用的是绕过操作系统缓存的直接IO,则不使用mmap。大多数数据库不使用mmap,而是使用直接IO

    直接IO意味着页面不经过操作系统的页面缓存,它们根本不会被操作系统缓存,也不会将其他块推出操作系统缓存。这还意味着所有读写操作都需要在块边界上完成。块边界有时可以通过文件系统上的statfs调用来确定

    大多数数据库似乎认为它们应该自己管理自己的页面缓存,并且只将操作系统用于物理读/写。因此,它们通常使用直接和同步IO

    众所周知,Linus Torvalds不同意这种方法。我认为供应商这样做是为了在不同的操作系统之间实现更好的行为一致性

  • 支持延迟分配的文件系统不会在光盘上的任何位置创建新文件。许多较新的文件系统支持将非常小的文件打包到自己的页面中,或与元数据共享这些文件(例如,reiser将非常小的文件放入inode?)。但对于较大的文件,大多数情况下,是的

  • 您可以这样做,但操作系统页面缓存将始终读取整个数据块,并将您请求的位复制到应用程序的内存中

  • 这取决于您使用的是直接IO还是非直接IO

  • 如果您使用的是绕过操作系统缓存的直接IO,则不使用mmap。大多数数据库不使用mmap,而是使用直接IO

    直接IO意味着页面不经过操作系统的页面缓存,它们根本不会被操作系统缓存,也不会将其他块推出操作系统缓存。这还意味着所有读写操作都需要在块边界上完成。块边界有时可以通过文件系统上的statfs调用来确定

    大多数数据库似乎认为它们应该自己管理自己的页面缓存,并且只将操作系统用于物理读/写。因此,它们通常使用直接和同步IO

    众所周知,Linus Torvalds不同意这种方法。我认为供应商这样做是为了在不同的操作系统之间实现更好的行为一致性

  • 通常,文件系统在新块的开头创建新文件,因为底层设备就是这样工作的。硬盘是块设备,因此不能处理小于“块”或“扇区”的任何内容。此外,操作系统根据页面处理内存和内存映射,页面通常更大(扇区通常为512或1024字节,页面通常为4096字节)。
    我想到的这个规则的一个例外是ReiserFS,它将小文件直接放入文件系统结构中(如果我没记错的话,它就是一个B+树!)。对于非常小的文件,这实际上是一个可行的优化,因为数据已经在RAM中,无需另一次搜索,但它同样可能是一个反优化,具体取决于情况

  • 这其实并不重要,因为操作系统无论如何都会将以整页(通常为4kB)为单位的数据读取到页面缓存中。读取一个字节将传输4kB并返回一个字节,从页面缓存中读取另一个字节将为您提供服务(如果它是同一页面或在readahead范围内的页面)

  • read
    是通过从页面缓存复制数据来实现的,而
    mmap
    只是将页面重新映射到您的地址空间(根据您的保护标志,可能会在写入时将其标记为copy)。因此,
    mmap
    将始终至少同样快,而且通常更快