Программирование в Linux: на каком устройстве находится файл - PullRequest
5 голосов
/ 01 апреля 2011

Я хотел бы знать, в какой записи в / dev находится файл. Например, если / dev / sdc1 смонтирован в / media / disk, и я спрашиваю /media/disk/foo.txt, я бы получить / dev / sdc в качестве ответа.

Используя системный вызов stat для этого файла, я получу его старшие и младшие номера (8 и 33 для sdc1). Теперь мне нужно получить «корневое» устройство (sdc) или его мажор / минор. Есть ли какая-нибудь функция syscall или библиотеки , которую я мог бы использовать, чтобы связать раздел с его основным устройством? Или даже лучше, чтобы получить это устройство прямо из файла?

brw-rw---- 1 root floppy 8, 32 2011-04-01 20:00 /dev/sdc
brw-rw---- 1 root floppy 8, 33 2011-04-01 20:00 /dev/sdc1

Заранее спасибо!

Ответы [ 5 ]

8 голосов
/ 01 апреля 2011

Быстрая и грязная версия: df $file | awk 'NR == 2 {print $1}'.

Программно ... ну, есть причина, по которой я начал с быстрой и грязной версии.Нет переносимого способа программно получить список смонтированных файловых систем.(getmntent() получает fstab записей, что не одно и то же.) Более того, вы даже не можете надежно проанализировать вывод mount(8);в разных Unix-системах точка монтирования может быть первым или последним элементом.Самый переносимый способ сделать это в конечном итоге ... парсинг df output (И даже это ненадежно, как вы заметили по номеру раздела).Таким образом, вы все равно вернетесь к быстрому и грязному решению оболочки, если только вы не захотите пройти /dev и искать блочные устройства с совпадающими major(st_rdev) (major() от sys/types.h).

Если вы ограничите это для Linux, вы можете использовать /proc/mounts, чтобы получить список смонтированных файловых систем.Аналогичным образом можно оптимизировать и другие конкретные Unix: например, в OS X и, я думаю, FreeBSD, вы можете использовать sysctl() в дереве vfs для получения точек монтирования.В худшем случае вы можете найти и использовать соответствующий заголовочный файл для расшифровки любого файла таблицы монтирования (и да, даже если он варьируется: в Solaris это /etc/mnttab, во многих других системах это /etc/mtab, некоторые системы помещают его в /var/run вместо /etc, а во многих Linux он либо отсутствует, либо является символической ссылкой на /proc/mounts).И его формат отличается практически во всех Unix-подобных ОС.

3 голосов
/ 02 апреля 2011

Требуемая информация существует в sysfs, которая предоставляет дерево устройств linux.Это моделирует отношения между устройствами в системе, и, так как вы пытаетесь определить родительское дисковое устройство из раздела, это место для поиска.Я не знаю, существуют ли какие-либо жесткие и быстрые правила, на которые можно положиться, чтобы остановить разрыв кода с будущими версиями ядра, но разработчики ядра стараются поддерживать sysfs как стабильный интерфейс.

Есливы посмотрите на /sys/dev/block/<major>:<minor>, вы увидите, что это символическая ссылка с компонентами хвоста, равными block/<disk-device-name>/<partition-device-name>.Если вы должны выполнить системный вызов readlink(2), вы можете проанализировать место назначения ссылки, чтобы получить имя дискового устройства.В оболочке (так как это проще выразить, но сделать это в C будет довольно просто):

$ echo $(basename $(dirname $(readlink /sys/dev/block/8:33)))
sdc

В качестве альтернативы, вы можете воспользоваться вложенностью каталогов разделов в каталогах дисков (опять же вshell, но из C, это open(2), read(2) и close(2)):

$ cat /sys/dev/block/8:33/../dev
8:32

Предполагается, что ваш начальный мажор: младший на самом деле для раздела, а не какой-то другойустройство.

2 голосов
/ 02 апреля 2011

То, что вы ищете, невозможно - нет соединения 1: 1 между файлом блочного устройства и разделом, который он описывает.

Рассмотрим:

  1. Вы можете создать несколько файлов блочных устройств с разными именами (но с одинаковыми старшими и младшими номерами), и они будут неразличимы (N: 1)

  2. Вы можете использовать файл блочного устройства в качестве аргумента для монтирования, чтобы смонтировать раздел, а затем удалить файл блочного устройства, оставив раздел монтированным. (0: 1)

Так что нет способа сделать то, что вы хотите, кроме как в нескольких конкретных и узких случаях.

1 голос
/ 02 апреля 2011

Старший номер сообщит вам, какое это устройство: 3 - IDE на 1-м контроллере, 22 - IDE на 2-м контроллере и 8 для SCSI.

Младший номер сообщит вам номер раздела и - для устройств IDE -если это основной или дополнительный диск.Этот расчет отличается для IDE и SCSI.

Для IDE это: x * 64 + p, x - номер диска на контроллере (0 или 1), а p - раздел

для SCSI.это: y * 16 + p, где y - номер диска, а p - раздел

0 голосов
/ 10 мая 2016

Не системный вызов, но:

df -h /path/to/my/file

С https://unix.stackexchange.com/questions/128471/determine-what-device-a-directory-is-located-on

Так что вы можете посмотреть исходный код df и посмотреть, что он делает.

Я понимаю, что этот пост старый, но этот вопрос был вторым результатом в моем поиске, и никто не упомянул df -h

...