利用Unix域套接字實現IPC

寫完後,至少調試了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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章