在fork和exec之后在父级和子级之间共享文件描述符

我在Linux,A和B上有两个进程。我想从进程A与进程B共享文件描述符,现在我只是将它序列化为char*并将其传递给execl参数,但这不起作用。

Ac看起来像这样:

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

Bc看起来像这样:

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

但这不起作用,我真的不明白为什么不行。 我怎样才能做到这一点? 如果它有效,它是在forkexec之后在父级和子级之间共享文件描述符的最佳解决方案吗?

更新

问题与我提出的问题无关,它是由@OliCharlesworth指出的传递整数的错误方式引起的。 请关闭这个问题。

File descriptors are always passed between a parent and child process

fork进程时,父进程中打开的文件描述符(在fork() )会隐式传递给子进程。 无需明确发送它们。

例如:

伪代码如下所示:

在过程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); } 

在子进程B中,您可以执行以下操作:

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

编辑:

如果进程不同,则需要显式传递文件描述符。 这通常使用UNIX-Domain套接字完成(如果您使用的是Linux Flavors)。 对于与此相关的代码,您可以看到此答案

是的,即使在fork或exec或fork和exec之后,文件描述符仍然保持打开。你只需要知道在使用exec替换的新进程映像中fd的值,将fd放在已知的那个fd上那个过程(例如:0,1,2)。 所以你可以用两种方式做到这一点:

  • 使用dup2将fd放置在任一标准文件描述符上(注意:据我所知,您将无法重置其实际已知的标准文件描述符)

  • 将fd作为6个exec函数之一的字符串参数传递就可以完成这项任务

因此,如果您希望保留标准fds,我建议您使用第二种方法

这是两种实施方法:

P1.c(使用参数传递)

 #include  #include  #include  #include  #include  #include  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(使用dup2和0)

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