![](/img/trans.png)
[英]using which IPC I can pass file descriptor from one process to another on same machine?
[英]Can I share a file descriptor to another process on linux or are they local to the process?
假設我有2個進程,ProcessA和ProcessB。 如果我在ProcessA中執行int fd=open(somefile)
,那么我可以將文件描述符fd
的值通過IPC傳遞給ProcessB並讓它操作同一個文件嗎?
您可以通過unix域套接字將文件描述符傳遞給另一個進程。 這是傳遞這樣一個文件描述符的代碼,取自Unix網絡編程
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 */
如果兩個進程都屬於同一個用戶,那么您可以簡單地使用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? ”。
您可以使用此線程中描述的方法或者(更常規)方法,通過創建它來在相關進程(通常是父子或兄弟)之間共享它,分叉進程自動接收副本。
實際上,分叉進程會獲取所有FD並且可以使用它們,除非它們關閉它們(這通常是一個好主意)。
因此,如果父級分叉兩個孩子,如果他們都有一個文件描述符,他們沒有關閉,現在它被共享(即使父母隨后關閉它)。 例如,這可能是從一個孩子到另一個孩子的管道。 這就是shell重定向的方式
ls -l | more
工作。
請注意,在上面的示例中,接收時設置變量,如:
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;
不需要。 帶有標題的消息結構的整個概念是接收站點不必知道它讀取的內容,並且可以通過檢查(第一個)標題,它是什么類型的消息以及期望什么。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.