#include<bits/stdc++.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<string.h>
#include<netinet/in.h>
#include<errno.h>
#include<stdio.h>
#include<sys/wait.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<arpa/inet.h>
#include<signal.h>
#define PORT 7000
#define EXIT_ERR(m) \
do{\
perror(m);\
printf("\n");\
exit(0);\
}while(0)
int read_fd(int sockfd,char *c,int len,int *fd);
int main(){
int fd;
pid_t pid;
// pid_t pid=fork() //在这儿范了个极大的错误,因为在pid==0之前执行了
//socketpair(AF_LOCAL,SOCK_STREAM,0,sockfd); 至于子进程新建了两个描述符.
int sockfd[2];
socketpair(AF_LOCAL,SOCK_STREAM,0,sockfd);
if( (pid=fork() ) ==0){
printf("pid is 0\n");
close(sockfd[0]);
char argfd[10];
char argmod[10];
int mod=O_RDONLY;
snprintf(argfd,sizeof(argfd),"%d",sockfd[1]);
snprintf(argmod,sizeof(argmod),"%d",mod);
if(execl("./openfile",argfd,"test.txt",argmod,(char *)NULL)<0)/在调用execl函数执行一个文件的话要确保:全路径名是正确的,第二个参数必须对应为第一个参数的文件名;最后一个参数是 (char *)NULL ;可以直接把第一个参数放在命令行运行来检验。否则会出现 Permission denied 错误。
//值得注意的是,即使执行的是一个解释器文件,也需要其有可执行权限。(这是在看APUE时遇到的问题)
EXIT_ERR("execl error");
}
int status;
close(sockfd[1]);
waitpid(pid,&status,0);
if(WIFEXITED(status)==0)
EXIT_ERR("child did terminate");
char c;
if(status=WEXITSTATUS(status)==0)
read_fd(sockfd[0],&c,1,&fd);
else{
EXIT_ERR("status !=0");
errno=status;
fd=-1;
}
printf("c: %c fd:%d\n", c,fd);
close(sockfd[0]);
return fd;
}
int read_fd(int sockfd,char *c,int len,int *fd)
{
printf("read_fd\n");
msghdr msg;
iovec iov[1];
iov[0].iov_base=c;
iov[0].iov_len=1;
msg.msg_name=NULL;
msg.msg_namelen=0;
msg.msg_iov=iov;
msg.msg_iovlen=1;
union{
cmsghdr cmsg;
char control[CMSG_LEN(sizeof(int))];
}control_un;
cmsghdr *cmsgptr;
msg.msg_control=control_un.control;
msg.msg_controllen=sizeof(control_un.control);
int n=recvmsg(sockfd,&msg,0);
if(n<=0)
EXIT_ERR("recvmag error");
if( ( cmsgptr=CMSG_FIRSTHDR(&msg) ) !=NULL && cmsgptr->cmsg_len==CMSG_LEN(sizeof(int)) )
{
if(cmsgptr->cmsg_level!=SOL_SOCKET)
EXIT_ERR("level != SOL_SOCKET");
if(cmsgptr->cmsg_type!=SCM_RIGHTS)
EXIT_ERR("type != SCM_RIGHTS");
*fd=*(int *)CMSG_DATA(cmsgptr);
}
return n;
}
#include<sys/socket.h>
#include<sys/types.h>
#include<string.h>
#include<netinet/in.h>
#include<errno.h>
#include<stdio.h>
#include<sys/wait.h>
#include<fcntl.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<signal.h>
#define PORT 7000
#define EXIT_ERR(m) \
do{\
perror(m);\
printf("\n");\
exit(0);\
}while(0)
int write_fd(int sockfd,int fd);
int main(int argc,char **argv){
printf("child start\n");
if(argc!=3)///
{
EXIT_ERR("arg error");
}
int fd;
if((fd=open(argv[1],atoi(argv[2])))<0)
EXIT_ERR("open error");
printf("%d\n",fd);
if(write_fd(atoi(argv[0]),fd)<=0){
EXIT_ERR("write_fd error");
exit(errno>0?errno:255);
}
printf("openfile finished\n");
exit(0);
}
int write_fd(int sockfd,int fd){
msghdr msg;
iovec iov[1];
union{
cmsghdr cms;
char control[CMSG_SPACE(sizeof(int))];
} control_un;
msg.msg_name=NULL;
msg.msg_namelen=0;
msg.msg_control=control_un.control;
msg.msg_controllen=sizeof(control_un.control);
msg.msg_iov=iov;
msg.msg_iovlen=1;
char c='a';
iov[0].iov_base=&c;
iov[0].iov_len=1;
cmsghdr *scmptr;
scmptr=CMSG_FIRSTHDR(&msg);
scmptr->cmsg_len=CMSG_LEN(sizeof(int));
scmptr->cmsg_level=SOL_SOCKET;
scmptr->cmsg_type=SCM_RIGHTS;
*(int *)CMSG_DATA(scmptr)=fd;
return sendmsg(sockfd,&msg,0);
}