Ключевые слова:kernel, struct, compile, freebsd, socket, connect, bind, (найти похожие документы)
Date: Thu, 2 May 2002 20:15:55 +0000 (UTC)
From: Valentin Nechayev <netch@segfault.kiev.ua>
Newsgroups: fido7.ru.unix.prog
Subject: Зачем нужно обнулять структуры перед передачей их в ядро
> Валентин, напомни, пожалуйста, ещё раз (ты, кажется, раньше говорил),
> зачем обнулять структуры перед передачей их в ядро... А это относится
Желательно - ко всем. Хотя стандарты этого не требуют.
Почему я говорю про желательно... почитай например Ralf Brown's Interrupt List.
Какие там странности навешиваются даже у стандартного софта на
неожиданные комбинации значений в регистрах.
Впрочем, это в досе и винде, а не в юниксах.
Во FreeBSD - вплоть до последнего полугода было то, что если в sin_addr
стоит не INADDR_ANY, то ненулевые значения в sin_zero (хвост структуры
sockaddr_in) приводят к отказу bind(). Это баг, и он уже исправлен, но
не знаю как с этим в других BSD.
У других ОС возможны другие эффекты. Хотя лично не наблюдал, бегали слухи.
Пару раз я видел явное требование заливать нулями все неизвестное.
> только к BSD или к другим ОС? Пару раз в манах натыкался на то, что
> структура должна быть обнулена, сейчас в красной книжке читаю про ioctl:
> If a return value is to be generated and there is no input,
> the buffer is zeroed.
Это, наверно, не то. ioctl() в большинстве реализаций устроен так,
что заводится буфер в kernel space заданного кодом ioctl размера и
переданные данные копируются в него. Потом копируются обратно в user space.
Если копирования из user в kernel нет, то берется то, что в полученной
по kernel malloc памяти, а там всегда для страховки нули.
> Почему они так нули любят?
Вокруг нас остались только идеологические наследники System 360:
архитектура, построенная во всех проявлениях на степенях двойки,
хранение целых чисел в дополнительном коде, представление плавающего
нуля всеми нулевыми байтами. Плюс к тому - невозможность указателя
со значением 0, причем не на уровне языка, а на уровне организации памяти.
Далее, стандарт Си на заливку статических переменных нулевыми значениями.
Далее, нулевое значение флагового параметра как отсутствие всех флагов...
В общем, сложилась устойчивая традиция - нулевое значение есть значение
из машинных нулей, и нулевое значение как безопасный дефолт.
При этом, bzero оказывается методом достичь максимально безопасного состояния
во всех параметрах, включая те, существование которых неизвестно автору
кода, как с теми же sin_zero и sin_len.
Нарушений этого принципа сейчас очень мало. Самое парадоксальное из
известных мне - syslog: LOG_EMERG==0, LOG_DEBUG==7,
в результате, написав по ошибке syslog(LOG_DAEMON,...) вместо
syslog(LOG_INFO,...) - получаешь wall на все терминалы.
При этом один из первых методов нарушить спокойствие программы, базирующейся
неявно на наличии нулей в полученной динамически памяти - сделать,
чтобы там не были нули. Например, на FreeBSD можно сказать
env MALLOC_OPTIONS=J $program и с хорошей вероятностью программа спечет корку,
если криво написана.;))
/netch