memfd_create创建的文件句柄传递到另一个进程中如何使用?举c/c++代码例子
时间: 2024-02-13 18:03:09 浏览: 130
C#程序提示“正由另一进程使用,因此该进程无法访问该文件”的解决办法
在 Linux 中,memfd_create 创建的文件句柄可以通过进程间通信(IPC)的方式传递到另一个进程中。其中,最常用的 IPC 方式是管道(pipe)和套接字(socket)。传递文件句柄需要使用特殊的系统调用 sendmsg 和 recvmsg,具体步骤如下:
1. 发送进程调用 sendmsg,填充 msghdr 结构体,将文件句柄封装到辅助数据(ancillary data)中,使用 SCM_RIGHTS 标志表示传递文件描述符。代码如下:
```c
#include <sys/socket.h>
#include <sys/types.h>
int send_fd(int socket, int fd)
{
struct msghdr msg = {0};
char buf[CMSG_SPACE(sizeof(fd))];
memset(buf, 0, sizeof(buf));
struct iovec iov[1];
iov[0].iov_base = buf;
iov[0].iov_len = sizeof(buf);
msg.msg_iov = iov;
msg.msg_iovlen = 1;
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
*(int *)CMSG_DATA(cmsg) = fd;
return sendmsg(socket, &msg, 0);
}
```
2. 接收进程调用 recvmsg,接收包含文件句柄的数据。代码如下:
```c
#include <sys/socket.h>
#include <sys/types.h>
int recv_fd(int socket)
{
struct msghdr msg = {0};
char buf[CMSG_SPACE(sizeof(int))];
memset(buf, 0, sizeof(buf));
struct iovec iov[1];
iov[0].iov_base = buf;
iov[0].iov_len = sizeof(buf);
msg.msg_iov = iov;
msg.msg_iovlen = 1;
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
int ret = recvmsg(socket, &msg, 0);
if (ret < 0) {
return ret;
}
return *(int *)CMSG_DATA(cmsg);
}
```
3. 发送进程调用 memfd_create 创建文件句柄,并将其传递给接收进程。代码如下:
```c
#include <sys/mman.h>
#include <sys/syscall.h>
#include <unistd.h>
int main()
{
int fd = syscall(__NR_memfd_create, "test", 0);
if (fd < 0) {
return -1;
}
// 写入数据到文件
char *data = "Hello, world!";
write(fd, data, strlen(data));
// 创建套接字并发送文件句柄
int sockfds[2];
socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds);
send_fd(sockfds[0], fd);
close(fd);
// 接收文件句柄
int recv_fd = recv_fd(sockfds[1]);
close(sockfds[1]);
// 使用接收到的文件句柄
char *mapped = (char *)mmap(NULL, 4096, PROT_READ, MAP_SHARED, recv_fd, 0);
printf("%s\n", mapped);
munmap(mapped, 4096);
close(recv_fd);
return 0;
}
```
注意:在使用文件句柄之前,需要在接收进程中调用 mmap 将其映射到内存中,否则无法访问文件内容。
阅读全文