Традиционно файлы устройств 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()
, определенных в
:
#include
#include
int major(dev_t dev); /* Старший номер устройства */
int minor(dev_t dev); /* Младший номер устройства */
dev_t makedev(int major, int minor); /* Создать значение dev_t */
(Некоторые системы реализуют их в виде макросов.)
Функция makedev()
идет другим путем; она принимает отдельные значения старшего и младшего номеров и кодирует их в значении dev_t
. В других отношениях ее использование выходит за рамки данной книги; патологически любопытные должны посмотреть
Следующая программа, ch05-devnum.c
, показывает, как использовать системный вызов stat()
, макросы проверки типа файла и, наконец, макросы major()
и minor()
.
/* ch05-devnum.c --- Демонстрация stat(), major(), minor(). */
#include
#include
#include
#include
#include
int main(int argc, char **argv) {
struct stat sbuf;
char *devtype;
if (argc != 2) {
fprintf(stderr, "usage: %s path\n", argv[0]);
exit(1);
}
if (stat(argv[1], &sbuf) < 0) {
fprintf(stderr, "%s: stat: %s\n", 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 device\n",
argv[1]);
exit(1);
}
printf("%s: major: %d, minor: %d\n", devtype,
major(sbuf.st_rdev), minor(sbuf.st_rdev));
exit(0);
}
Вот что происходит при запуске программы:
$ ch05-devnum /tmp /* Попробовать не устройство */
/tmp is not a block or character device