Портативный способ определения размера сектора в Linux

Я хочу написать небольшую программу на C, которая может определить размер сектора жесткого диска. Я хотел прочитать файл, расположенный в /sys/block/sd[X]/queue/hw_sector_size, и он работал в CentOS 6/7.

Однако, когда я тестировал в CentOS 5.11, файл hw_sector_size отсутствует, и я нашел только max_hw_sectors_kb и max_sectors_kb.

Таким образом, я хотел бы знать, как я могу определить (API) размер сектора в CentOS 5 или есть ли другой лучший способ сделать это. Спасибо.


person vesontio    schedule 16.10.2016    source источник
comment
Возможный дубликат Блокировать информацию об устройстве без монтирования в Linux   -  person jww    schedule 03.04.2019


Ответы (1)


Утилита fdisk отображает эту информацию (и успешно работает на ядрах старше, чем версия 2.6.x в CentOS 5), так что кажется вероятным местом для поиска ответа. К счастью, мы живем в чудесном мире открытого исходного кода, поэтому все, что для этого требуется, — это небольшое исследование.

Программа fdisk предоставляется в составе пакета util-linux. , поэтому нам нужно это в первую очередь.

Размер сектора отображается в выводе fdisk следующим образом:

Disk /dev/sda: 477 GiB, 512110190592 bytes, 1000215216 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes

Если мы ищем Sector size в коде util-linux , мы находим его в disk-utils/fdisk-list.c:

fdisk_info(cxt, _("Sector size (logical/physical): %lu bytes / %lu bytes"),
            fdisk_get_sector_size(cxt),
            fdisk_get_physector_size(cxt));

Итак, похоже, нам нужно найти fdisk_get_sector_size, который определен в libfdisk/src/context.c:

unsigned long fdisk_get_sector_size(struct fdisk_context *cxt)
{
    assert(cxt);
    return cxt->sector_size;
}

Ну, это было не очень полезно. Нам нужно узнать, где установлен cxt->sector_size:

$ grep -lri 'cxt->sector_size.*=' | grep -v tests
libfdisk/src/alignment.c
libfdisk/src/context.c
libfdisk/src/dos.c
libfdisk/src/gpt.c
libfdisk/src/utils.c

Я начну с alignment.c, так как это имя файла звучит многообещающе. Просматривая этот файл в поисках того же регулярного выражения, которое я использовал для перечисления файлов, мы находим это:

cxt->sector_size = get_sector_size(cxt->dev_fd);

Что приводит меня к:

static unsigned long get_sector_size(int fd)
{
    int sect_sz;

    if (!blkdev_get_sector_size(fd, &sect_sz))
        return (unsigned long) sect_sz;
    return DEFAULT_SECTOR_SIZE;
}

Что, в свою очередь, приводит меня к определению blkdev_get_sector_size в lib/blkdev.c:

#ifdef BLKSSZGET
int blkdev_get_sector_size(int fd, int *sector_size)
{
    if (ioctl(fd, BLKSSZGET, sector_size) >= 0)
        return 0;
    return -1;
}
#else
int blkdev_get_sector_size(int fd __attribute__((__unused__)), int *sector_size)
{
    *sector_size = DEFAULT_SECTOR_SIZE;
    return 0;
}
#endif

И вот мы идем. Есть BLKSSZGET ioctl, который кажется полезным. Поиск BLKSSZGET приводит нас к этому вопросу о стеке с переполнением, который включает следующая информация в комментарии:

Для записи: BLKSSZGET = размер логического блока, BLKBSZGET = размер физического блока, BLKGETSIZE64 = размер устройства в байтах, BLKGETSIZE = размер устройства/512. По крайней мере, если верить комментариям в fs.h и моим экспериментам. — Эдвард Фальк

person larsks    schedule 16.10.2016
comment
Это просто потрясающе! Большое спасибо larsks! - person vesontio; 16.10.2016