1

在我的一个课程中,我们的任务是在第一个超级块中查找并打印一些值,然后将这些值与所有其他超级块以 3、5 和 7 的幂进行比较,直到分区结束。

例如,您将 superblock0 与 superblock1、0 和 3、0 和 5、0 和 7、0 和 9 等进行比较。

我在超级块中输出值的代码有效,并且我想到了一个算法,它将获得 3、5 和 7 的所有幂,但我不确定如何检测分区的结尾。

以及如何使用这些权力循环所有超级块直到结束或中断情况是什么。

下面是我访问第一个超级块的代码。

int fd;
super_block_t s;

if((fd = open(DEVICE, O_RDONLY)) < 0){ //check if disk can be read
    perror(DEVICE);
    exit(1);
} 

//read superblock
lseek(fd, OFFSET, SEEK_SET);
read(fd, &s, sizeof(s));
close(fd);
4

2 回答 2

2

您可以尝试在那里寻找并查看是否获得 a EINVAL,或者您可以使用BLKGETSIZE64ioctl 获取块设备的大小:

#include <linux/fs.h>
#include <stdint.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/ioctl.h>

void main(int argc, char** argv) {
  int fd = open(argv[1], O_RDONLY);
  uint64_t size;
  ioctl(fd, BLKGETSIZE64, &size);
  printf("Size in bytes: %llu\n", size);
}
于 2021-09-27T21:48:15.840 回答
0

文件系统所在的块设备的大小与该文件系统本身的大小之间存在差异。鉴于您的任务是对文件系统本身内的超级块进行操作,我假设您对后者更感兴趣。如果您对实际设备尺寸更感兴趣,那么@that-other-guy 的回答是正确的。

假设您正在使用ext4文件系统,并且根据此处的信息,文件系统的完整大小将是总块数乘以块大小。在超级块的结构中,相关字段有:

s_blocks_count_lo很简单,但s_log_block_size需要一些处理,因为存储的值意味着:

块大小为 2 ^ (10 + s_log_block_size)。

将所有这些放在一起,您可以执行以下操作:

uintmax_t get_filesystem_size(const char *device) {
  int fd; 
  
  if((fd = open(device, O_RDONLY)) < 0) {
    perror(device);
    exit(1);
  }   

  if (lseek(fd, 1024, SEEK_SET) < 0) {
    perror("lseek");
    exit(1);
  }

  uint8_t block0[1024];
  if (read(fd, &block0, 1024) < 0) {
    perror("read");
    exit(1);
  }

  if (s_magic(block0) != 0xef53) {
    fprintf(stderr, "bad magic\n");
    exit(1);
  }

  close(fd);

  return s_blocks_count_lo(block0) * s_block_size(block0);
}

使用以下 ext4 超级块特定的辅助函数:

uint16_t s_magic(const uint8_t *buffer) {
  return le16(buffer + 0x38);
}

uint32_t s_blocks_count_lo(const uint8_t *buffer) {
  return le32(buffer + 0x4);
}

uintmax_t s_block_size(const uint8_t *buffer) {
  return 1 << (10 + le32(buffer + 0x18));
}

和以下通用字节序辅助函数:

uint16_t le16(const uint8_t *buffer) {
  int result = 0;
  for (int i = 1; i >= 0; i--) {
    result *= 256;
    result += buffer[i];
  }
  return result;
}

uint32_t le32(const uint8_t *buffer) {
  int result = 0;
  for (int i = 3; i >= 0; i--) {
    result *= 256;
    result += buffer[i];
  }
  return result;
}
于 2021-09-28T04:39:04.303 回答