Share a file descriptor between parent and child after fork and exec

跟風遠走 提交于 2019-12-08 02:01:20

问题


I have two processes on Linux, A & B. I want to share the file descriptor from process A with process B, now I just serialize it to a char* and pass it to the execl parameters, but that doesn't work.

A.c looks like this:

union descriptor{
    char c[sizeof(int)];
    int i;
} fd;
pid_t pid;

fd.i = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// Perform other socket functions

pid = fork();
if(pid == 0){
    // Read data from socket
    if(execl("./B", fd.c, NULL) < 0){
        exit(EXIT_FAILURE);
    }else(
        exit(EXIT_SUCCESS);
    }
}else if(pid < 0){
    exit(EXIT_FAILURE);
}else{
    waitpid(pid, NULL, 0);
}

B.c looks like this:

union descriptor{
    char c[sizeof(int)];
    int i;
} fd;

memcpy(&fd.c[0], argv[0], sizeof(int));

write(fd.i, "TEST", 4);
close(fd.i);

But this doesn't work, and I don't really understand why not. How can I make this work? And if it works, is it the best solution to share a file descriptor between a parent and a child after a fork and a exec?

Update

The problem is unrelated to the question I asked, it is caused by a wrong way of passing an integer as pointed out by @OliCharlesworth. Please close this question.


回答1:


File descriptors are always passed between a parent and child process

When you fork a process, the file descriptors that are open in the parent(at the time of fork()) are implicitly passed on to the child. There is no need to send them explicitly.

For example:

The pseudo-code looks as follows:

In process A:

fd = open_socket_or_file;
char str_fd[3];
str_fd[0]=fd;
str_fd[1]=fd;
str_fd[2]=0;
if(fork()==0)
{
     execl("./B",str_fd,NULL);
}

In the child process B you can do:

int fd = argv[1][0];
/* now do whatever you want with the fd...*/

EDIT:

In case the processes are different, you need to pass the file descriptor explicitly. This is generally done using UNIX-Domain Sockets(If you are using Linux Flavors). For code related to this, you can see this answer




回答2:


Yes that is true that file descriptors remain open even after fork or exec or fork and exec.You only need to know the value of fd in the new process image that was replaced using exec else put that fd on the one which is already known to that process(ex:0,1,2). So you can do this in two ways:

  • Placing the fd on either one of standard file descriptors using dup2(note:as far as i know you will be unable to reset that standard file descriptor for which it was actually known for)

  • Passing the fd as string argument for one of 6 exec functions does the job

Therefore I suggest you to use second method in case if you want standard fds remain

These are the two methods of implementation:

P1.c(using argument passing)

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
void main()
{
    printf("Hello this is process 1\n");
    int fd=open("./foo",O_RDONLY);
    char buf[255];
    //int n=read(fd,buf,255);
    int h=fork();
    if(h==0)
    {
        char *fname="./p2";
        char *arg[3];
        char targ[10];
        sprintf(targ,"%d",fd);
        arg[0]=fname;
        arg[1]=targ;
        arg[2]=NULL;
        execvp(fname,arg);
    }
    else
    {
        printf("This is from p1 process\n");
        //write(1,buf,strlen(buf));
                    //do some process with p1
        printf("This is end of p1 process\n");
    }
}

P1.c(using dup2 with 0)

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
void main()
{
    printf("Hello this is process 1\n");
    int fd=open("./foo",O_RDONLY);
    int h=fork();
    if(h==0)
    {
        dup2(fd,0);//note we will be loosing standard input in p2
        execvp(fname,NULL);
    }
    else
    {
        printf("This is from p1 process\n");
        //write(1,buf,strlen(buf));
                    //do some process with p1
        printf("This is end of p1 process\n");
    }
}

P2.c

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
int main(int argc,char *argv[])
{
    int fd=atoi(argv[1]);      //here fd=0 in case dup2 in process ps1.c
    char buf[1024];
    int n=read(fd,buf,1024);
    buf[n]='\0';
    printf("This is from p2\n");
    write(1,buf,strlen(buf));
}


来源:https://stackoverflow.com/questions/21512334/share-a-file-descriptor-between-parent-and-child-after-fork-and-exec

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!