Как преобразовать errno в UNIX в соответствующую строку?

Как преобразовать errno в UNIX в соответствующую строку?

10.10.2009 06:38:50 Просмотров 17 Источник

Есть ли в UNIX функция для преобразования errno в соответствующую строку, например, EIDRM в "EIDRM". Его очень раздражает отладка, чтобы проверить наличие ошибок с этими целочисленными errno.

У вопроса есть решение - Посмотреть?

Ответы - Как преобразовать errno в UNIX в соответствующую строку? / How to convert errno in UNIX to corresponding string?

Является ответом!
atk

10.10.2009 06:45:55

strerror()должен это сделать. http://linux.die.net/man/3/strerror

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

https://stackoverflow.com/questions/1546882/how-to-convert-errno-in-unix-to-corresponding-string/1546889#comment1404021_1546889
strerror на самом деле превратит их в гораздо более полезные строки, чем просто "EIDRM", как просил ОП, но это ответ, который я бы тоже дал.
https://stackoverflow.com/questions/1546882/how-to-convert-errno-in-unix-to-corresponding-string/1546889#comment57031402_1546889
эти строки на самом деле не очень полезны, потому что man-страницы для системных вызовов часто определяют поведение ошибок в терминах кода перечисления. Строка-это в лучшем случае намек.
https://stackoverflow.com/questions/1546882/how-to-convert-errno-in-unix-to-corresponding-string/1546889#comment58962310_1546889
Опасность, Уилл Робинсон! strerror()локализованы, как я обнаружил, когда проверял строку ошибки на "нет такого файла или каталога", но платформа моего пользователя возвращала" Arquivo ou diretório não encontrado " вместо этого. (Это было на языке, где само значение errno не было открыто.)
https://stackoverflow.com/questions/1546882/how-to-convert-errno-in-unix-to-corresponding-string/1546889#comment101371620_1546889
@orm Да, эти строки очень полезны для начинающих пользователей в обычных случаях, но за пределами определенного момента эти подсказки могут быть бесполезными или даже вводящими в заблуждение.
Andrey Vlasovskikh

10.10.2009 06:50:23

Я не уверен в таких enumили perror(3)C, которые возвращают читаемое человеком представление кода ошибки. Пожалуйста, обратитесь к справочным страницам для получения более подробной информации.

https://stackoverflow.com/questions/1546882/how-to-convert-errno-in-unix-to-corresponding-string/1546893#comment1404030_1546893
Я думал, что perror () просто печатает в STDERR, а не преобразует число в значение. Может быть, я неправильно запомнил (и неправильно прочитал главную страницу)?
https://stackoverflow.com/questions/1546882/how-to-convert-errno-in-unix-to-corresponding-string/1546893#comment1404035_1546893
Да, perror-это средство отладки для errno.
Andrey Vlasovskikh

10.10.2009 06:58:15

Просто еще одно решение, которое решает именно ту проблему, которая у вас есть, но в Python вместо C:

>>> import errno
>>> errno.errorcode[errno.EIDRM]
'EIDRM'
https://stackoverflow.com/questions/1546882/how-to-convert-errno-in-unix-to-corresponding-string/1546901#comment101371743_1546901
Это хороший ответ, но стоит знать, что Python включает только подмножество всех возможных значений errno, поэтому в некоторых системах он не будет иметь записей для всех из них. В типичных случаях это не проблема, но если вы используете это как общий способ поиска кодов ошибок, вы можете столкнуться с этим.
ayrnieu

10.10.2009 07:00:36

Если вы действительно хотите EIDRM, а не его строку ошибки: нет. Однако, на OpenBSD,

man errno|egrep ' [0-9]+ E[A-Z]+'|sed 's/^ *//'|cut -d' ' -f1,2

распечатывает красивую таблицу "...eidm \ n...- то, что вы можете преобразовать дальше в структуру данных для языка программирования, в котором вы хотели бы иметь эту функцию.

Stephen Niedzielski

25.12.2012 05:10:16

Теперь есть утилита errno, распространяемая с пакетом moreutils.

mtraceur

11.08.2019 10:01:09

В UNIX нет стандартной функции для этого.

Но недавно я написал errnonameфункцию errnoname, которая делает именно это.

errnoname(также strerror, strerror_r, strerror_l) печатают" дружественную человеку " подсказку о том, что ошибка была, но их выходы

  • обычно без документов,
  • не нормируется,
  • не гарантируется соблюдение каких-либо ограничений по длине или формату,
  • часто отличается в зависимости от настроек локали, и
  • не всегда имеют смысл во всех ситуациях (например , они имеют тенденцию печатать perrorдля File exists, хотя эта ошибка часто возвращается для вещей, которые не являются файлами ).

Это означает, что они внешне удобны для пользователя, но

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

По иронии судьбы, ничто не мешает этим функциям просто использовать EEXISTлокаль C. Но ни один libc, о котором я знаю, не делает этого.

В любом случае, поскольку мое errnoвыпущено под "лицензией BSD с нулевым предложением" (0BSD), которая является разрешительной лицензией, или, точнее, лицензией, эквивалентной публичному домену, вы можете делать с ней все, что захотите.

Чтобы сделать этот ответ самостоятельным, в то же время вписываясь в пределы символов ответа, ниже приведены два сокращенных варианта функции errnoname.

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

Пара заметок:

  1. Это охватывает все или большинство errnoname, имя которого ему неизвестно.

Вариант 1: Простой, Универсальный

Этот очень портативный и простой, без каких-либо крайних случаев, чтобы беспокоиться. Он будет компилироваться практически с любым компилятором C89 или лучше, который вы можете бросить на него. (Возможно, даже компиляторы C++, что становится все более редким по мере того, как языки расходятся.)

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

errnoname

Вариант 2: Явно Эффективный, Подходит Для Большинства Систем

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

Он безопасен для использования до тех пор, пока система имеет положительные, относительно небольшие и разумно непрерывные errnoname

https://stackoverflow.com/questions/1546882/how-to-convert-errno-in-unix-to-corresponding-string/57447983#comment105215216_57447983
Хорошая идея иметь функцию errnoname (), но очень плохо, что она использует switch-case. Для обработки ошибок это может быть хорошо, но для других целей, таких как трассировка, это неоправданно неоптимально. Вы должны были создать большой массив, используя коды errno в качестве индексов. Я имею в виду, используя синтаксис { ..., [индекс] = значение, ... }. Конечно, там тоже могут быть дыры.
https://stackoverflow.com/questions/1546882/how-to-convert-errno-in-unix-to-corresponding-string/57447983#comment105229851_57447983
@vvaltchev теперь я добавил реализацию на основе массива в качестве опции (активируемой определением ERRNONAME_SAFE_TO_USE_ARRAYпри компиляции) в errnoname . (Документально подтверждено в разделе Оптимизация .) Спасибо, что заговорили об этом. Я ожидал услышать, Есть ли спрос на подход, основанный на массиве, прежде чем пересмотреть, как я хотел бы его решить.
https://stackoverflow.com/questions/1546882/how-to-convert-errno-in-unix-to-corresponding-string/57447983#comment105238532_57447983
Хорошая работа, мужик! Ваш проект заработал свою первую звезду GitHub: -) я реализовал пользовательское решение для своего случая (мне нужны были только коды Linux errno), но все равно приятно знать, что вы добавили эту функцию. В любом случае, да, я понимаю озабоченность тем, что теоретически могут существовать большие коды errno в какой-то системе, но на практике во всех системах UNIX, которые я когда-либо видел в своей жизни, они являются просто почти последовательными числами, обычно менее нескольких сотен в общей сложности. @mtraceur
https://stackoverflow.com/questions/1546882/how-to-convert-errno-in-unix-to-corresponding-string/57447983#comment105762244_57447983
@vvaltchev о дальнейшем тестировании: у меня есть gcc 4.8.5 (выпущенный пять лет назад), и ему удается автоматически оптимизировать версию коммутатора в поиск массива с -O2, -O3или-Os. (Это на ARMv7 с Linux на устройства, где errno являются строго последовательными. Затем он уморительно не сумел объединить пару sub r0, r0, #1и cmp r0, #132в одну cmp r0, #133, но в остальном основанный на коммутаторе и массиве код C генерирует идентичный машинный код.)
https://stackoverflow.com/questions/1546882/how-to-convert-errno-in-unix-to-corresponding-string/57447983#comment105762631_57447983
Я думаю, что одно отличие инструкции состоит в том, что она решила сделать массив 132 элементов, где 0-й индекс является 1-м errno, вместо ручной версии массива, где 1-й индекс является 1-м errno. В частности, вручную добавив в case 0: return 0 не изменить результат - так что я думаю, оптимизатор делает свое решение на абстрактном виде логики, которая уже признала, что ноль-так же, как и любой другой в ауте случае, и исключает его из эвристически заметив, что один дополнительный массив, запись, вероятно, более эффективны, чем всегда-инструкции.
https://stackoverflow.com/questions/1546882/how-to-convert-errno-in-unix-to-corresponding-string/57447983#comment105763226_57447983
Современный clang 9.0.1 для AArch64 Linux демонстрирует такое же поведение-идентичный код, но для выбора массива, начинающегося с первого errno и, следовательно, нуждающегося sub, затем cmpвместо просто cmp.
https://stackoverflow.com/questions/1546882/how-to-convert-errno-in-unix-to-corresponding-string/57447983#comment105763346_57447983
Я мог бы поклясться, что тестировал с включенными более высокими оптимизациями и не видел, как переключатели превращаются в массивы поиска. Но, по-видимому, я, должно быть, напортачил и тестировал только с оптимизациями "выключенными" (все, что ниже-O2, в основном умышленно делает наш код неэффективным и непригодным для рассуждений о том, как оптимизировать на уровне исходного кода, но, по-видимому, я ошибся и сделал именно это). Я думаю, что, возможно, я предположил, что критика @vvaltchev пришла из-за того, что уже попробовал-O2или лучше, но в любом случае это моя вина, что я пропустил это раньше.
https://stackoverflow.com/questions/1546882/how-to-convert-errno-in-unix-to-corresponding-string/57447983#comment105763500_57447983
Я должен признать - если бы я знал наверняка, что -O2или лучше даже пять лет назад уже превращал подобные операторы switch в поисковые запросы массива, я, возможно, просто оставил бы его как простой оператор switch, а не реализовал второй вариант на основе массива. Тем не менее, явный вариант на основе массива хорошо иметь в качестве опции для крайних случаев, когда такие оптимизации компилятора недоступны или не срабатывают (например, если есть разрыв в значениях errno, или слишком много пробелов, или слишком большой разрыв, но человеческое суждение все же показывает, что лучше сделать поиск массива.)
https://stackoverflow.com/questions/1546882/how-to-convert-errno-in-unix-to-corresponding-string/57447983#comment105764266_57447983
@vvaltchev-о, в ответ на ваш оригинальный ответ, Спасибо! Я был рад видеть ваш ответ. Да, реализовать свой собственный, вероятно, лучше и проще, когда вы знаете, что поддерживаете только определенный хорошо известный фиксированный набор систем или errnoзначения errno будут малыми и непрерывными в типичных системах для типичных применений. Другие недостатки варианта, основанного на массиве, включают, например, то, что он, скорее всего, будет слегка ошибочным из-за человеческой ошибки и потребует более тщательного обдумывания, чтобы проверить правильность, хотя я сделал это правильно, насколько я могу судить.)
Закрыть X