Skip to content

Commit a4f89a5

Browse files
committed
send_fd.cpp
1 parent 0d786ee commit a4f89a5

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed

ch13/send_fd.cpp

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#include <sys/socket.h>
2+
#include <fcntl.h>
3+
#include <stdio.h>
4+
#include <unistd.h>
5+
#include <stdlib.h>
6+
#include <assert.h>
7+
#include <string.h>
8+
9+
static const int CONTROL_LEN = CMSG_LEN( sizeof(int) );
10+
/* 发送文件描述符,fd参数是用来传递信息的UNIX域socket,fd_to_send参数是待发送的文件描述符 */
11+
void send_fd( int fd, int fd_to_send ){
12+
struct iovec iov[1];
13+
struct msghdr msg;
14+
char buf[0];
15+
16+
iov[0].iov_base = buf;
17+
iov[0].iov_len = 1;
18+
msg.msg_name = NULL;
19+
msg.msg_namelen = 0;
20+
msg.msg_iov = iov;
21+
msg.msg_iovlen = 1;
22+
23+
cmsghdr cm;
24+
cm.cmsg_len = CONTROL_LEN;
25+
cm.cmsg_level = SOL_SOCKET;
26+
cm.cmsg_type = SCM_RIGHTS;
27+
*(int *)CMSG_DATA( &cm ) = fd_to_send;
28+
msg.msg_control = &cm; /* 设置辅助数据 */
29+
msg.msg_controllen = CONTROL_LEN;
30+
31+
sendmsg( fd, &msg, 0 );
32+
}
33+
34+
/* 接收目标文件描述符 */
35+
int recv_fd( int fd ){
36+
struct iovec iov[1];
37+
struct msghdr msg;
38+
char buf[0];
39+
40+
iov[0].iov_base = buf;
41+
iov[0].iov_len = 1;
42+
msg.msg_name = NULL;
43+
msg.msg_namelen = 0;
44+
msg.msg_iov = iov;
45+
msg.msg_iovlen = 1;
46+
47+
cmsghdr cm;
48+
msg.msg_control = &cm;
49+
msg.msg_controllen = CONTROL_LEN;
50+
51+
recvmsg( fd,&msg,0 );
52+
53+
int fd_to_read = *(int *)CMSG_DATA( &cm );
54+
return fd_to_read;
55+
}
56+
57+
58+
int main(){
59+
int pipefd[2];
60+
int fd_to_pass = 0;
61+
/* 创建父亲,子进程间的管道,文件描述符pipefd[0]和pipefd[1]都是UNIX域socket */
62+
int ret = socketpair( PF_UNIX, SOCK_DGRAM, 0, pipefd );
63+
assert( ret != -1 );
64+
65+
pid_t pid = fork();
66+
assert( pid>=0 );
67+
68+
if( pid == 0 ){
69+
close( pipefd[0] );
70+
fd_to_pass = open( "test.txt", O_RDWR, 0666 );
71+
/* 子进程通过管道将文件描述符发送到父进程。如果文件test.txt打开失败,则子进程将标准输入文件描述符发送到父进程 */
72+
send_fd( pipefd[1], ( fd_to_pass > 0 ) ? fd_to_pass : 0 );
73+
close( fd_to_pass );
74+
exit(0);
75+
}
76+
77+
close( pipefd[1] );
78+
fd_to_pass = recv_fd( pipefd[0] ); /* 父进程从管道接收目标文件描述符 */
79+
char buf[1024];
80+
memset( buf, '\0', 1024 ); /* 读目标文件描述符,以验证其有效性 */
81+
read( fd_to_pass, buf, 1024 );
82+
printf("I got fd %d and data %s\n", fd_to_pass, buf);
83+
close( fd_to_pass );
84+
}

0 commit comments

Comments
 (0)