我可以共享一个文件描述符到Linux上的另一个进程,或者他们是本地进程?

说我有2个进程,ProcessA和ProcessB。 如果我在ProcessA中执行int fd=open(somefile) ,那么我可以通过IPC的文件描述符fd的值传递给ProcessB,并让它操纵相同的文件?

您可以通过unix域套接字将文件描述符传递给另一个进程。 下面是从Unixnetworking编程中获取的传递这样一个文件描述符的代码

 ssize_t write_fd(int fd, void *ptr, size_t nbytes, int sendfd) { struct msghdr msg; struct iovec iov[1]; #ifdef HAVE_MSGHDR_MSG_CONTROL union { struct cmsghdr cm; char control[CMSG_SPACE(sizeof(int))]; } control_un; struct cmsghdr *cmptr; msg.msg_control = control_un.control; msg.msg_controllen = sizeof(control_un.control); cmptr = CMSG_FIRSTHDR(&msg); cmptr->cmsg_len = CMSG_LEN(sizeof(int)); cmptr->cmsg_level = SOL_SOCKET; cmptr->cmsg_type = SCM_RIGHTS; *((int *) CMSG_DATA(cmptr)) = sendfd; #else msg.msg_accrights = (caddr_t) &sendfd; msg.msg_accrightslen = sizeof(int); #endif msg.msg_name = NULL; msg.msg_namelen = 0; iov[0].iov_base = ptr; iov[0].iov_len = nbytes; msg.msg_iov = iov; msg.msg_iovlen = 1; return(sendmsg(fd, &msg, 0)); } /* end write_fd */ 

这里是接收文件描述符的代码

 ssize_t read_fd(int fd, void *ptr, size_t nbytes, int *recvfd) { struct msghdr msg; struct iovec iov[1]; ssize_t n; int newfd; #ifdef HAVE_MSGHDR_MSG_CONTROL union { struct cmsghdr cm; char control[CMSG_SPACE(sizeof(int))]; } control_un; struct cmsghdr *cmptr; msg.msg_control = control_un.control; msg.msg_controllen = sizeof(control_un.control); #else msg.msg_accrights = (caddr_t) &newfd; msg.msg_accrightslen = sizeof(int); #endif msg.msg_name = NULL; msg.msg_namelen = 0; iov[0].iov_base = ptr; iov[0].iov_len = nbytes; msg.msg_iov = iov; msg.msg_iovlen = 1; if ( (n = recvmsg(fd, &msg, 0)) <= 0) return(n); #ifdef HAVE_MSGHDR_MSG_CONTROL if ( (cmptr = CMSG_FIRSTHDR(&msg)) != NULL && cmptr->cmsg_len == CMSG_LEN(sizeof(int))) { if (cmptr->cmsg_level != SOL_SOCKET) err_quit("control level != SOL_SOCKET"); if (cmptr->cmsg_type != SCM_RIGHTS) err_quit("control type != SCM_RIGHTS"); *recvfd = *((int *) CMSG_DATA(cmptr)); } else *recvfd = -1; /* descriptor was not passed */ #else /* *INDENT-OFF* */ if (msg.msg_accrightslen == sizeof(int)) *recvfd = newfd; else *recvfd = -1; /* descriptor was not passed */ /* *INDENT-ON* */ #endif return(n); } /* end read_fd */ 

您可以使用此线程中描述的方法,或者(更传统的)方式,通过在相关进程(通常是父 – 子或同级)之间共享它,分叉进程自动接收副本。

实际上,分叉进程得到所有的FD,并可以使用它们,除非它们closures它们(这通常是一个好主意)。

因此,如果一个父项分叉了两个子项,如果它们都有一个文件描述符,它们就不会closures,现在就被共享了(即使父项closures了它)。 例如,这可能是从一个孩子到另一个孩子的pipe道。 这是shellredirect的方式

 ls -l | more 

工作。

请注意,在上面的例子中,接收variables的设置,如:

 msg.msg_name = NULL; msg.msg_namelen = 0; iov[0].iov_base = ptr; iov[0].iov_len = nbytes; msg.msg_iov = iov; msg.msg_iovlen = 1; 

不需要。 带有标题的消息结构的整个概念是,接收站点不必知道它读的是什么,并且可以通过检查(第一个)标题,它是什么types的消息以及期望什么。

如果两个进程属于同一个用户,那么你可以简单地使用procfs。

 char fd_path[64]; // actual maximal length: 37 for 64bit systems snprintf(fd_path, sizeof(fd_path), "/proc/%d/fd/%d", SOURCE_PID, SOURCE_FD); int new_fd = open(fd_path, O_RDWR); 

当然你需要一些IPC机制来分享SOURCE_FD的价值。 参见例如“ Linux C:收到信号后,是否可以知道发件人的PID? ”。