Книга: Linux программирование в примерах

5.3.1.1. Анализ переносимости

5.3.1.1. Анализ переносимости

Есть несколько соображений по переносимости. Во-первых, не следует предполагать, что двумя первыми элементами, возвращаемыми readdir(), всегда будут '.' и '..'. Многие файловые системы используют организацию каталогов, которые отличаются от первоначального дизайна Unix, и '.' и '..' могут быть в середине каталога или даже вовсе не присутствовать[55].

Во-вторых, стандарт POSIX ничего не говорит о возможных значениях d_info. Он говорит, что возвращенные структуры представляют элементы каталогов для файлов; это предполагает, что readdir() не возвращает пустые элементы, поэтому реализация GNU/Linux readdir() не беспокоится с возвратом элементов, когда 'd_ino == 0'; она переходит к следующему действительному элементу.

Поэтому по крайней мере на системах GNU/Linux и Unix маловероятно, что d_ino когда-нибудь будет равен нулю. Однако, лучше по возможности вообще избегать использования этого поля.

Наконец, некоторые системы используют d_fileno вместо d_ino в struct dirent. Знайте об этом, когда нужно перенести на такие системы код, читающий каталоги.

Косвенные системные вызовы

«Не пробуйте это дома, дети!»

- М-р Wizard -

Многие системные вызовы, такие, как open(), read() и write(), предназначены для вызова непосредственно из кода пользователя: другими словами, из кода, который пишете вы как разработчик GNU/Linux.

Однако, другие системные вызовы существуют лишь для того, чтобы дать возможность реализовать стандартные библиотечные функции более высокого уровня, и никогда не должны вызываться непосредственно. Одним из таких системных вызовов является GNU/Linux getdents(); он читает несколько элементов каталога в буфер, предоставленный вызывающим — в данном случае, кодом реализации readdir(). Затем код readdir() возвращает действительные элементы каталога, по одному за раз, пополняя при необходимости буфер.

Эти системные вызовы только-для-библиотечного-использования можно отличить от вызовов для-использования-пользователем по их представлению в странице справки. Например, из getdents(2).

ИМЯ
  getdents - получить элементы каталога
ОПИСАНИЕ
  #include <unistd.h>
  #include <linux/types.h>
  #include <linux/dirent.h>
  #include <linux/unistd.h>
  _syscall3(int, getdents, uint, fd, struct dirent*,
            dirp, uint, count);
  int getdents(unsigned int fd, struct dirent *dirp,
               unsigned int count);

Любой системный вызов, использующий макрос _syscallX(), не должен вызываться кодом приложения. (Дополнительную информацию об этих вызовах можно найти в справочной странице для intro(2); вам следует прочесть эту справочную страницу, если вы этого еще не сделали.)

В случае getdents() на многих других системах Unix есть сходный системный вызов; иногда с тем же именем, иногда с другим. Поэтому попытка использования этих вызовов привела бы в любом случае лишь к большому беспорядку с переносимостью; гораздо лучше во всех случаях использовать readdir(), интерфейс которого хорошо определен, стандартизован и переносим.

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


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