Мне нужно отправить файловые дескрипторы некоторых буферов общей памяти из одного процесса в другой. Я могу передать fds напрямую через сокеты домена UNIX, как показано ниже:
Отправить ФД:
static void send_fds(int socket, int* fds, int n) // send fd by socket
{
struct msghdr msg = {0};
struct cmsghdr* cmsg;
char buf[CMSG_SPACE(n * sizeof(int))], dup[256];
memset(buf, '\0', sizeof(buf));
struct iovec io = {.iov_base = &dup, .iov_len = sizeof(dup)};
msg.msg_iov = &io;
msg.msg_iovlen = 1;
msg.msg_control = buf;
msg.msg_controllen = sizeof(buf);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(n * sizeof(int));
memcpy((int*)CMSG_DATA(cmsg), fds, n * sizeof(int));
if (sendmsg(socket, &msg, 0) < 0)
printf("Failed to send message\n");
}
Получить ФД:
static int* recv_fds(int socket, int n) {
int* fds = (int*)malloc(n * sizeof(int));
struct msghdr msg = {0};
struct cmsghdr* cmsg;
char buf[CMSG_SPACE(n * sizeof(int))], dup[256];
memset(buf, '\0', sizeof(buf));
struct iovec io = {.iov_base = &dup, .iov_len = sizeof(dup)};
msg.msg_iov = &io;
msg.msg_iovlen = 1;
msg.msg_control = buf;
msg.msg_controllen = sizeof(buf);
if (recvmsg(socket, &msg, 0) < 0)
printf("Failed to receive message\n");
cmsg = CMSG_FIRSTHDR(&msg);
memcpy(fds, (int*)CMSG_DATA(cmsg), n * sizeof(int));
return fds;
}
Но когда я использую доменные сокеты через абстракцию libuv_pipe_t
, предоставленную libuv
, я не смог передать fds. Предоставляет ли libuv
какой-либо способ передачи файловых дескрипторов между серверным каналом и клиентским каналом? Если да, то как именно отправлять и получать fds?
сервер uv_pipe_t:
#include <assert.h>
#include <memory.h>
#include <stdlib.h>
#include <unistd.h>
#include <uv.h>
#define SOCKET_NAME "socket_name"
void alloc_buffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
static char buffer[1024];
buf->base = buffer;
buf->len = sizeof(buffer);
}
void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
if (nread < 0) {
uv_stop(stream->loop);
uv_close((uv_handle_t*)stream, NULL);
}
printf("message received : %s\n", buf->base);
}
static void connection_cb(uv_stream_t* server, int status) {
printf("new connection recevied\n");
int r;
uv_pipe_t connection;
r = uv_pipe_init(server->loop, &connection, 0);
assert(r == 0);
r = uv_accept(server, (uv_stream_t*)&connection);
assert(r == 0);
r = uv_read_start((uv_stream_t*)&connection, alloc_buffer, read_cb);
assert(r == 0);
}
int main() {
uv_pipe_t p;
int r;
r = uv_pipe_init(uv_default_loop(), &p, 0);
assert(r == 0);
unlink(SOCKET_NAME);
r = uv_pipe_bind(&p, SOCKET_NAME);
assert(r == 0);
r = uv_listen((uv_stream_t*)&p, 128, connection_cb);
assert(r == 0);
printf("listening...\n");
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
uv_loop_close(uv_default_loop());
}
клиент uv_pipe_t:
#include <assert.h>
#include <memory.h>
#include <uv.h>
#define SOCKET_NAME "socket_name"
static void connect_cb(uv_connect_t* connect_req, int status) {
printf("connected!");
// send file descriptor
int fds[2];
fds[0] = fileno(fopen("fd_test_0.txt", "w"));
fds[1] = fileno(fopen("fd_test_1.txt", "w"));
// how to send "fds" array to server ?
}
int main() {
uv_pipe_t p;
uv_connect_t conn_req;
int r;
r = uv_pipe_init(uv_default_loop(), &p, 0);
assert(r == 0);
uv_pipe_connect(&conn_req, &p, SOCKET_NAME, connect_cb);
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
uv_loop_close(uv_default_loop());
}
этот пример показывает, как передавать pipe обрабатывает трубы, но это не полностью решает мою проблему.
Любая помощь приветствуется !!!