写完后,至少调试了30分钟时间。
错误1:
snprintf(argsockfd, sizeof(argsockfd), "%d", sockfd[1]);
snprintf(argmode, sizeof(argmode), "%d", mode);
写作:
snprintf(argsockfd, sizeof(argsockfd), "%s", sockfd[1]);
snprintf(argmode, sizeof(argmode), "%s", mode);
错误2: msg.msg_control = unc;
msg.msg_controllen = sizeof(unc);
忘记初始化
疑点3:如果不断跳转到recvmsg,总是可以接收,并没有阻塞?不知道什么原因,明天再看看
解决:由于recvmsg返回为0时,表示TCP对端已经发送了FIN。此时应当退出
#include "unp.h"
#define unc un.control
int my_open(const char *name, int mode);
int my_read(int fd, int *argfd);
int main(int argc, char **argv){
int fd, n;
char buf[MAXLINE];
if((fd = my_open(argv[1], O_RDONLY)) < 0)
err_sys("my_open");
while((n = read(fd, buf, MAXLINE)) > 0)
write(STDOUT_FILENO, buf, n);
exit(0);
}
int my_open(const char *name, int mode){
int sockfd[2], fd, status;
pid_t tid;
char argsockfd[10], argmode[10];
if(socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd) < 0 )
err_sys("pairsock");
if((tid = fork( )) < 0)
err_sys("fork");
else if(tid == 0){/*child进程*/
#ifdef DEBUG
printf("child exec\n");
#endif
close(sockfd[0]);
snprintf(argsockfd, sizeof(argsockfd), "%d", sockfd[1]);
snprintf(argmode, sizeof(argmode), "%d", mode);
execl("./openfile", "openfile", argsockfd,
argmode, name, (char *)NULL);
err_sys("execl");
}
/*parent进程*/
close(sockfd[1]);
waitpid(tid, &status, 0);
#ifdef DEBUG
sleep(5);
#endif
if(my_read(sockfd[0], &fd) < 0)/*读取描述符*/
return -1;
close(sockfd[0]);
return fd;
}
int my_read(int fd, int *argfd){
int n;
char *buf = malloc(sizeof(char));
struct msghdr msg;
struct cmsghdr *cmsg;
union{
struct cmsghdr cm;
char control[CMSG_SPACE(sizeof(int))];
}un;
struct iovec iov[1];
iov[0].iov_base = buf;
iov[0].iov_len = 1;
bzero(&msg, sizeof(msg));
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_control = unc;
msg.msg_controllen = sizeof(unc);
//msg.msg_flags = 0;
again:
if((n = recvmsg(fd, &msg, 0)) <= 0){
if(errno == EINTR)
return -1;
else
goto again;
}
free(buf);
buf = NULL;
#ifdef DEBUG
printf("recv is complete %d\n", n);
goto again;
#endif
cmsg = CMSG_FIRSTHDR(&msg);
if(cmsg == NULL){
return -1;
}
if(cmsg->cmsg_len != CMSG_LEN(sizeof(int))){
return -1;
}
if((cmsg->cmsg_level == SOL_SOCKET)&&(cmsg->cmsg_type == SCM_RIGHTS)){
*argfd = *(int *)CMSG_DATA(cmsg);
}
else
*argfd = -1;
return 0;
}
/*示范1*/
#include "unp.h"
#define unc un.control
int my_write(int openfd, int fd);
int main(int argc, char **argv){
int fd, openfd;
if((fd = open(argv[3], atoi(argv[2]))) < 0)
err_sys("open");
openfd = atoi(argv[1]);
if(my_write(openfd, fd) < 0)/*利用openfd套接口将fd发送给父进程*/
err_sys("my_write");
close(fd);
exit(0);
}
int my_write(int openfd, int fd){
int n;
char *c = malloc(sizeof(char));
struct msghdr msg;
struct cmsghdr *cmsg;
struct iovec iov[1];
union{
struct cmsghdr cm;
char control[CMSG_SPACE(sizeof(int))];
}un;
*c = 'a';
iov[0].iov_base = c;
iov[0].iov_len = 1;
bzero(&msg, sizeof(msg));
msg.msg_control = unc;
msg.msg_controllen = sizeof(unc);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
*(int *)CMSG_DATA(cmsg) = fd;
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_flags = 0;
again:
if((n = sendmsg(openfd, &msg, 0) ) < 0){
if(errno == EINTR)
goto again;
else
return -1;
}
//sleep(5);
free(c);
c = NULL;
return 0;
}