-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcode13_5.cpp
More file actions
92 lines (80 loc) · 2.3 KB
/
Copy pathcode13_5.cpp
File metadata and controls
92 lines (80 loc) · 2.3 KB
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
#include <sys/socket.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <time.h>
static const int CONTROL_LEN = CMSG_LEN(sizeof(int));
/*发送文件描述符,fd参数是用来传递信息的UNIX域socket,fd_to_send参数是待发送的文件描述符*/
void send_fd(int fd,int fd_to_send)
{
struct iovec iov[1];
struct msghdr msg;
char buf[0];
iov[0].iov_base = buf;
iov[0].iov_len = 1;
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
cmsghdr cm;
cm.cmsg_len = CONTROL_LEN;
cm.cmsg_level = SOL_SOCKET;
cm.cmsg_type = SCM_RIGHTS;
*(int *)CMSG_DATA(&cm) = fd_to_send;
msg.msg_control = &cm;/*设置辅助数据*/
msg.msg_controllen = CONTROL_LEN;
sendmsg(fd,&msg,0);
}
/*接受目标文件描述符*/
int recv_fd(int fd)
{
struct iovec iov[1];
struct msghdr msg;
char buf[0];
iov[0].iov_base = buf;
iov[0].iov_len = 1;
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
cmsghdr cm;
msg.msg_control = &cm;/*设置辅助数据*/
msg.msg_controllen = CONTROL_LEN;
recvmsg(fd,&msg,0);
int fd_to_read = *(int *)CMSG_DATA(&cm);
return fd_to_read;
}
int main()
{
int pipefd[2];
int fd_to_pass = 0;
/*创建父子进程的管道,文件描述符pipefd[0]和pipefd[1] 都是UNIX域socket*/
int ret = socketpair(PF_UNIX,SOCK_DGRAM,0,pipefd);
assert(ret != -1);
pid_t pid = fork();
assert(pid >= 0);
if(pid == 0)
{
close(pipefd[0]);
fd_to_pass = open("code13_5.cpp",O_RDWR,0666);
/*子进程通过管道将文件描述符发送到父进程,如果文件test.txt打开失败,则
* 子进程将标准输入文件描述符发送到父进程*/
send_fd(pipefd[1],(fd_to_pass > 0) ? fd_to_pass : 0);
close(fd_to_pass);/*这里关闭文件描述符,父进程也能读文件,是因为在send_fd上可能有文件描述符的临时变量,导致文件引用数不会为0,*/
printf("www");
exit(0);
}
close(pipefd[1]);
int a = 1000000000;
while(a--);
fd_to_pass = recv_fd(pipefd[0]);/*父进程从管道接受目标文件描述符*/
char buff[1024];
memset(buff,'\0',1024);
read(fd_to_pass,buff,1024);/*读目标文件描述符,以验证其有效性*/
printf("I got fd %d and data %s\n",fd_to_pass,buff);
close(fd_to_pass);
return 0;
}