unix域套接字进程间传递文件描述符

#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);



}




















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值