Книга: Linux программирование в примерах
5.4.4.1. Сведения об устройстве
5.4.4.1. Сведения об устройстве
Стандарт POSIX не определяет значение типа dev_t
, поскольку предполагалось его использование на не-Unix системах также, как на Unix-системах. Однако стоит знать, что находится в dev_t
.
Когда истинно S_ISBLK(sbuf.st_mode)
или S_ISCHR(sbuf.st_mode)
, сведения об устройстве находятся в поле sbuf.st_rdev
. В противном случае это поле не содержит никакой полезной информации.
Традиционно файлы устройств Unix кодируют старший и младший номера устройства в значении dev_t
. По старшему номеру различают тип устройства, такой, как «дисковый привод» или «ленточный привод». Старшие номера различают также разные типы устройств, такие, как диск SCSI в противоположность диску IDE. Младшие номера различают устройства данного типа, например, первый диск или второй. Вы можете увидеть эти значения с помощью 'ls -l
':
$ ls -l /dev/hda /dev/hda? /* Показать номера для первого жесткого диска */
brw-rw---- 1 root disk 3, 0 Aug 31 2002 /dev/hda
brw-rw---- 1 root disk 3, 1 Aug 31 2002 /dev/hda1
brw-rw---- 1 root disk 3, 2 Aug 31 2002 /dev/hda2
brw-rw---- 1 root disk 3, 3 Aug 31 2002 /dev/hda3
brw-rw---- 1 root disk 3, 4 Aug 31 2002 /dev/hda4
brw-rw---- 1 root disk 3, 5 Aug 31 2002 /dev/hda5
brw-rw---- 1 root disk 3, 6 Aug 31 2002 /dev/hda6
brw-rw---- 1 root disk 3, 7 Aug 31 2002 /dev/hda7
brw-rw---- 1 root disk 3, 8 Aug 31 2002 /dev/hda8
brw-rw---- 1 root disk 3, 9 Aug 31 2002 /dev/hda9
$ ls -l /dev/null /* Показать сведения также для /dev/null */
crw-rw-rw- 1 root root 1, 3 Aug 31 2002 /dev/null
Вместо размера файла ls
отображает старший и младший номера. В случае жесткого диска /dev/hda
представляет диск в целом, /dev/hda1
, /dev/hda2
и т.д. представляют разделы внутри диска. У них у всех общий старший номер устройства (3), но различные младшие номера устройств.
Обратите внимание, что дисковые устройства являются блочными устройствами, тогда как /dev/null
является символьным устройством. Блочные и символьные устройства являются отдельными сущностями; даже если символьное устройство и блочное устройство имеют один и тот же старший номер устройства, они необязательно связаны
Старший и младший номера устройства можно извлечь из значения dev_t
с помощью функций major()
и minor()
, определенных в <sys/sysmacros.h>
:
#include <sys/types.h> /* Обычный */
#include <sys/sysmacros.h>
int major(dev_t dev); /* Старший номер устройства */
int minor(dev_t dev); /* Младший номер устройства */
dev_t makedev(int major, int minor); /* Создать значение dev_t */
(Некоторые системы реализуют их в виде макросов.)
Функция makedev()
идет другим путем; она принимает отдельные значения старшего и младшего номеров и кодирует их в значении dev_t
. В других отношениях ее использование выходит за рамки данной книги; патологически любопытные должны посмотреть mknod(2).
Следующая программа, ch05-devnum.c
, показывает, как использовать системный вызов stat()
, макросы проверки типа файла и, наконец, макросы major()
и minor()
.
/* ch05-devnum.c --- Демонстрация stat(), major(), minor(). */
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
int main(int argc, char **argv) {
struct stat sbuf;
char *devtype;
if (argc != 2) {
fprintf(stderr, "usage: %s pathn", argv[0]);
exit(1);
}
if (stat(argv[1], &sbuf) < 0) {
fprintf(stderr, "%s: stat: %sn", argv[1], strerror(errno));
exit(1);
}
if (S_ISCHR(sbuf.st_mode))
devtype = "char";
else if (S_ISBLK(sbuf.st_mode))
devtype = "block";
else {
fprintf(stderr, "%s is not a block or character devicen",
argv[1]);
exit(1);
}
printf("%s: major: %d, minor: %dn", devtype,
major(sbuf.st_rdev), minor(sbuf.st_rdev));
exit(0);
}
Вот что происходит при запуске программы:
$ ch05-devnum /tmp /* Попробовать не устройство */
/tmp is not a block or character device
$ ch05-devnum /dev/null /* Символьное устройство */
char: major: 1, minor: 3
$ ch05-devnum /dev/hda2 /* Блочное устройство */
block: major: 3, minor: 2
К счастью, вывод согласуется с выводом ls
, давая нам уверенность[59], что мы в самом деле написали правильный код.
Воспроизведение вывода ls замечательно и хорошо, но действительно ли это полезно? Ответ — да. Любое приложение, работающее с иерархиями файлов, должно быть способно различать различные типы файлов. Подумайте об архиваторе, таком как tar
или cpio
. Было бы пагубно, если бы такая программа рассматривала файл дискового устройства как обычный файл, пытаясь прочесть его и сохранить его содержимое в архиве! Или подумайте о find
, которая может выполнять произвольные действия, основываясь на типе и других атрибутах файлов, с которыми она сталкивается, (find
является сложной программой; посмотрите find(1), если вы с ней не знакомы.) Или даже нечто простое, как пакет, оценивающий свободное дисковое пространство, тоже должно отличать обычные файлы от всего остального.
- Основные сведения об устройствах и драйверах
- Общие сведения
- Общие сведения о Проводнике Windows Vista
- Общие сведения о поиске и индексировании
- Общие сведения о веб-ресурсах Интернета
- Общие сведения об электронной почте
- Общие сведения о файловых менеджерах
- Основные сведения о диаграммах
- Основные сведения о базах данных и программах для их обработки
- Дополнительные сведения о gdb
- Основные сведения о запросах
- Общие сведения об учетных записях