При передаче файловых дескрипторов через доменные сокеты Unix используются управляющие сообщения на уровне SOL_SOCKET
типа SCM_RIGHTS
.
Управляющие сообщения читаются и записываются с использованием макросов CMSG_FIRSTHDR
, CMSG_NXTHDR
иCMSG_DATA
.Они принимают во внимание вопросы выравнивания.В зависимости от операционной системы и реализации libc они приводят указатели и разыменовывают результат либо в том же, либо в другом модуле перевода.Они также возвращают такие указатели, и вызывающий код обычно разыменовывает их.
В результате, использование простого выделенного в стеке char buf[CMSG_SPACE(sizeof(int))]
в качестве буфера управляющего сообщения нарушит строгое псевдонимы, так как доступ к буферу возможен только с использованиемЗначения типа char
, signed char
, unsigned char
или их квалифицированные версии.(На некоторых платформах буфер также может быть неправильно выровнен, но соглашения о вызовах amd64, кажется, гарантируют это, потому что буфер достаточно большой.)
Очевидно правильное решение - выделить буфер управляющего сообщения, используя calloc()
, который обеспечивает надлежащим образом выровненную память без эффективного типа.Однако я хотел бы не делать программу менее эффективной.
В https://svnweb.freebsd.org/base/head/lib/libopenbsd/imsg.c?revision=292023&view=markup Я нашел другой подход, когда буфер стека имеет тип union { struct cmsghdr hdr; char buf[CMSG_SPACE(sizeof(int))]; }
, но я не знаю, так ли этоверно.Я думаю, это помогает, что struct cmsghdr
имеет поле типа int
.
Дополнительный вопрос: как сделать это в C ++, учитывая, что C ++ имеет другие правила относительно (среди прочего) объединений, чем C?