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