Как установить errno в драйвере устройства Linux?

Я разрабатываю драйвер символьного устройства Linux. Я хочу установить errno при возникновении ошибки в системном вызове ioctl().

long my_own_ioctl(struct file *file, unsigned int req, unsigned long arg)
{
    long ret = 0;
    BOOL isErr = FALSE;

    // some operation
    // ...

    if (isErr) {
        // set errno
        // ...                 <--- What should I do?
        ret = -1;
    }

    return ret;
}

Что я должен сделать, чтобы достичь этого? Заранее спасибо!


Пожалуйста, позвольте мне объяснить мое заявление более подробно.

Мое устройство находится в /dev/myCharDev. Мое приложение пользовательского пространства выглядит так:

#define _COMMAND                    (1)
#define _ERROR_COMMAND_PARAMETER    (-1)

int main()
{
    int fd = open("/dev/myCharDec", O_RDONLY);
    int errnoCopy;

    if (fd) {
        if (ioctl(fd, _COMMAND, _ERROR_COMMAND_PARAMETER) < 0) {      // should cause error in ioctl()
            errnoCopy = errno;
            printf("Oops, error occurred: %s\n", strerr(errnoCopy));  // I want this "errno" printed correctly
        }

        close(fd);
    }

    return 0;
}

Как я упоминал в комментариях выше, как мне установить «errno» в моих собственных кодах драйверов устройств и сделать их доступными для чтения приложениям пользовательского пространства?


person Andrew Chang    schedule 04.07.2014    source источник


Ответы (3)


Хороший вопрос!

Хорошо, вы можете думать об errno как о глобальной переменной (честно говоря, это extern int). errno имеет множество предопределенных макросов для кодов ошибок в библиотеке errno.h. Вы можете посмотреть здесь. Весьма вероятно, что некоторые из этих кодов ошибок описывают то, что вы хотите показать. Выберите правильный, установите его, как если бы это была переменная, которую вы определили, и (важно!) немедленно выйдите!

Однако вы можете спросить себя, является ли установка errno правильным подходом к вашей проблеме. Вы всегда можете определить (*int) и разработать свои собственные коды ошибок и механизм обработки ошибок. Errno предназначен для отображения и объяснения системных ошибок. Считаете ли вы свой код частью «системы» (как я вижу, вы разрабатываете свой собственный системный вызов, так что это может иметь место)? Так что продолжайте и используйте errno, чтобы объяснить вашу «системную ошибку».

Изменить (об обновлении вопроса): Хорошо, больше информации. Как я уже сказал, errno является внешним int и устанавливается ядром. Значение, на которое устанавливается errno, является просто возвращаемым значением системного вызова. Затем ядро ​​Linux интерпретирует это отрицательное значение через библиотеку errno.h. Таким образом, пример сообщения об ошибке устанавливается простым возвратом (EBUSY — это просто пример — вы можете использовать все предопределенные типы ошибок) сообщения об ошибке, которое вы хотите получить из вашего системного вызова. Пример:

return -EBUSY

Надеюсь, поможет

person sestus    schedule 04.07.2014
comment
Я добавляю некоторые пояснения в свой вопрос. - person Andrew Chang; 04.07.2014
comment
errno is an extern int не имеет смысла. Программы режима ядра и пользовательского режима выполняются в разных адресных пространствах. - person Melab; 28.01.2021

Возвращает отрицательный номер ошибки из ioctl. Библиотека c интерпретирует это и возвращает код возврата -1, а errno устанавливает положительную ошибку. Например, в исходном примере для errno будет установлено значение 1.

Кроме того, ваш прототип функции ioctl в ядре выглядит неправильно. Какую версию ядра вы используете?

person slobobaby    schedule 04.07.2014
comment
Благодарю вас! Соединяю ваши ответы и ответы сестуса и понимаю, что мне делать. Но ответ сестуса более подробный. Какой позор, что можно было принять только один ответ. - person Andrew Chang; 08.07.2014

if (isErr)
    {
        printk(KERN_ALERT "Error %d: your description\n", errno);
        ret = errno;
    }

где errno — это возвращаемое значение некоторой функции.

Ваш драйвер устройства должен всегда возвращать статус для полученного запроса. Рекомендуется всегда использовать перечисляемые коды возврата, а также обычные коды возврата. Возврат 0 = пройден 1 или -1 = не пройден, расплывчато и может ввести в заблуждение.

Прочтите раздел 3.1 Эффективная обработка ошибок, создание отчетов и восстановление: для получения дополнительной информации

person Sagar Jain    schedule 04.07.2014
comment
Насколько я понимаю, он хочет генерировать ошибки и соответственно устанавливать errno. Вы только что прочитали errno. Но системный вызов, который он разрабатывает, по умолчанию не устанавливает errno. Ему нужно установить его. - person sestus; 04.07.2014
comment
Да, я спросил о том, чтобы установить errno в драйвере устройства вместо приложений пользовательского пространства. - person Andrew Chang; 04.07.2014