Книга: Разработка приложений в среде Linux. Второе издание

11.4.1. Создание входных точек устройств и именованных каналов

11.4.1. Создание входных точек устройств и именованных каналов

Процессы создают файлы устройств и именованных каналов в файловой системе с помощью вызова mknod().

#include <fcntl.h>
#include <unistd.h>
int mknod(const char *pathname, mode_t mode, dev_t dev);
pathname
— это имя файла, который нужно создать, mode — это и режим доступа (который модифицируется текущим umask), и тип нового файла (S_IFIFO, S_IFBLK, S_IFCHR). Последний параметр, dev, содержит старший (major) и младший (minor) номера создаваемого устройства. Тип устройства (символьное или блочное) и старший номер устройства сообщают ядру, какой драйвер устройств отвечает за операции с этим файлом устройства. Младший номер используется внутри драйвером устройства, чтобы различать отдельные устройства среди многих, которыми он управляет. Только пользователю root разрешено создавать файлы устройств; именованные же каналы могут создавать все пользователи.

Заголовочный файл <sys/sysmacros.h> представляет три макроса для манипулирования значениями типа dev_t. Макрос makedev() принимает старшие номера в первом аргументе, младшие — во втором и возвращает значение dev_t, ожидаемое mknod(). Макросы major() и minor() принимают значение типа dev_t в качестве единственного аргумента и возвращают, соответственно, старший и младший номер устройства.

Программа mknod, доступная в Linux, предоставляет пользовательский интерфейс к системному вызову mknod() (подробности см. в man 1 mknod). Ниже приведена упрощенная реализация mknod для иллюстрации системного вызова mknod(). Следует отметить, что программа создает файл с режимом доступа 0666 (предоставляя право на чтение и запись всем пользователям) и зависит от системной установки umask процесса для получения прав доступа.

 1: /* mknod.с */
 2:
 3: /* Создать устройство или именованный канал, указанный в командной строке.
 4:    См. подробности о параметрах командной строки
 5:    на man-странице mknod(1). */
 6:
 7: #include <errno.h>
 8: #include <stdio.h>
 9: #include <stdlib.h>
10: #include <string.h>
11: #include <sys/stat.h>
12: #include <sys/sysmacros.h>
13: #include <unistd.h>
14:
15: void usage(void) {
16:  fprintf (stderr, "использование: mknod <путь> [b | с | u | p]"
17:   "<старший> <младший>n");
18:  exit(1);
19: }
20:
21: int main(int argc, const char **argv) {
22:  int major = 0, minor = 0;
23:  const char *path;
24:  int mode = 0666;
25:  char *end;
26:  int args;
27:
28:  /* Всегда необходимы, как минимум, тип создаваемого inode
29:     и путь к нему. */
30:  if (argc < 3) usage();
31:
32:  path = argv[1];
33:
34:  /* второй аргумент указывает тип создаваемого узла */
35:  if (!strcmp(argv[2], "b")) {
36:   mode | = S_IFBLK;
37:   args = 5;
38:  } else if (!strcmp(argv[2] , "с") || !strcmp(argv[2], "u")) {
39:   mode |= S_IFCHR;
40:   args = 5;
41:  } else if(!strcmp(argv[2], "p")) {
42:   mode |= S_IFIFO;
43:   args = 3;
44:  } else {
45:   fprintf(stderr, "неизвестный тип узла %sn", argv[2]);
46:   return 1;
47:  }
48:
49:  /* args сообщает, сколько аргументов ожидается, поскольку нам нужно
50:    больше информации при создания устройств, чем именованных каналов*/
51:  if (argc != args) usage();
52:
53:  if (args == 5) {
54:   /* получить старший и младший номера файла устройств,
55:      который нужно создать */
56:   major = strtol(argv[3], &end, 0);
57:   if (*end) {
58:    fprintf(stderr,"неверный старший номер %sn", argv[3]);
59:    return 1;
60:   }
61:
62:   minor = strtol(argv[4], &end, 0);
63:   if (*end) {
64:    fprintf(stderr, "неверный младший номер %sn", argv[4]);
65:    return 1;
66:   }
67:  }
68:
69:  /* если создается именованный канал, то финальный параметр
70:     игнорируется */
71:  if (mknod(path, mode, makedev(major, minor))) {
72:   fprintf(stderr, "вызов mknod не удался : %sn", strerror(errno));
73:   return 1;
74:  }
75:
76:  return 0;
77: }

Оглавление книги


Генерация: 5.672. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз