网站策划任职要求如何更换wordpress域名
2026/5/21 21:53:55 网站建设 项目流程
网站策划任职要求,如何更换wordpress域名,襄阳seo优化排名,天津小型企业网站设计fd从一个进程传到另一个进程涉及到socket通信#xff0c;具体来说是通过UNIX domain socket的辅助数据#xff08;ancillary data#xff09;机制实现的。这是一种在进程间传递文件描述符的标准方法。 1. fd传递的核心原理 在Linux中#xff0c;文件描述符只在单个进程内有…fd从一个进程传到另一个进程涉及到socket通信具体来说是通过UNIX domain socket的辅助数据ancillary data机制实现的。这是一种在进程间传递文件描述符的标准方法。1. fd传递的核心原理在Linux中文件描述符只在单个进程内有效。不同进程的文件描述符表是独立的因此不能直接将一个进程的fd值传给另一个进程使用。但内核提供了一种特殊机制允许通过UNIX domain socket传递文件描述符的所有权。这里我们用dma-buf共享机制为案例来分析。进程A (exporter) 进程B (importer) │ │ ├─ 创建 dma-buf │ │ dmabuf dma_buf_export(...) │ │ fd_A dma_buf_fd(dmabuf, ...) │ │ │ ├─ 通过 UNIX socket 发送 fd_A │ │ sendmsg(sock, msg, SCM_RIGHTS) │ │ │ │ │ └───────────────────────────├─ 接收 fd │ │ recvmsg(sock, msg, ...) │ │ fd_B extract_fd_from_msg(msg) │ │ │ ├─ 使用 fd_B 获取 dma-buf │ │ dmabuf dma_buf_get(fd_B) │ │ │ ├─ 进行后续操作 │ │ dma_buf_attach(...) │ │ dma_buf_map_attachment(...)2. fd传递的实现细节1. UNIX Domain Socket准备两个进程需要先建立UNIX domain socket连接。通常有两种方式方式一命名socket// Server端 (可能是exporter或专门的管理服务)intsocksocket(AF_UNIX,SOCK_STREAM,0);structsockaddr_unaddr;addr.sun_familyAF_UNIX;strcpy(addr.sun_path,/tmp/dma_buf_socket);bind(sock,(structsockaddr*)addr,sizeof(addr));listen(sock,5);intclientaccept(sock,NULL,NULL);// Client端intsocksocket(AF_UNIX,SOCK_STREAM,0);structsockaddr_unaddr;addr.sun_familyAF_UNIX;strcpy(addr.sun_path,/tmp/dma_buf_socket);connect(sock,(structsockaddr*)addr,sizeof(addr));方式二socketpair(适用于父子进程)intsv[2];socketpair(AF_UNIX,SOCK_STREAM,0,sv);// sv[0] 和 sv[1] 是一对连接的socket2. 发送端 (Exporter) 代码示例// 假设已经创建了 dma-buf 并获得了 fdintdmabuf_fddma_buf_fd(dmabuf,O_CLOEXEC);// 准备发送消息structmsghdrmsg{0};structioveciov[1];charbuf[1]{X};// 必须发送至少一个字节的数据iov[0].iov_basebuf;iov[0].iov_len1;msg.msg_ioviov;msg.msg_iovlen1;// 准备辅助数据这是关键union{charbuf[CMSG_SPACE(sizeof(int))];structcmsghdralign;}u;msg.msg_controlu.buf;msg.msg_controllensizeof(u.buf);structcmsghdr*cmsgCMSG_FIRSTHDR(msg);cmsg-cmsg_levelSOL_SOCKET;cmsg-cmsg_typeSCM_RIGHTS;// 表示传递文件描述符cmsg-cmsg_lenCMSG_LEN(sizeof(int));// 将 fd 复制到辅助数据中memcpy(CMSG_DATA(cmsg),dmabuf_fd,sizeof(int));// 发送if(sendmsg(socket_fd,msg,0)0){perror(sendmsg failed);return-1;}3. 接收端 (Importer) 代码示例// 准备接收消息structmsghdrmsg{0};structioveciov[1];charbuf[1];iov[0].iov_basebuf;iov[0].iov_len1;msg.msg_ioviov;msg.msg_iovlen1;// 准备接收辅助数据union{charbuf[CMSG_SPACE(sizeof(int))];structcmsghdralign;}u;msg.msg_controlu.buf;msg.msg_controllensizeof(u.buf);// 接收if(recvmsg(socket_fd,msg,0)0){perror(recvmsg failed);return-1;}// 提取文件描述符structcmsghdr*cmsgCMSG_FIRSTHDR(msg);if(cmsgNULL||cmsg-cmsg_type!SCM_RIGHTS){fprintf(stderr,No fd received\n);return-1;}intreceived_fd;memcpy(received_fd,CMSG_DATA(cmsg),sizeof(int));// 现在可以使用 received_fd 来访问 dma-buf 了structdma_buf*dmabufdma_buf_get(received_fd);3. 内核层面的处理当通过SCM_RIGHTS发送fd时内核做了以下关键操作发送端处理(scm_send-scm_fp_copy)检查发送进程是否有权访问该fd增加对应file结构的引用计数get_file()将file指针存储在socket缓冲区中接收端处理(scm_recv-scm_detach_fds)在接收进程的文件描述符表中分配新的fdget_unused_fd_flags()将file结构安装到新fd上fd_install()接收进程现在拥有指向同一file对象的新fd关键代码路径内核// net/core/scm.cint__scm_send(structsocket*sock,structmsghdr*msg,structscm_cookie*p){...if(cmsg-cmsg_typeSCM_RIGHTS){errscm_fp_copy(cmsg,p-fp);// 复制文件描述符...}...}voidscm_detach_fds(structmsghdr*msg,structscm_cookie*scm){...for(i0;ifdnum;i){intnew_fdget_unused_fd_flags(O_CLOEXEC);// 分配新fd...fd_install(new_fd,fp[i]);// 安装file到新fd...}...}4. 为什么需要这种机制安全性fd不能被猜测或伪造只有通过显式传递才能共享发送方必须有对该fd的访问权限正确的引用计数内核自动管理file对象的引用计数防止资源泄漏和悬空指针跨进程地址空间隔离每个进程有自己的fd表和地址空间通过内核中介实现安全共享灵活性支持任意类型的文件描述符dma-buf、eventfd、socket等可以一次传递多个fd5.实际应用场景场景1Wayland compositor 和 客户端// Wayland compositor (exporter)intdmabuf_fdcreate_dmabuf_for_scanout();wl_buffer_send_dmabuf_fd(client,dmabuf_fd);// 内部使用 sendmsg SCM_RIGHTS// Wayland client (importer)intreceived_fdwl_buffer_receive_dmabuf_fd();// 内部使用 recvmsg// 将 fd 传给 GPU 驱动做纹理导入场景2Android GraphicBuffer 共享// SurfaceFlinger (exporter)intion_fdion_alloc(...);// 或 dma_heap_alloc()android::Parcel parcel;parcel.writeDupFileDescriptor(ion_fd);// 内部通过 binder SCM_RIGHTSsend_parcel_to_app(parcel);// App (importer)intfdparcel.readFileDescriptor();// 映射或传给GPU使用场景3多媒体PipelineCamera - GPU - DisplayCamera驱动 (V4L2) │ ├─ dma_buf_export() → fd1 │ └── [UNIX socket SCM_RIGHTS] ── GPU进程 │ ├─ dma_buf_get(fd1) ├─ 渲染到另一个 dma-buf → fd2 │ └── [SCM_RIGHTS] ── Display进程 │ └─ dma_buf_get(fd2) drm_mode_addfb2(fd2)6. 注意事项fd的生命周期发送fd后发送方应该close(fd)自己的副本如果不再需要接收方负责close()接收到的fd内核会正确管理底层file对象的引用计数权限检查发送方必须对fd有访问权限SELinux/AppArmor 可能施加额外限制限制每次sendmsg可传递的fd数量有限制通常是SCM_MAX_FD 253socket缓冲区大小限制可能影响大量fd的传递错误处理如果接收方未能及时处理接收到的fd可能导致资源泄漏需要有超时和清理机制7. 内核视角的完整流程发送进程 内核 接收进程 │ │ │ ├─ sendmsg(fd5) │ │ │ │ │ │ │ └─────────────────├─ scm_send() │ │ │ └─ scm_fp_copy() │ │ │ ├─ fcheck(5) → file │ │ │ ├─ get_file(file) │ │ │ └─ 存储 file* │ │ │ │ │ ├─ socket buffer 中传递 │ │ │ │ │ │ [时间流逝] │ │ │ │ │ │─────────────── recvmsg() ├─ │ │ │ │ ├─ scm_detach_fds() │ │ │ ├─ get_unused_fd() → 7 │ │ │ └─ fd_install(7, file) │ │ │ │ │ │──────────────────────────├─ 得到 fd7 │ │ │ (指向同一file) │ │ │现在接收进程的fd 7和发送进程的fd 5指向内核中的同一个struct file对象而该file的private_data指向struct dma_buf从而实现了dma-buf的共享。8. 小结fd的传递是dma-buf跨进程共享的关键环节。通过UNIX domain socket的SCM_RIGHTS机制Exporter导出dma-buf为fd通过socket发送Importer接收fd在内核中获取到同一个dma-buf对象内核确保引用计数正确、访问安全这种设计优雅地解决了跨进程共享内核对象的问题是Linux IPC的重要组成部分不仅用于dma-buf也广泛应用于eventfd、pidfd、bpf fd等现代内核特性中。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询