linux:利用socketpair来在进程间传递描述符
1.socketpair
2.sendmsg/recvmsg
3.UNIX域套接字传递描述字
功能:创建一个圈双工的流管道
原型:
int socketpair(int domain, int type, int protocol, int sv[2]);
参数 domain :协议家族
type: 套接字种类
protocol:协议种类
sv:返回的套接字对
返回值: 成功返回0, 失败返回-1
通过sockpair创建的全双通管道可以实现父子间进程通讯
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define ERR_EXIT(m) \ do { \ perror(m);\ exit(EXIT_FAILURE);\ }while(0) int main(int argc, const char *argv[]) { int sockfds[2]; int ret = socket(PF_UNIX, SOCK_STREAM, 0, sockfds); if(ret == -1) ERR_EXIT("sockpair"); pid_t pid; pid = fork(); if(pid == -1) ERR_EXIT("fork"); if(pid > 0) { int val = 0; close(sockfd[1]); while(1) { ++val; printf("sending data: %d\n", val); write(sockfds[0], &val, sizeof(val)); read(sockfd[0], &val, sizeof(val)); printf("data received: %d\n", val); sleep(1); } }else if(pid == 0) { int val; close(sockfds[0]); while(1) { read(sockfds[1], &val, sizeof(val)); ++val; write(sockfds[1], &val, sizeof(val)); } } return 0; }
会发现val的值不停的增加,并且在父子间进程被传递;
下面我们来看一下更加强大的sendmsg函数
ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
struct msghdr {
void *msg_name; /* optional address */
socklen_t msg_namelen; /* size of address */
struct iovec *msg_iov; /* scatter/gather array */
size_t msg_iovlen; /* # elements in msg_iov */
void *msg_control; /* ancillary data, see below */
size_t msg_controllen; /* ancillary data buffer len */
int msg_flags; /* flags on received message */
};
参数解释:
1.void *msg_name; /* optional address */
socklen_t msg_namelen;
这两个参数确定发送的地址
2。struct iovec *msg_iov; /* scatter/gather array */
我们要发送的数据存放在这个结构体中
struct iovec {
void *iov_base; /* Starting address */ 这个相当于缓冲区
size_t iov_len; /* Number of bytes to transfer */ 缓冲区长度
};
结构如上
++++++
这是一个msghdr的示意图
3.再下面几个数据时辅助信息。
我们通过自己封装sendmsg实现传递描述符
自己写一个send_fd