我在Linux上的C程序遇到了一个问题。
我知道当一个进程被fork时,子进程会继承一些来自父进程的东西,包括打开的文件描述符。
问题是,我正在编写一个多进程服务器应用程序,其中有一个主进程接受新连接并将描述符放入共享内存中。
当子进程尝试从共享内存中的描述符读取数据时,在select()
操作中出现了EBADF
错误!
在fork之后,子进程如何读取和使用父进程创建的套接字(或任何文件描述符)?
我在Linux上的C程序遇到了一个问题。
我知道当一个进程被fork时,子进程会继承一些来自父进程的东西,包括打开的文件描述符。
问题是,我正在编写一个多进程服务器应用程序,其中有一个主进程接受新连接并将描述符放入共享内存中。
当子进程尝试从共享内存中的描述符读取数据时,在select()
操作中出现了EBADF
错误!
在fork之后,子进程如何读取和使用父进程创建的套接字(或任何文件描述符)?
顺便说一句,你可以从UNIX网络编程网站下载许多服务器和客户端的好例子。
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);
SCM_RIGHTS
的消息大致如下: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;
}
}
accept
。在 Linux 上,一个非标准的方法是使用clone
和CLONE_FILES
代替fork
,以便进程共享文件描述符。 - Timothy Baldwin