Bạn không thể truyền một ổ cắm (hoặc bất kỳ bộ mô tả tệp nào khác) từ quy trình này sang quy trình khác thông qua bộ nhớ dùng chung. Trình mô tả tệp chỉ là một số nguyên nhỏ. Đặt số nguyên này trong bộ nhớ chia sẻ và truy cập nó từ một tiến trình khác không tự động làm cho cùng một số nguyên thành một bộ mô tả tệp hợp lệ từ quan điểm của quá trình khác.
Cách chính xác để gửi bộ mô tả tệp từ quy trình này sang quy trình khác là gửi dữ liệu phụ như SCM_RIGHTS
thông qua một kênh truyền thông socket hiện có giữa hai quy trình.
Trước tiên, hãy tạo kênh giao tiếp của bạn với socketpair()
trước khi bạn fork()
. Bây giờ, trong phụ huynh, đóng một đầu của cặp ổ cắm, và, trong con, đóng đầu kia. Bây giờ bạn có thể sendmsg()
từ cha mẹ ở một đầu của ổ cắm này và nhận được với recvmsg()
ở trẻ em bằng cách sử dụng đầu kia.
Gửi một tin nhắn với SCM_RIGHTS
trông giống như sau:
struct msghdr m;
struct cmsghdr *cm;
struct iovec iov;
char buf[CMSG_SPACE(sizeof(int))];
char dummy[2];
memset(&m, 0, sizeof(m));
m.msg_controllen = CMSG_SPACE(sizeof(int));
m.msg_control = &buf;
memset(m.msg_control, 0, m.msg_controllen);
cm = CMSG_FIRSTHDR(&m);
cm->cmsg_level = SOL_SOCKET;
cm->cmsg_type = SCM_RIGHTS;
cm->cmsg_len = CMSG_LEN(sizeof(int));
*((int *)CMSG_DATA(cm)) = your_file_descriptor_to_send;
m.msg_iov = &iov;
m.msg_iovlen = 1;
iov.iov_base = dummy;
iov.iov_len = 1;
dummy[0] = 0; /* doesn't matter what data we send */
sendmsg(fd, &m, 0);
Tiếp nhận một tin nhắn với SCM_RIGHTS
trong nó đi một cái gì đó như thế này:
struct msghdr m;
struct cmsghdr *cm;
struct iovec iov;
struct dummy[100];
char buf[CMSG_SPACE(sizeof(int))];
ssize_t readlen;
int *fdlist;
iov.iov_base = dummy;
iov.iov_len = sizeof(dummy);
memset(&m, 0, sizeof(m));
m.msg_iov = &iov;
m.msg_iovlen = 1;
m.msg_controllen = CMSG_SPACE(sizeof(int));
m.msg_control = buf;
readlen = recvmsg(fd, &m, 0);
/* Do your error handling here in case recvmsg fails */
received_file_descriptor = -1; /* Default: none was received */
for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm)) {
if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS) {
nfds = (cm->cmsg_len - CMSG_LEN(0))/sizeof(int);
fdlist = (int *)CMSG_DATA(cm);
received_file_descriptor = *fdlist;
break;
}
}
tôi đã nói về quá trình cha/con, vì vậy câu hỏi là: Làm cách nào để truy cập con vào tệp mô tả do phụ huynh tạo sau khi ngã ba? – user1995143
+1 Để có câu trả lời hay, nhưng nghe có vẻ như tôi muốn sử dụng đề tài tốt hơn. –
@ user1995143 Đó chính là câu hỏi tôi đã trả lời. Không quan trọng mối quan hệ cha/con của 2 quy trình là gì. Miễn là bạn có một ổ cắm miền UNIX như một kênh truyền thông, bạn có thể truyền tải các bộ mô tả tập tin bằng cách sử dụng kỹ thuật này. Hoặc bạn có thể làm theo đề xuất của [Robert S. Barnes] (http://stackoverflow.com/users/71074/robert-s-barnes) và sử dụng nhiều chủ đề thay vì nhiều quy trình. Sau đó, bạn không phải lo lắng về nó bởi vì các bộ mô tả tập tin được chia sẻ giữa tất cả các luồng của một tiến trình đơn lẻ. – Celada