АнглийскийФранцузскийИспанский

Ad


Значок OnWorks

объяснение_lca2010 - Интернет в облаке

Запустите объяснение_lca2010 в провайдере бесплатного хостинга OnWorks через Ubuntu Online, Fedora Online, онлайн-эмулятор Windows или онлайн-эмулятор MAC OS.

Это команда объяснения_lca2010, которую можно запустить в провайдере бесплатного хостинга OnWorks, используя одну из наших многочисленных бесплатных онлайн-рабочих станций, таких как Ubuntu Online, Fedora Online, онлайн-эмулятор Windows или онлайн-эмулятор MAC OS.

ПРОГРАММА:

ИМЯ


объяснение_lca2010 - Носитель не найден: когда пора перестать пытаться читать Strerror(3)
разум.

МОТИВАЦИЯ


Идея libexplain пришла мне в голову еще в начале 1980-х. Всякий раз, когда системный вызов
возвращает ошибку, ядро ​​точно знает, что пошло не так ... и сжимает это в
менее 8 бит ERRNO. Пользовательское пространство имеет доступ к тем же данным, что и ядро, оно
должно быть возможно, чтобы пользовательское пространство могло точно выяснить, что произошло, что спровоцировало ошибку
return и используйте это для написания хороших сообщений об ошибках.

Неужели все так просто?

Ошибка Сообщения as тонкость
Хорошие сообщения об ошибках - это часто те «однопроцентные» задачи, которые сбрасываются по расписанию.
давление сжимает ваш проект. Однако хорошее сообщение об ошибке может привести к серьезным последствиям.
непропорциональное улучшение пользовательского опыта, когда пользователь пугается
неизвестная территория, обычно не встречается. Это непростая задача.

Как личный программист, автор не видел проблемы с (совершенно точной) ошибкой.
сообщения вроде этого:
плавающее исключение (дамп ядра)
пока не была указана альтернативная непрограммистская интерпретация. Но это не то
Единственное, что не так с сообщениями об ошибках Unix. Как часто вы видите такие сообщения об ошибках, как:
$ ./тупой
не могу открыть файл
$
На данный момент у разработчика есть два варианта:

1.
вы можете запустить отладчик, например GDB(1) или

2.
вы можете использовать Трассирование(1) или ферма(1) заглянуть внутрь.

· Помните, что ваши пользователи могут даже не иметь доступа к этим инструментам, не говоря уже о возможности
использовать их. (Прошло очень много времени с тех пор, как Юникс начинающий означает "только написал one
драйвер устройства".)

Однако в этом примере использование Трассирование(1) показывает
$ Трассирование -e trace = open ./тупой
open ("some / file", O_RDONLY) = -1 ENOENT (Нет такого файла или каталога)
не могу открыть файл
$
Это значительно больше информации, чем содержится в сообщении об ошибке. Обычно
глупый исходный код выглядит так
int fd = open ("что-то", O_RDONLY);
если (fd <0)
{
fprintf (stderr, «невозможно открыть файл \ n»);
выход(1);
}
Пользователю не сообщают который файл, а также не сообщает пользователю который ошибка. Был ли файл
даже там? Была ли проблема с разрешениями? Он говорит вам, что пытался открыть
файл, но, вероятно, это было случайно.

Возьмите свою подсказку и побейте ею программиста-личинки. Расскажи ему о перрор(3).
В следующий раз, когда вы воспользуетесь программой, вы увидите другое сообщение об ошибке:
$ ./тупой
open: нет такого файла или каталога
$
Прогресс, но не то, что мы ожидали. Как пользователь может исправить проблему, если сообщение об ошибке
не говорит ему, в чем проблема? Глядя на источник, мы видим
int fd = open ("что-то", O_RDONLY);
если (fd <0)
{
perror («открыть»);
выход(1);
}
Пора еще раз пробежаться с подсказкой. На этот раз сообщение об ошибке занимает один шаг.
вперед и один шаг назад:
$ ./тупой
что-то: Данный файл или каталог отсутствует
$
Теперь мы знаем файл, который он пытался открыть, но нам больше не сообщают, что он был открытый(2)
это не удалось. В данном случае это, вероятно, несущественно, но может быть значительным для
другие системные вызовы. Это могло бы быть создающих(2) вместо этого операция, подразумевающая, что
нужны разные разрешения.
const char * filename = "что-то";
int fd = open (имя файла, O_RDONLY);
если (fd <0)
{
perror (имя файла);
выход(1);
}
К сожалению, приведенный выше пример кода типичен и для неличинных программистов. Время
рассказать нашему ученику падавану о Strerror(3) системный вызов.
$ ./тупой
открытый что-то: Данный файл или каталог отсутствует
$
Это максимизирует информацию, которая может быть представлена ​​пользователю. Код выглядит как
это:
const char * filename = "что-то";
int fd = open (имя файла, O_RDONLY);
если (fd <0)
{
fprintf (stderr, «открыть% s:% s \ n», имя файла, strerror (errno));
выход(1);
}
Теперь у нас есть системный вызов, имя файла и строка ошибки. Это содержит все
информация, которая Трассирование(1) напечатан. Это настолько хорошо, насколько это возможно.

Или это?

ограничения of перрор и Strerror
Проблема, которую автор видел еще в 1980-х, заключалась в том, что сообщение об ошибке было неполным.
Относится ли «нет такого файла или каталога» к «некоторые»Или в«задачаФайл в
"некоторыеКаталог?

Беглый взгляд на страницу руководства для Strerror(3) говорит:
strerror - возвращает строку, описывающую номер ошибки
Обратите внимание: это описание ошибки номера не ошибка.

С другой стороны, ядро знает в чем была ошибка. Был конкретный момент в
код ядра, вызванный определенным условием, когда код ядра разветвляется и говорит «нет».
Может ли программа в пространстве пользователя определить конкретное условие и написать более точную ошибку?
сообщение?

Однако проблема глубже. Что делать, если проблема возникает во время читать(2) система
звонок, а не открытый(2) позвонить? Это просто для сообщения об ошибке, связанного с
открытый(2) включить имя файла, оно прямо здесь. Но чтобы иметь возможность включить имя файла
в ошибке, связанной с читать(2) системный вызов, вы должны передать имя файла всем
путь вниз по стеку вызовов, а также файловый дескриптор.

И вот что раздражает: ядро ​​уже знает, какое имя файла
дескриптор связан с. Почему программист должен передавать все избыточные данные
путь вниз по стеку вызовов, чтобы улучшить сообщение об ошибке, которое может никогда не появиться? В
на самом деле, многие программисты не беспокоятся, и возникающие в результате сообщения об ошибках еще хуже для
его.

Но это были 1980-е, на PDP11 с ограниченными ресурсами и без общих библиотек. Назад
тогда не было включено ни одной разновидности Unix / Proc даже в зачаточной форме, и Lsof(1) программа
было больше десяти лет назад. Так что идея была отложена как непрактичная.

уровень Infinity Поддержка
Представьте, что вы уровень поддержки бесконечности. В вашей должностной инструкции сказано, что вы никогда не
всегда нужно поговорить с пользователями. Почему же тогда все еще есть постоянный поток людей, желающих
Вы, местный гуру Unix, расшифровали очередное сообщение об ошибке?

Как ни странно, 25 лет спустя, несмотря на простую систему разрешений, реализованную с полным
последовательность, большинство пользователей Unix до сих пор не знают, как расшифровать «Нет такого файла или каталога»,
или любые другие загадочные сообщения об ошибках, которые они видят каждый день. Или, по крайней мере, загадочно, чтобы
их.

Разве не было бы хорошо, если бы техподдержка первого уровня не нуждалась в расшифровке сообщений об ошибках?
Было бы неплохо иметь сообщения об ошибках, которые пользователи могли бы понять, не звоня
техническая поддержка?

Эти дни / Proc в Linux более чем способен предоставить информацию, необходимую для декодирования
подавляющее большинство сообщений об ошибках и указывают пользователю на ближайшую причину их
проблема. В системах с ограниченным / Proc реализация, Lsof(1) команда может заполнять
много пробелов.

В 2008 году поток запросов на перевод приходил к автору слишком часто. Это было
время пересмотреть эту идею 25-летней давности, и результат - libexplain.

С ПОМОЩЬЮ БИБЛИОТЕКА


Интерфейс библиотеки по возможности старается быть согласованным. Начнем с
пример использования Strerror(3):
если (переименовать (старый_путь, новый_путь) <0)
{
fprintf (stderr, "переименовать% s% s:% s \ n", old_path, new_path,
strerror (ошибка));
выход(1);
}
Идея libexplain - предоставить Strerror(3) эквивалент для каждый системный вызов,
специально адаптирован к этому системному вызову, так что он может предоставить более подробную информацию об ошибке
сообщение, содержащее большую часть информации, которую вы видите под заголовком «ОШИБКИ» раздела
2 и 3 человек страницы, дополненные информацией о реальных условиях, актуальной аргументации
значения и системные ограничения.

Ассоциация просто Кейсы
Ассоциация Strerror(3) замена:
если (переименовать (старый_путь, новый_путь) <0)
{
fprintf (stderr, "% s \ n", имя_объяснения (старый_путь, новый_путь));
выход(1);
}

Ассоциация Эррно Кейсы
Также можно передать явное ERRNO(3) ценность, если вы сначала должны сделать что-нибудь
обработка, которая нарушит ERRNO, например, восстановление после ошибок:
если (переименовать (старый_путь, новый_путь <0))
{
int old_errno = ошибка;
...код который беспокоит ERRNO...
fprintf (stderr, "% s \ n", объяснение_ошибка_rename (old_errno,
старый_путь, новый_путь));
выход(1);
}

Ассоциация Многопотоковый корпуса
Некоторые приложения являются многопоточными и поэтому не могут совместно использовать внутренние ресурсы libexplain.
буфер. Вы можете предоставить свой собственный буфер, используя
если (отвязать (путь))
{
символьное сообщение [3000];
объяснение_message_unlink (сообщение, размер(сообщение), путь);
error_dialog(сообщение);
возврат -1;
}
И для полноты оба ERRNO(3) и потокобезопасный:
ssize_t nbytes = чтение (fd, data, sizeof (данные));
если (nbytes <0)
{
символьное сообщение [3000];
int old_errno = ошибка;
...ошибка выздоровление...
объяснение_message_errno_read (сообщение, размер(сообщение),
old_errno, fd, data, sizeof (данные));
error_dialog(сообщение);
возврат -1;
}

Это замены для strerror_r(3) в системах, в которых он есть.

Интерфейс Сахар
Набор функций, добавленных в качестве удобных, чтобы побудить программистов использовать
Библиотека libexplain, оказались наиболее часто используемыми автором функциями libexplain в
программы командной строки:
int fd = объяснять_creat_or_die (имя_файла, 0666);
Эта функция пытается создать новый файл. Если не может, выводится сообщение об ошибке и
завершается с EXIT_FAILURE. Если ошибки нет, возвращается новый дескриптор файла.

Связанная функция:
int fd = объяснение_creat_on_error (имя_файла, 0666);
будет печатать сообщение об ошибке при сбое, но также возвращает исходный результат ошибки и
ERRNO(3) также не подвергается сомнению.

Все домен другие система звонки
Как правило, каждый системный вызов имеет свой собственный включаемый файл.
#включаютимя.h>
который определяет прототипы функций для шести функций:

· объяснять_имя,

· Объяснение_errno_имя,

· Объяснение_сообщение_имя,

· Объяснение_message_errno_имя,

· объяснять_имя_или_ди и

· объяснять_имя_при_ошибке.

У каждого прототипа функции есть документация Doxygen, и эта документация is не раздетый
при установке включаемых файлов.

Ассоциация ждать(2) системный вызов (и друзья) имеют несколько дополнительных вариантов, которые также интерпретируют сбой
быть статусом выхода, отличным от EXIT_SUCCESS. Это относится к система(3) и закрыть(3) как
Что ж.

Покрытие включает 221 системный вызов и 547 запросов ioctl. Есть еще много систем
звонки еще не реализованы. Системные вызовы, которые никогда не возвращаются, например выход(2), нет
в библиотеке и никогда не будет. В Exec семейство системных вызовов Он поддержали, потому что
они возвращаются при возникновении ошибки.

Кошка
Вот как могла бы выглядеть гипотетическая «кошачья» программа с полным отчетом об ошибках,
используя libexplain.
#включают
#включают
#включают
Есть одно включение для libexplain плюс обычные подозреваемые. (Если вы хотите уменьшить
загрузку препроцессора, вы можете использовать специфическиеимя.h> включает.)
статическая пустота
процесс (ФАЙЛ * fp)
{
для (;;)
{
char buffer [4096];
size_t n = объяснять_fread_or_die (буфер, 1, sizeof (буфер), fp);
если (! n)
перерыва;
объяснение_fwrite_or_die (буфер, 1, n, стандартный вывод);
}
}
Ассоциация процесс функция копирует файловый поток в стандартный вывод. В случае возникновения ошибки
для чтения или записи сообщается (и путь будет включен в
error), и команда завершается с EXIT_FAILURE. Мы даже не беспокоимся об отслеживании
пути или передать их в стек вызовов.
Int
основной (int argc, char ** argv)
{
для (;;)
{
int c = getopt (argc, argv, «о:»);
если (c == EOF)
перерыва;
переключатель (c)
{
case 'o':
объяснять_freopen_or_die (optarg, "w", stdout);
перерыва;
Самое интересное в этом коде то, что libexplain может сообщать об ошибках. включая домен пути даже
если вы не явно повторно откройте стандартный вывод, как это сделано здесь. Мы даже не беспокоимся о
отслеживание имени файла.
по умолчанию:
fprintf (stderr, "Использование:% ss [-o ] ... \ n ",
argv [0]);
вернуть EXIT_FAILURE;
}
}
если (optind == argc)
процесс (стандартный ввод);
еще
{
пока (optind <argc)
{
ФАЙЛ * fp = объяснять_fopen_or_die (argv [optind] ++, "r");
процесс (fp);
объяснять_fclose_or_die (fp);
}
}
Стандартный вывод будет закрыт неявно, но будет слишком поздно для вывода отчета об ошибке.
выдано, поэтому мы делаем это здесь, на случай, если буферизованный ввод-вывод еще ничего не написал, и
есть ошибка ENOSPC или что-то в этом роде.
объяснять_fflush_or_die (стандартный вывод);
вернуть EXIT_SUCCESS;
}
Это все. Полный отчет об ошибках, чистый код.

Расти Шкала of Интерфейс Доброта
Для тех из вас, кто не знаком с этим, «Как мне сделать так, чтобы это было трудно злоупотреблять?» Расти Рассела.
Страница обязательна к прочтению разработчиками API.
http://ozlabs.org/~rusty/index.cgi/tech/2008-03-30.html

10. Это что она в получить неправильно.

Цели нужно ставить высокие, амбициозно высокие, иначе вы их достигнете и не будете думать, что вы
закончено, когда вас нет.

Библиотека libexplain обнаруживает фиктивные указатели и многие другие фиктивные параметры системных вызовов,
и, как правило, пытается избежать сбоев в работе даже в самых тяжелых обстоятельствах.

Библиотека libexplain предназначена для обеспечения многопоточности. Более реальное использование, вероятно, будет
покажите места, где это можно улучшить.

Самая большая проблема заключается в самих именах функций. Поскольку C не имеет
пространства имен, библиотека libexplain всегда использует префикс имени объяснения. Это
традиционный способ создания псевдо-пространства имён во избежание конфликтов символов.
Однако это приводит к появлению некоторых неестественно звучащих имен.

9. Ассоциация компилятор or оставил не будет позволять являетесь получить it неправильно.

Распространенная ошибка - использовать объяснение_открыть там, где предназначалась объяснение_открыть_или_ди.
К счастью, на этом этапе компилятор часто выдает ошибку типа (например не могу назначить
const char * rvalue в int lvalue).

8. Ассоциация компилятор будете предупреждать if являетесь получить it неправильно.

Если имя_объяснения используется, когда было предназначено имя_объяснения_или_die, это может вызвать другие
проблемы. GCC имеет полезный атрибут функции warn_unused_result, а libexplain
библиотека прикрепляет его ко всему объяснению_имя вызовы функций для выдачи предупреждения, когда вы
совершите эту ошибку. Совместите это с GCC -Ошибка чтобы повысить уровень добродетели до 9.

7. Ассоциация Очевидный использование is (вероятно) домен исправить вариант.

Имена функций выбраны так, чтобы передать их значение, но это не всегда
успешный. Пока объясни_имя_или_ди и объясни_имя_on_error довольно информативны,
менее используемые поточно-безопасные варианты труднее декодировать. Прототипы функций помогают
компилятор к пониманию, а комментарии Doxygen в файлах заголовков помогают пользователю
к пониманию.

6. Ассоциация имя говорит являетесь КАК в использование его.

Особенно важно прочитать объяснение_имя_или_ди как «объясни (имя или умри)".
Использование последовательного префикса пространства имен объясняет_ имеет некоторые нежелательные побочные эффекты в
отдел очевидности.

Порядок слов в именах также указывает порядок аргументов. Аргумент
списки всегда конец с теми же аргументами, что и системный вызов; Найти of их. Если
_errno_ появляется в имени, его аргумент всегда предшествует аргументам системного вызова. Если
_message_ появляется в имени, два его аргумента всегда идут первыми.

5. Do it правую or it будете перерыв at время выполнения.

Библиотека libexplain обнаруживает фиктивные указатели и многие другие фиктивные параметры системных вызовов,
и, как правило, пытается избежать сбоев в работе даже в самых тяжелых обстоятельствах. Должно
никогда не ломается во время выполнения, но более широкое использование в реальном мире, несомненно, улучшит это.

Некоторые сообщения об ошибках нацелены на разработчиков и сопровождающих, а не на конечных пользователей, так как это
может помочь с разрешением ошибки. Не столько «перерыв во время работы», сколько «быть информативным на
время выполнения »(после системного вызова barfs).

4. Подписаться общий соглашение и Вы будете получить it правильно.

Поскольку C не имеет пространств имен, библиотека libexplain всегда использует имя_объяснения.
приставка. Это традиционный способ создания псевдо-пространства имён во избежание
конфликты символов.

Конечные аргументы всех вызовов libexplain идентичны системному вызову, который они
описывают. Это предназначено для обеспечения согласованного соглашения, общего с
системные вызовы сами.

3. Читать домен документации и Вы будете получить it правильно.

Библиотека libexplain стремится иметь полную документацию Doxygen для каждого
общедоступный вызов API (а также внутренний).

СООБЩЕНИЕ СОДЕРЖАНИЕ


Работа с libexplain немного похожа на взгляд на днище автомобиля, когда он включен.
подъемник у слесаря. Там есть какие-то уродливые вещи, плюс грязь и грязь, и
пользователи редко это видят. Хорошее сообщение об ошибке должно быть информативным даже для пользователя, который
был достаточно удачлив, что ему не приходилось очень часто смотреть на изнанку, а также
информативна для механика, выслушивающего описание пользователя по телефону. Это
задача не из легких.

Возвращаясь к нашему первому примеру, можно сказать, что код хотел бы, чтобы он использовал libexplain:
int fd = объяснять_open_or_die ("что-то / вещь", O_RDONLY, 0);
завершится ошибкой с таким сообщением об ошибке
open (pathname = "some / file", flags = O_RDONLY) не удалось, такого файла или каталога нет
(2, ENOENT), потому что в текущем каталоге нет "некоторого" каталога
Это разбивается на три части
системный вызов не смогли, системная ошибка , так как:
объяснение

Перед тем, как Так как
Можно увидеть часть сообщения перед «потому что» как слишком техническую, чтобы не‐
технических пользователей, в основном в результате точной печати самого системного вызова на
начало сообщения об ошибке. И похоже Трассирование(1) выход, для бонусных фанатов
пунктов.
open (pathname = "some / file", flags = O_RDONLY) не удалось, такого файла или каталога нет
(2, ЭНОЕНТ)
Эта часть сообщения об ошибке важна для разработчика, когда он пишет код.
и не менее важно для сопровождающего, который должен читать отчеты об ошибках и исправлять ошибки в
код. Он точно говорит о том, что не удалось.

Если этот текст не представлен пользователю, то пользователь не может скопировать и вставить его в
отчет об ошибке, и если его нет в отчете об ошибке, сопровождающий не может знать, что на самом деле пошло
неправильно.

Часто технический персонал будет использовать Трассирование(1) или ферма(1) чтобы получить эту точную информацию, но
этот путь не открыт при чтении отчетов об ошибках. Система репортера ошибок далека
прочь, и теперь уже в совершенно другом состоянии. Таким образом, эта информация должна быть в
отчет об ошибке, что означает, что он должен быть в сообщении об ошибке.

Представление системного вызова также дает контекст остальной части сообщения. Если нужно
возникает, вызывающий нарушение аргумент системного вызова может быть упомянут по имени в объяснении
после «потому что». Кроме того, все строки полностью заключены в кавычки и экранированы строками C, поэтому
встроенные символы новой строки и непечатаемые символы не заставят терминал пользователя уйти
непрочное.

Ассоциация системная ошибка это то, что выходит из Strerror(2) плюс символ ошибки. Нетерпеливый и
опытные системные администраторы могут перестать читать на этом этапе, но опыт автора на сегодняшний день
это дальнейшее чтение является полезным. (Если это не приносит пользы, вероятно, это область
libexplain, что можно улучшить. Разумеется, участие в коде приветствуется.)

После Так как
Это часть сообщения об ошибке, предназначенная для нетехнических пользователей. Это выходит за рамки
простые аргументы системного вызова и ищет что-то более конкретное.
в текущем каталоге нет "некоторого" каталога
В этой части делается попытка простым языком объяснить ближайшую причину ошибки.
здесь интернационализация имеет важное значение.

Как правило, политика заключается в том, чтобы включить как можно больше информации, чтобы пользователь
не нужно искать его (и не упускает его из отчета об ошибке).

Интернационализация
Большинство сообщений об ошибках в библиотеке libexplain переведены на международный уровень. Там
локализации пока нет, поэтому, если вам нужны объяснения на вашем родном языке,
пожалуйста, внесите свой вклад.

Квалификатор «большинство из», приведенный выше, относится к тому факту, что доказательство концепции
реализация не включала поддержку интернационализации. Кодовая база
постепенно пересматриваются, обычно в результате сообщений рефакторинга, так что каждая ошибка
строка сообщения появляется в коде ровно один раз.

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

посмертный
Бывают случаи, когда программа еще не использует libexplain, а вы не можете использовать Трассирование(1)
или. Существует объяснять(1) команда, включенная в libexplain, которую можно использовать для
расшифровать сообщения об ошибках, если состояние базовой системы не изменилось слишком сильно.
$ объяснять переименовать Foo / tmp / bar / baz -e ЭНОЕНТ
переименовать (oldpath = "foo", newpath = "/ tmp / bar / baz") не удалось, такого файла или каталога нет
(2, ENOENT), потому что в новом пути нет каталога "bar" "/ Tmp"каталог
$
Обратите внимание, как неоднозначность пути разрешается с помощью имени аргумента системного вызова. Из
конечно, вы должны знать ошибку и системный вызов для объяснять(1) быть полезным. Как
Помимо этого, это один из способов, используемых автоматическим набором тестов libexplain для проверки того, что
libexplain работает.

Философия
«Расскажи мне все, включая то, что я не знал, что искать».

Библиотека реализована таким образом, что при статической компоновке только код, который вы
на самом деле использование будет связано. Это достигается за счет наличия одной функции для каждого исходного файла,
когда это возможно.

Когда появится возможность предоставить дополнительную информацию, libexplain сделает это. Чем меньше пользователь
придется выследить для себя, тем лучше. Это означает, что UID сопровождаются
имя пользователя, GID сопровождаются именем группы, PID сопровождаются процессом
имя, дескрипторы файлов и потоки сопровождаются путем, и т.д.

При разрешении путей, если компонент пути не существует, libexplain будет искать похожие
имена, чтобы предложить альтернативы типографским ошибкам.

Библиотека libexplain пытается использовать как можно меньше кучи, а обычно ее нет. Это
чтобы избежать нарушения состояния процесса, насколько это возможно, хотя иногда это
неизбежно.

Библиотека libexplain пытается быть потокобезопасной, избегая глобальных переменных, сохраняя
заявить в стеке, насколько это возможно. Имеется единственный общий буфер сообщений, а
функции, которые его используют, задокументированы как небезопасные для потоков.

Библиотека libexplain не мешает обработчикам сигналов процесса. Это делает
определить, вызовет ли указатель segfault вызов, но не невозможный.

Когда информация доступна через системный вызов, а также через / Proc
запись, системный вызов является предпочтительным. Это сделано для того, чтобы не нарушить состояние процесса.
Также бывают случаи, когда дескрипторы файлов недоступны.

Библиотека libexplain скомпилирована с поддержкой больших файлов. Нет большого / маленького
шизофрения. Если это влияет на типы аргументов в API, будет выдана ошибка
если необходимый большой файл определения отсутствует.

FIXME: Требуется работа, чтобы убедиться, что квоты файловой системы обрабатываются в коде. Этот
относится к некоторым getrlimit(2) также границы.

Бывают случаи, когда родственные пути малоинформативны. Например: системные демоны,
серверы и фоновые процессы. В этих случаях в ошибке используются абсолютные пути.
объяснения.

PATH Постановление


Краткая версия: см. путь_разрешение(7).

Длинная версия: большинство пользователей никогда не слышали о путь_разрешение(7) и многие опытные пользователи
никогда не читал. Вот аннотированная версия:

Шаг 1: Start of домен разрешающая способность процесс
Если имя пути начинается с символа косой черты («/»), начальным каталогом поиска будет
корневой каталог вызывающего процесса.

Если имя пути не начинается с символа косой черты («/»), начальный поиск
каталог процесса разрешения - это текущий рабочий каталог процесса.

Шаг 2: Ходить вдоль домен путь
Установите текущий каталог поиска на начальный каталог поиска. Теперь для каждого не-
последний компонент имени пути, где компонент представляет собой подстроку, разделенную косой чертой («/»)
символов, этот компонент ищется в текущем справочнике.

Если у процесса нет разрешения на поиск в текущем каталоге поиска, EACCES
возвращается ошибка («В доступе отказано»).
open (pathname = "/home/archives/.ssh/private_key", flags = O_RDONLY) не удалось,
В разрешении отказано (13, EACCES), поскольку у процесса нет разрешения на поиск
в каталог с именем "/home/archives/.ssh", GID процесса 1000
"pmiller" не соответствует владельцу каталога 1001 "архивы", поэтому владелец
режим разрешений "rwx" игнорируется, остальные режимы разрешений - "---", а
процесс не является привилегированным (не имеет возможности DAC_READ_SEARCH)

Если компонент не найден, возвращается ошибка ENOENT («Нет такого файла или каталога»).
unlink (pathname = "/ home / microsoft / rubbish") не удалось, нет такого файла или каталога (2,
ENOENT), потому что нет «Microsoft» каталог в имени пути "/ Главная"каталог

Также существует некоторая поддержка пользователей, когда они неправильно вводят пути, делая предложения, когда
ENOENT возвращается:
open (pathname = "/user/include/fcntl.h", flags = O_RDONLY) не удалось, такого файла нет или
directory (2, ENOENT), потому что в пути "/" нет каталога "user"
каталог, вы имели в виду каталог "usr" вместо этого?

Если компонент найден, но не является ни каталогом, ни символической ссылкой, ENOTDIR
возвращается ошибка («Не каталог»).
open (pathname = "/home/pmiller/.netrc/lca", flags = O_RDONLY) не удалось, не
каталог (20, ENOTDIR), потому что обычный файл ".netrc" в пути
Каталог "/ home / pmiller" используется в качестве каталога, когда он не

Если компонент найден и является каталогом, мы устанавливаем текущий каталог поиска на этот
каталог и перейдите к следующему компоненту.

Если компонент найден и представляет собой символическую ссылку (символическая ссылка), мы сначала разрешаем эту символическую ссылку.
ссылка (с текущим справочным каталогом в качестве начального справочного каталога). В случае ошибки это
ошибка возвращается. Если результатом не является каталог, возвращается ошибка ENOTDIR.
unlink (pathname = "/ tmp / dangling / rubbish") не удалось, такого файла или каталога нет (2,
ENOENT), потому что "болтающаяся" символическая ссылка в имени пути "/ Tmp"каталог
относится к "нигде", которого не существует
Если разрешение символической ссылки успешно и возвращает каталог, мы устанавливаем текущий
найдите каталог в этот каталог и перейдите к следующему компоненту. Обратите внимание, что
процесс разрешения здесь включает в себя рекурсию. Чтобы защитить ядро ​​от стека
переполнение, а также для защиты от отказа в обслуживании есть ограничения на максимальное
глубина рекурсии и максимальное количество следующих символических ссылок. Ошибка ELOOP
возвращается при превышении максимума («Слишком много уровней символических ссылок»).
open (pathname = "/ tmp / dangling", flags = O_RDONLY) не удалось, слишком много уровней
символические ссылки (40, ELOOP), поскольку в
путь, начиная с "/ tmp / dangling"
Также возможно получить ошибку ELOOP или EMLINK, если символических ссылок слишком много, но нет
петля была обнаружена.
open (pathname = "/ tmp / rabbit-hole", flags = O_RDONLY) не удалось, слишком много уровней
символические ссылки (40, ELOOP), потому что в
путь (8)
Обратите внимание, как напечатан фактический предел.

Шаг 3: Найдите домен окончательный запись
Поиск последнего компонента имени пути происходит так же, как и поиск всех других
компоненты, как описано в предыдущем шаге, с двумя отличиями:

(i) Последний компонент не обязательно должен быть каталогом (по крайней мере, в том, что касается разрешения пути
процесс обеспокоен. Это может быть каталог или не каталог, потому что
требования конкретного системного вызова).

(II)
Если последний компонент не найден, это не обязательно ошибка; может мы просто
создавая это. Подробности обращения с заключительной записью описаны в
справочные страницы конкретных системных вызовов.

(III)
Также возможна проблема с последним компонентом, если это символическая ссылка.
и этого не следует придерживаться. Например, используя открытый(2) Флаг O_NOFOLLOW:
open (pathname = "a-symlink", flags = O_RDONLY | O_NOFOLLOW) не удалось, слишком много уровней
символические ссылки (ELOOP), поскольку был указан O_NOFOLLOW, но имя пути относится к
символическая ссылка

(IV)
Пользователи часто делают ошибки при вводе путевых имен. Библиотека libexplain
пытается внести предложения, когда возвращается ENOENT, например:
open (pathname = "/usr/include/filecontrl.h", flags = O_RDONLY) не удалось, такого файла нет или
каталог (2, ENOENT), потому что в пути нет обычного файла "filecontrl.h"
"/ usr / include", вы имели в виду обычный файл" fcntl.h "?

(v) Также возможно, что последний компонент должен быть чем-то иным, чем
обычный файл:
readlink (pathname = "just-a-file", data = 0x7F930A50, data_size = 4097) не удалось,
Неверный аргумент (22, EINVAL), поскольку путь - это обычный файл, а не символическая ссылка.

(V)
FIXME: обработка бита "t".

ограничения
Существует ряд ограничений в отношении имен путей и имен файлов.

Ограничение длины пути
Существует максимальная длина имен путей. Если путь (или какой-то промежуточный
путь, полученный при разрешении символьных ссылок) слишком длинный, ENAMETOOLONG
возвращается ошибка («Слишком длинное имя файла»). Обратите внимание, как включен системный лимит
в сообщении об ошибке.
open (pathname = "очень длинный", flags = O_RDONLY) не удалось, слишком длинное имя файла (36,
ENAMETOOLONG), поскольку имя пути превышает максимальную длину пути системы (4096)

Ограничение длины имени файла
Некоторые варианты Unix имеют ограничение на количество байтов в каждом компоненте пути.
Некоторые из них занимаются этим молча, а некоторые дают ENAMETOOLONG; libexplain
библиотека использует путьконф(3) _PC_NO_TRUNC, чтобы указать, какой. Если эта ошибка произойдет,
Библиотека libexplain укажет ограничение в сообщении об ошибке, ограничение
получен из путьконф(3) _PC_NAME_MAX. Обратите внимание, как включен системный лимит
в сообщении об ошибке.
open (pathname = "system7 / only-has-14-символов", flags = O_RDONLY) не удалось, файл
слишком длинное имя (36, ENAMETOOLONG), потому что компонент "only-has-14-characters"
дольше системного предела (14)

Пустой путь
В исходной Unix пустой путь относился к текущему каталогу.
В настоящее время POSIX постановляет, что пустой путь не может быть успешно разрешен.
open (pathname = "", flags = O_RDONLY) не удалось, нет такого файла или каталога (2,
ENOENT), потому что POSIX постановляет, что пустой путь не может быть разрешен
успешно

Разрешения...
Биты прав доступа файла состоят из трех групп по три бита. Первая группа
три используется, когда эффективный идентификатор пользователя вызывающего процесса равен идентификатору владельца
файл. Вторая группа из трех используется, когда идентификатор группы файла либо равен
эффективный идентификатор группы вызывающего процесса или один из дополнительных идентификаторов группы
вызывающий процесс. Когда ни один из них не выполняется, используется третья группа.
open (pathname = "/ И т.д. / пароль", flags = O_WRONLY) не удалось, в доступе отказано (13,
EACCES), потому что у процесса нет разрешения на запись в обычный "passwd"
файл в пути "/ и т.д."каталог, эффективный UID процесса 1000" pmiller "
не соответствует обычному владельцу файла 0 "root", поэтому режим разрешения владельца "rw-"
игнорируется, остальные режимы разрешений - "r--", и процесс не является привилегированным.
(не имеет возможности DAC_OVERRIDE)
Этому объяснению отведено довольно много места, поскольку большинство пользователей не знают, что это
как работает система разрешений. В частности: собственник, группа и др.
разрешения являются исключительными, они не объединяются «ИЛИ».

СТРАННЫЙ И ИНТЕРЕСНО СИСТЕМА ВЫЗОВЫ


Процесс написания определенного обработчика ошибок для каждого системного вызова часто обнаруживает
интересные причуды и граничные условия, или непонятные ERRNO(3) значения.

ЭНОМЕДИУМ, Нет средний найденный
Акт копирования компакт-диска был источником названия для этой статьи.
$ dd если = / dev / cdrom of = fubar.iso
dd: открытие «/ dev / cdrom»: носитель не найден
$
Автор задавался вопросом, почему его компьютер говорит ему, что экстрасенса не существует.
Средняя. Не говоря уже о том, что огромное количество носителей английского языка не
даже зная, что «media» - это множественное число, не говоря уже о том, что «media» - это единственное число, строка
вернулся Strerror(3) для ЭНОМЕДИУМА настолько краток, что почти полностью не содержит
содержание.

После появления открытый(2) возвращает ENOMEDIUM, было бы неплохо, если бы библиотека libexplain могла расширять
немного об этом, исходя из типа привода. Например:
... потому что в дисководе нет диска
... потому что в приводе компакт-дисков нет диска
... потому что в ленточном накопителе нет ленты
... потому что в картридере нет карты памяти

Так и случилось ...
open (pathname = "/ dev / cdrom", flags = O_RDONLY) не удалось, носитель не найден (123,
ENOMEDIUM), поскольку в дисководе компакт-дисков нет диска.
Уловка, о которой ранее не подозревал автор, заключалась в том, чтобы открыть устройство с помощью
Флаг O_NONBLOCK, который позволит вам открыть диск без носителя. Ты тогда
проблема конкретного устройства IOCTL(2) запросы, пока вы не разберетесь, что это за хрень. (Нет
конечно, если это POSIX, но похоже, что он работает таким же образом в BSD и Solaris, согласно
домен водим(1) источники.)

Также обратите внимание на различное использование понятий «диск» и «диск» в контексте. Стандарт CD возник
во Франции, но все остальное имеет букву «k».

ОШИБКА, Плохой адрес
Любой системный вызов, который принимает аргумент указателя, может вернуть EFAULT. Библиотека libexplain
может выяснить, какой аргумент ошибочен, и делает это, не нарушая процесса
(или поток) обработка сигналов.

Когда доступно, минкор(2) используется системный вызов, чтобы узнать, действительна ли область памяти.
Он может возвращать три результата: сопоставленный, но не в физической памяти, сопоставленный и физический.
память, а не отображается. При проверке правильности указателя первые два - «да».
и последнее - «нет».

Проверить строки C сложнее, потому что вместо указателя и размера мы
есть указатель. Чтобы определить размер, нам нужно было бы найти NUL, и это могло бы
segfault, уловка ‐ 22.

Чтобы обойти это, библиотека libexplain использует lstat(2) вызов sysem (с известным
хороший второй аргумент), чтобы проверить строки C на достоверность. Возврат ошибки && errno == EFAULT
это «нет», а все остальное - «да». Это, конечно, ограничивает строки до PATH_MAX
символов, но обычно это не проблема для библиотеки libexplain, потому что это
почти всегда самые длинные струны, о которых он заботится.

ЭМФИЛЬ, Слишком многих открытый файлов
Эта ошибка возникает, когда у процесса уже открыто максимальное количество файловых дескрипторов.
Если фактический предел должен быть напечатан, а библиотека libexplain пытается это сделать, вы не можете открыть
файл в / Proc прочитать, что это такое.
open_max = sysconf (_SC_OPEN_MAX);
Это не так уж и сложно, есть системная конфигурация(3) способ получения предела.

АНФИЛЬ, Слишком многих открытый файлов in система
Эта ошибка возникает, когда установлен системный предел на общее количество открытых файлов.
достиг. В этом случае нет под рукой системная конфигурация(3) способ получения предела.

Копнув глубже, можно обнаружить, что в Linux есть / Proc запись, которую мы могли прочитать
получить это значение. Уловка-22: у нас закончились файловые дескрипторы, поэтому мы не можем открыть файл для
читай предел.

В Linux для его получения используется системный вызов, но у него нет функции-оболочки [e] glibc, поэтому
вы должны все это очень внимательно:
длинной
объяснять_maxfile (недействительно)
{
#ifdef __linux__
структура __sysctl_args аргументы;
int32_t максимальный файл;
size_t maxfile_size = размер(максфайл);
int name [] = {CTL_FS, FS_MAXFILE};
memset (& args, 0, sizeof (struct __sysctl_args));
args.name = имя;
аргументы.nlen = 2;
args.oldval = & maxfile;
args.oldlenp = & maxfile_size;
если (системный вызов (SYS__sysctl, & args)> = 0)
вернуть maxfile;
#endif
возврат -1;
}
Это позволяет включить ограничение в сообщение об ошибке, если оно доступно.

ЭИНВАЛ "Неверный аргумент » vs ЭНОСИС «Функция не реализовано »
Неподдерживаемые действия (например, символическая(2) в файловой системе FAT) не сообщаются
последовательно от одного системного вызова к другому. Возможна установка EINVAL или
ENOSYS вернулся.

В результате необходимо уделять внимание этим случаям ошибок, чтобы исправить их, особенно
поскольку EINVAL также может относиться к проблемам с одним или несколькими аргументами системного вызова.

Внимание который ERRNO(3) is не всегда набор
Бывают случаи, когда необходимо прочитать исходники [e] glibc, чтобы определить, как и
когда для некоторых системных вызовов возвращаются ошибки.

Feof(3) файлно(3)
Часто предполагается, что эти функции не могут возвращать ошибку. Это верно, только если
домен поток аргумент действителен, однако они способны обнаружить недопустимый
указатель.

fpathconf(3) путьконф(3)
Возвращаемое значение fpathconf(2) и путьконф(2) на законных основаниях может быть -1, так что это
необходимо увидеть, если ERRNO(3) задано явно.

IOCTL(2)
Возвращаемое значение IOCTL(2) на законных основаниях может быть -1, поэтому необходимо проверить, не
ERRNO(3) задано явно.

Readdir(3)
Возвращаемое значение Readdir(3) имеет значение NULL как для ошибок, так и для конца файла. это
необходимо увидеть, если ERRNO(3) задано явно.

Setbuf(3) установочный буфер(3) Setlinebuf(3) setvbuf(3)
Все эти функции, кроме последней, возвращают значение void. А также setvbuf(3) задокументировано только как
возврат «ненулевого» при ошибке. Надо посмотреть, если ERRNO(3) был явно
комплект.

стртод(3) стртол(3) стртольд(3) Strtoll(3) Стртул(3) Strtoull(3)
Эти функции возвращают 0 в случае ошибки, но это также допустимое возвращаемое значение. это
необходимо увидеть, если ERRNO(3) задано явно.

Ungetc(3)
Хотя стандартом ANSI C требуется резервное копирование только одного символа, он оказывается
из того, что [e] glibc допускает больше ... но это означает, что он может потерпеть неудачу с ENOMEM. Оно может
также не сработает с EBADF, если fp подделка. Сложнее всего, если вы пропустите EOF с ошибкой
происходит возврат, но номер ошибки не устанавливается.

Библиотека libexplain правильно обнаруживает все эти ошибки даже в тех случаях, когда
значения ошибок плохо документированы, если вообще задокументированы.

ЭНОПК, Нет космосе оставил on устройство
Когда эта ошибка относится к файлу в файловой системе, библиотека libexplain печатает монтирование
точка файловой системы с проблемой. Это может сильно усложнить причину ошибки.
яснее.
запись (fildes = 1 "example", data = 0xbfff2340, data_size = 5) не удалась, места не осталось
на устройстве (28, ENOSPC), поскольку файловая система, содержащая fildes ("/ Главная") не имеет
больше места для данных
По мере добавления дополнительной поддержки специальных устройств ожидается, что сообщения об ошибках будут включать устройство
название и фактический размер устройства.

ЭРОФС, Только чтение файл система
Когда эта ошибка относится к файлу в файловой системе, библиотека libexplain печатает монтирование
точка файловой системы с проблемой. Это может сильно усложнить причину ошибки.
яснее.

По мере добавления дополнительной поддержки специальных устройств ожидается, что сообщения об ошибках будут включать устройство
имя и тип.
open (pathname = "/ dev / fd0", O_RDWR, 0666) не удалось, файловая система только для чтения (30, EROFS)
поскольку на дискете установлен язычок защиты от записи

... потому что CD-ROM не записывается
... поскольку на карте памяти установлен язычок защиты от записи
... потому что магнитная лента ½ дюйма не имеет пишущего кольца

переименовать
Ассоциация переименовать(2) системный вызов используется для изменения местоположения или имени файла, его перемещения
между каталогами, если требуется. Если целевой путь уже существует, он будет
атомарно заменены, так что нет точки, в которой другой процесс пытается
доступ он обнаружит, что он отсутствует.

Однако есть ограничения: вы можете переименовать каталог только поверх другого.
каталог, если целевой каталог не пуст.
переименовать (oldpath = "foo", newpath = "bar") не удалось, каталог не пустой (39,
ENOTEMPTY), потому что newpath не является пустым каталогом; то есть он содержит записи
Кроме как "." а также ".."
Вы также не можете переименовать каталог поверх каталога, не являющегося каталогом.
переименовать (oldpath = "foo", newpath = "bar") не удалось, это не каталог (20, ENOTDIR)
потому что oldpath - это каталог, а newpath - это обычный файл, а не каталог
И обратное не допускается
переименовать (oldpath = "foo", newpath = "bar") не удалось, это каталог (21, EISDIR)
потому что newpath - это каталог, а oldpath - это обычный файл, а не каталог

Это, конечно, усложняет работу библиотеки libexplain, потому что
разъединить(2) или RmDir(2) системный вызов неявно вызывается переименовать(2), так что все
разъединить(2) или RmDir(2) ошибки также должны быть обнаружены и обработаны.

дубликат2
Ассоциация дубликат2(2) системный вызов используется для создания второго файлового дескриптора, который ссылается на
тот же объект, что и первый дескриптор файла. Обычно это используется для реализации ввода оболочки
и перенаправление вывода.

Самое интересное в том, что, как и переименовать(2) может атомарно переименовать файл поверх
существующий файл и удалите старый файл, дубликат2(2) может сделать это с уже открытым файлом
Дескриптор.

Еще раз, это усложняет работу библиотеки libexplain, потому что Закрыть(2)
системный вызов неявно вызывается дубликат2(2), и поэтому все Закрыть(2) ошибки должны быть
также обнаружены и обработаны.

ПРИКЛЮЧЕНИЯ IN ИОКТЛ ПОДДЕРЖКИ


Ассоциация IOCTL(2) системный вызов предоставляет авторам драйверов устройств способ связи с
пользовательское пространство, которое не вписывается в существующий API ядра. Видеть ioctl_list(2).

Декодирование Запрос Номера
Бегло взглянув на IOCTL(2) интерфейс, по-видимому, будет большой, но конечный
количество возможных IOCTL(2) запросы. Каждый разный IOCTL(2) запрос эффективно
другой системный вызов, но без какой-либо безопасности типов - компилятор не может помочь
программист понял это правильно. Вероятно, это была мотивация tcflush(3) и
друзья.

Первое впечатление, что вы можете расшифровать IOCTL(2) запросы с использованием огромного коммутатора
утверждение. Это оказывается невозможным, потому что очень быстро обнаруживается, что это
невозможно включить все необходимые системные заголовки, определяющие различные IOCTL(2)
просьбы, потому что им сложно играть друг с другом в приятной игре.

Более глубокий взгляд показывает, что существует ряд «частных» номеров запросов и устройство
авторам драйверов рекомендуется их использовать. Это означает, что существует гораздо больший возможный
набор запросов с неоднозначными номерами запросов, которые сразу бросаются в глаза. Также,
есть и некоторые исторические неясности.

Мы уже знали, что переключение непрактично, но теперь мы знаем, что для выбора
соответствующее имя запроса и объяснение, мы должны учитывать не только номер запроса, но и
также файловый дескриптор.

Реализация IOCTL(2) поддержка в библиотеке libexplain должна иметь таблицу
указатели на IOCTL(2) дескрипторы запросов. Каждый из этих дескрипторов включает необязательный
указатель на функцию разрешения неоднозначности.

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

Представление
Философия библиотеки libexplain - предоставлять столько информации, сколько
возможно, включая точное представление системного вызова. На случай, если
IOCTL(2) это означает печать правильного номера запроса (по имени), а также правильного (или
по крайней мере, полезное) представление третьего аргумента.

Ассоциация IOCTL(2) прототип выглядит так:
int ioctl (int fildes, int запрос, ...);
при котором должны срабатывать ваши аварийные сигналы безопасности типа. Внутри [e] glibc, это превращено
в различные формы:
int __ioctl (int fildes, int запрос, длинный аргумент);
int __ioctl (int fildes, int request, void * arg);
а интерфейс системных вызовов ядра Linux ожидает
asmlinkage long sys_ioctl (unsigned int fildes, беззнаковый запрос int, unsigned long
аргумент);
Крайняя изменчивость третьего аргумента становится проблемой, когда библиотека libexplain
пытается напечатать представление этого третьего аргумента. Однако, как только номер запроса
устранена неоднозначность, каждая запись в таблице ioctl библиотеки libexplain имеет
пользовательская функция print_data (ОО выполняется вручную).

Пояснения
Меньше проблем с определением используемого объяснения. После того, как номер запроса
устранена неоднозначность, каждая запись в таблице ioctl библиотеки libexplain имеет собственный
print_explanation (опять же, ОО выполняется вручную).

В отличие от системных вызовов разделов 2 и 3, большинство IOCTL(2) запросы без ошибок
задокументировано. Это означает, что для правильного описания ошибок необходимо прочитать ядро
источники для открытия

· какие ERRNO(3) значения могут быть возвращены, и

· Причина каждой ошибки.

Из-за объектно-ориентированного характера диспетчеризации вызовов функций внутри ядра вам необходимо прочитать
Найти источники, реализующие это IOCTL(2) запрос, а не только общая реализация. Это
следует ожидать, что разные ядра будут иметь разные номера ошибок и тонко
разные причины ошибок.

ЭИНВАЛ vs ЕНОТТИ
Ситуация еще хуже для IOCTL(2) запросы, чем для системных вызовов, с EINVAL и
ENOTTY оба используются, чтобы указать, что IOCTL(2) запрос неуместен в том смысле, что
контекст, а иногда и ENOSYS, ENOTSUP и EOPNOTSUPP (предназначенные для использования для сокетов) как
хорошо. В исходных текстах ядра Linux есть комментарии, которые, кажется, указывают на прогрессивный
выполняется очистка. Для дополнительного хаоса BSD добавляет к путанице ENOIOCTL.

В результате необходимо уделять внимание этим случаям ошибок, чтобы исправить их, особенно
поскольку EINVAL также может относиться к проблемам с одним или несколькими аргументами системного вызова.

intptr_t
Стандарт C99 определяет целочисленный тип, который гарантированно может содержать любой указатель.
без потери представительства.

Приведенный выше прототип функции syscall было бы лучше написать
long sys_ioctl (unsigned int fildes, беззнаковый запрос int, intptr_t arg);
Проблема заключается в когнитивном диссонансе, вызванном особенностями устройства или файловой системы.
IOCTL(2) реализации, такие как:
long vfs_ioctl (struct file * filp, unsigned int cmd, unsigned long arg);
На betXNUMX есть большой выбор IOCTL(2) запросы фактически имеют третий аргумент int * arg. Но имея это
объявленный long приводит к тому, что код трактует это как long * arg. Это безвредно для 32-битных
(sizeof (long) == sizeof (int)), но неприятно на 64-битных (sizeof (long)! = sizeof (int)).
В зависимости от порядка байтов вы получаете или не получаете ожидаемое значение, но вы всегда получить
каракули из памяти или стопки каракулей.

Записывая все это как
int ioctl (int fildes, int запрос, ...);
int __ioctl (int fildes, int запрос, intptr_t arg);
long sys_ioctl (unsigned int fildes, беззнаковый запрос int, intptr_t arg);
long vfs_ioctl (struct file * filp, unsigned int cmd, intptr_t arg);
подчеркивает, что целое число - это только целое число, чтобы представить количество, которое почти
всегда несвязанный тип указателя.

Заключение


Используйте libexplain, вашим пользователям это понравится.

АВТОРСКИЕ ПРАВА


libexplain версии 1.4
Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Питер Миллер

Используйте объяснение_lca2010 в Интернете с помощью сервисов onworks.net


Бесплатные серверы и рабочие станции

Скачать приложения для Windows и Linux

  • 1
    Сковорода
    Сковорода
    SWIG - это инструмент для разработки программного обеспечения
    который соединяет программы, написанные на C, и
    C ++ с множеством высокоуровневых
    языки программирования. SWIG используется с
    разные...
    Скачать SWIG
  • 2
    Тема WooCommerce Nextjs React
    Тема WooCommerce Nextjs React
    Тема React WooCommerce, созданная с помощью
    Далее JS, Webpack, Babel, Node и
    Экспресс, используя GraphQL и Apollo
    Клиент. Магазин WooCommerce в React (
    содержит: продукты...
    Скачать тему WooCommerce Nextjs React
  • 3
    Archlabs_repo
    Archlabs_repo
    Репозиторий пакетов для ArchLabs Это
    приложение, которое также можно получить
    от
    https://sourceforge.net/projects/archlabs-repo/.
    Он был размещен на OnWorks в...
    Скачать archlabs_repo
  • 4
    Зефир Проект
    Зефир Проект
    Проект Zephyr - новое поколение
    операционная система реального времени (RTOS), которая
    поддерживает несколько аппаратных средств
    архитектуры. Он основан на
    компактное ядро ​​...
    Скачать проект Зефир
  • 5
    SCons
    SCons
    SCons - инструмент для создания программного обеспечения
    это лучшая альтернатива
    классический инструмент сборки "Make",
    мы все знаем и любим. SCons - это
    реализовал ...
    Скачать SCons
  • 6
    PSInt
    PSInt
    PSeInt - интерпретатор псевдокода для
    испаноязычные студенты-программисты.
    Его основная цель - быть инструментом для
    изучение и понимание основных
    концепция ...
    Скачать PSInt
  • Больше »

Команды Linux

  • 1
    7z
    7z
    7z - файловый архиватор с самым высоким
    степень сжатия ...
    Беги 7z
  • 2
    7za
    7za
    7za - файловый архиватор с самым высоким
    степень сжатия ...
    Беги 7за
  • 3
    пресмыкающийся
    пресмыкающийся
    ЖУТКО - Информация о геолокации
    ОПИСАНИЕ агрегатора: Creepy — это
    приложение, позволяющее собирать
    информация, связанная с геолокацией, о
    пользователи из...
    Беги жутко
  • 4
    сборник сверчков
    сборник сверчков
    крикет — программа для управления
    сбор и отображение временных рядов
    данные ...
    Запустите команду cricket-compile
  • 5
    g-wrap-config
    g-wrap-config
    g-wrap-config - скрипт для получения
    информация об установленной версии
    G-Wrap ...
    Запустите g-wrap-config
  • 6
    г.accessgrass
    г.accessgrass
    g.access — контролирует доступ к
    текущий набор карт для других пользователей на
    система. Если опция не указана, печатает
    Текущее состояние. КЛЮЧЕВЫЕ СЛОВА: общее, карта.
    руководство, п...
    Запустите g.accessgrass
  • Больше »

Ad