ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

SerenityOS recvfd(2) 手册解析:通过本地域套接字带外传递文件描述符

SerenityOS recvfd(2) 手册解析:通过本地域套接字带外传递文件描述符 SerenityOS recvfd(2) 手册解析通过本地域套接字带外传递文件描述符【免费下载链接】serenityThe Serenity Operating System 项目地址: https://gitcode.com/GitHub_Trending/se/serenity本篇围绕 Serenity OS 系统调用手册页 recvfd.md 展开完整覆盖其函数原型、options标志、返回值与错误码语义并结合内核源码 sys$recvfd 实现 与 LocalSocket::recvfd 的实现细节说明 fd 如何以带外out-of-band方式在本地套接字两端传递。读完后你将掌握如何在两个 SerenityOS 进程间通过AF_LOCAL套接字传递打开的文件描述符、recvfd()的非阻塞语义与全部错误码的内核出处、以及它与配对调用sendfd()的协作方式。1. 功能概述跨进程传递打开的 fdrecvfd()用于从经sockfd连接的本地套接字对端进程接收一个已打开的文件描述符file descriptor。它与sendfd()构成一对对称系统调用调用原型语义返回sendfdint sendfd(int sockfd, int fd);发送一个打开的 fd 给本地套接字对端成功返回 0失败返回 -1recvfdint recvfd(int sockfd, int options);接收对端发来的 fd成功返回新分配的非负 fd失败返回 -1两者都要求sockfd指向本地域local domain套接字且 fd 的传递是带外的走独立的 fd 队列不影响套接字常规数据流read/write缓冲区的内容与顺序。这一机制源自 Plan 9 from User SpaceSerenityOS 将其纳入自身系统调用集。1.1 与常规数据流的分离这一点在内核结构上可以直接印证。LocalSocket 为每对连接维护了两个DoubleBuffer数据缓冲m_for_client/m_for_server见 LocalSocket 构造函数用于常规读写而sendfd/recvfd使用的m_fds_for_client/m_fds_for_server两个VectorNonnullRefPtrOpenFileDescription队列是完全独立的。从源码结构看两个通道的阻塞判定互不影响因此传 fd 不会干扰同一连接上的普通字节流通信。1.2 系统调用层与 LibC 封装recvfd在系统调用表中的注册条目见 Syscall.hS(recvfd, NeedsBigProcessLock::No)NeedsBigProcessLock::No表明该调用不要求持有进程大锁执行路径较短。用户态入口位于 LibC 的 sys/socket.cppint recvfd(int sockfd, int options) { int rc syscall(SC_recvfd, sockfd, options); ... }原型声明见 sys/socket.h。与手册页一致需要#include sys/socket.h后即可调用。2. Synopsis 与 options 参数手册页给出的函数原型为#include sys/socket.h int recvfd(int sockfd, int options);options是一个位掩码目前手册页仅定义了一个标志O_CLOEXEC接收到的新 fd 应设置 close-on-exec 标志即调用进程后续exec时该 fd 自动关闭exec(2) 手册页交叉引用的执行语义。在内核实现中该标志的解析只有一步sys$recvfd 中若options O_CLOEXEC则向新 fd 写入FD_CLOEXEC标志位随后连同收到的OpenFileDescription一起挂入调用进程的 fd 表。换言之recvfd()成功返回的 fd 是调用进程 fd 表中新分配的最小空闲号它引用的是对端发来的同一份打开文件描述对象共享打开状态如文件偏移、异步信号状态。3. 非阻塞语义与接收流程手册页明确指出recvfd()是非阻塞调用若套接字队列中没有等待接收的 fd 则会失败返回EAGAIN。内核侧的完整调用链为前置检查sys$recvfdrequire_promise(Pledge::recvfd)——进程必须已pledge了recvfd能力否则拒绝EDEFAULTopen_file_description(sockfd)失败则返回对应错误fd 未打开即EBADF不是套接字 →ENOTSOCK不是本地套接字 →EAFNOSUPPORT。预分配 fd 槽位先在调用进程 fd 表中allocate()一个 fd 号为即将收到的描述符预留位置。出队LocalSocket::recvfd 在套接字互斥锁下按当前 fd 的角色Role::Connected或Role::Accepted选出对应的recvfd队列队列为空则返回EAGAIN否则queue.take_first()取出队首的OpenFileDescription并转移所有权。落入 fd 表回到 sys$recvfd将描述符连同O_CLOEXEC转换后的标志写入已分配的 fd 槽位返回 fd 号。角色role与队列的对应关系由 recvfd_queue_for / sendfd_queue_for 决定客户端角色Connected从m_fds_for_client收、往m_fds_for_server发被接受端角色Accepted反之。两个方向各自独立排队互不干扰。4. 返回值与错误码附内核出处成功时recvfd()返回收到的 fd非负整数失败返回 -1 并设置errno。手册页列出的五个错误在内核中的产生位置如下errno手册页含义内核产生位置EBADFsockfd不是打开的 fdopen_file_description(sockfd)解析失败见 sys$recvfdENOTSOCKsockfd不指向套接字!socket_description-is_socket()见 sys$recvfdEAFNOSUPPORTsockfd不是本地域套接字!socket.is_local()见 sys$recvfdEINVALsockfd不是已连接/已接受的套接字LocalSocket::recvfd 中 role 既非Connected也非AcceptedEAGAIN该套接字上没有排队等待的 fdLocalSocket::recvfd 队列为空时与之配对的sendfd()手册页见 sendfd.md还额外定义了两个错误ENOTCONNsys$sendfd 中!socket.is_connected()与EBUSYLocalSocket::sendfd 中对端待收队列超过 128 个 fd 时拒绝源码中该上限标注为 FIXME、尚待确定正式的限制策略。这解释了为何recvfd()是非阻塞的队列无界增长不受鼓励发送端满 128 即快速失败接收端则以EAGAIN表示当前没有可取的 fd。5. 典型使用模式基于前文语义一次 fd 传递的完整流程示意如下以AF_LOCAL流式套接字为例#include sys/socket.h #include fcntl.h /* 接收方先建立本地连接bind/listen/accept 或 connect 完成后再取 fd */ int client /* accept() 返回的已接受套接字或 connect() 后的对端套接字 */; int fd recvfd(client, O_CLOEXEC); /* 要求 pledge 过 recvfd */ if (fd 0) { /* errno: EBADF/ENOTSOCK/EAFNOSUPPORT/EINVAL/EAGAIN */ } /* 发送方在与 client 同一连接的另一个 fd 上执行 sendfd(peer_fd, fd_to_pass); 要求 pledge 过 sendfd返回 0 表示入队成功。 */要点归纳两端必须先完成本地套接字的连接/接受使角色达到Connected或Accepted否则会收到EINVALrecvfd()返回EAGAIN时通常意味着对端尚未sendfd或已取空队列可稍后重试该调用本身不会挂起传过来的是打开的文件描述符接收方得到的是一个全新 fd 号但共享同一打开文件状态可直接读写、dup或再传给第三方。6. 历史与延伸阅读recvfd()最早由 Plan 9 from User Space 引入SerenityOS 保留了该命名与语义并扩展了options位掩码当前仅O_CLOEXEC。相关手册页与源码入口配对调用手册页sendfd(2)系统调用实现Kernel/Syscalls/sendfd.cppsys$sendfd与sys$recvfd同文件实现内核套接字层队列Kernel/Net/LocalSocket.cpp系统调用注册表Kernel/API/Syscall.h用户态封装Userland/Libraries/LibC/sys/socket.cpp适用前提以上行为描述基于当前仓库内核与 LibC 的实际实现sendfd端 128 个 fd 的队列上限是源码中明确标注待完善的临时值FIXME后续版本可能调整以仓库当时的 LocalSocket::sendfd 为准。【免费下载链接】serenityThe Serenity Operating System 项目地址: https://gitcode.com/GitHub_Trending/se/serenity创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表