shm implemented as memfd syscall
cheliequan
2022-12-27 54951dfb930bea890aef14be02236f81b3a19f2e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include "ipc_msg.h"
#include <string.h>
#include <stdlib.h>
 
/**
 * @brief 发送目标文件描述符
 * @param fd        传递信息的 UNIX 域 文件描述符
 * @param fd_to_send    待发送的文件描述符
 */
int  send_fd_args_sendmsg(int  fd, int fd_to_send, pid_t pid, void **ppdata, int len)
{
    struct iovec iov[1];
    struct msghdr msg;
  int control_len = 0;  
  int ret = 0;
  memfd_data_st memfd_data;
    struct cmsghdr cm;            /* 这是辅助数据头部结构体,文件描述符就是通过这个结构体以及后面的数据部分发送的 */
  
   control_len = CMSG_SPACE(sizeof(memfd_data_st) + len);
   char * recv_buf = (char *)malloc(control_len); 
 
   if(NULL != recv_buf)
   {
        return -1;
   }   
 
    iov[0].iov_base = recv_buf;
    iov[0].iov_len = 1;
    msg.msg_name = NULL;
    msg.msg_namelen = 0;
    msg.msg_iov = iov;
    msg.msg_iovlen = 1;
 
  memfd_data.memfd = fd_to_send;
  memfd_data.pid = pid;
  memfd_data.data = *ppdata;
  memfd_data.len = len;
  
 
    cm.cmsg_len = control_len;    /* 辅助数据的字节数,包扩头部和真正的数据 */
    cm.cmsg_level = SOL_SOCKET;    /* 表示原始协议级别,与 setsockopt 的 level 参数相同 */
    cm.cmsg_type = SCM_RIGHTS;    /* 控制信息类型,SCM_RIGHTS 表示传送的内容是访问权 */
    *(memfd_data_st*)CMSG_DATA(&cm) = memfd_data;/* 设置真正数据部分为我们想发送的文件描述符 */
    msg.msg_control = &cm;        /* 设置辅助数据 */
    msg.msg_controllen = control_len;
 
    ret = sendmsg(fd, &msg, 0);
  free(recv_buf);
  return ret;
}
 
/**
 * @brief 发送目标文件描述符
 * @param fd        传递信息的 UNIX 域 文件描述符
 * @param fd_to_send    待发送的文件描述符
 */
int  send_fd_sendmsg(int  fd, memfd_data_st** ppmemfd_data)
{
  memfd_data_st *ptr_memfd_data = *ppmemfd_data; 
  return send_fd_args_sendmsg(fd, ptr_memfd_data->memfd, ptr_memfd_data->pid, &ptr_memfd_data->data, ptr_memfd_data->len);
}
 
/**
 * @brief 接受文件描述符
 * @param fd 传递信息的 UNIX 域 文件描述符
 */
int recv_fd_recvmsg(int  fd, memfd_data_st** ppmemfd_data)
{
  struct iovec iov[1];
  struct msghdr msg;
  char recv_buf[MAX_LEN];
  int ret = -1; 
  int control_len = 0;
  struct cmsghdr cm;
 
  iov[0].iov_base = recv_buf;
    iov[0].iov_len = 1;
    msg.msg_name = NULL;
    msg.msg_namelen = 0;
    msg.msg_iov = iov;
    msg.msg_iovlen = 1;
 
  control_len = CMSG_SPACE(sizeof(memfd_data_st) + MAX_LEN);
 
    msg.msg_control = &cm;
    msg.msg_controllen = control_len;
 
    ret = recvmsg(fd, &msg, 0);
  if(ret < 0)
  {
    ret = -1;
  }
  
  int off = offsetof(memfd_data_st, len);
  int len = *(int*)((char *)CMSG_DATA(&cm) + off);
  control_len = CMSG_SPACE(sizeof(memfd_data_st) + len);
  *ppmemfd_data = (memfd_data_st *)malloc(control_len);
  if(*ppmemfd_data == NULL)
  {
      return -1;
  }
  memset(*ppmemfd_data, 0, control_len);
  memcpy(*ppmemfd_data, CMSG_DATA(&cm),  control_len);
  return ret;
}