У меня есть фрагмент кода, который использует сокеты домена Unix и sendmsg / recvmsg для отправки файлов fd между двумя процессами. Этот код должен работать как на Linux, так и на Mac (он выполняется отдельно для обеих платформ). Я использую сокеты SOCK_DGRAM (датаграмма).
Я отправляю по одному fd в своем коде. На Mac после успешной отправки нескольких файлов fd таким образом recvmsg () завершается ошибкой с EMSGSIZE. Согласно справочной странице для recvmsg, это может произойти, только если msg-> msg_iovlen ‹= 0 или> = константа, которая на Mac равна 2048. В моем коде я всегда привязывал msg_iovlen к 1, я проверял это на отправителе и получателе, а также при чтении заголовка сообщения сразу после сбоев recvmsg (). Этот же код отлично работает в Linux.
Другая возможность, если посмотреть на исходный код ядра XNU, состоит в том, что у получателя могли закончиться fd, но я отправил только 4 или 5 fd до того, как произошла ошибка, поэтому должно быть много fd.
Если я не отправляю fd, а отправляю только данные, этой ошибки не возникает.
Вот как выглядит код, упаковывающий управляющее сообщение:
// *obj is the fd, objSize is sizeof(*obj)
// cmsg was allocated earlier as a 512 byte buffer
cmsgLength = CMSG_LEN(objSize);
cmsgSpace = CMSG_SPACE(objSize);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = cmsgLength;
memcpy(CMSG_DATA(cmsg), obj, objSize);
msg->msg_control = cmsg;
msg->msg_controllen = cmsgSpace;
А вот и ресивер:
msg = (struct msghdr *)pipe->msg;
iov = msg->msg_iov;
iov->iov_base = buf;
iov->iov_len = size;
// msg->msg_control was set earlier
msg->msg_controllen = 512;
return recvmsg(sockFd, msg, 0);
Какие-нибудь подсказки? заранее спасибо