是否可以对TCP客户端的文件描述符执行mmap操作?
问题解答
对TCP客户端套接字fd执行mmap操作本身就无法实现。
原因说明
mmap的本质是将进程的虚拟地址空间映射到对应文件描述符指向的底层对象的物理存储区域,要求底层对象支持按固定偏移随机寻址,普通文件、块设备、共享内存段都符合这个要求。
而TCP套接字是流式协议的抽象,没有固定的存储偏移和持久化的可寻址缓冲区,内核没有为TCP套接字实现mmap所需的相关操作回调,所以调用必然返回失败。你可以打印errno确认错误类型,通常返回的是ENODEV(不支持该操作的设备)错误码。
替代方案(实现零拷贝收发需求)
你代码中期望的「往内存地址写数据就自动发送给客户端」的零拷贝效果,可以用以下成熟方案实现:
- 使用
sendfile系统调用:如果要发送的数据存储在普通文件中,直接调用sendfile可以让内核直接把页缓存中的文件数据拷贝到套接字发送缓冲区,全程不需要经过用户态内存拷贝,性能和你期望的mmap效果接近。 - 使用
splice系统调用:支持在内核空间直接完成两个文件描述符之间的数据传输,不需要拷贝到用户态,支持管道、套接字等非普通文件的fd之间的数据搬运。 - 高版本Linux内核可以使用带
MSG_ZEROCOPY标志的send调用:发送时内核会直接映射用户态内存页到内核空间,不需要做内存拷贝,完成发送后再通知用户态回收内存。
补充:只有极少数特殊类型的套接字支持mmap操作,比如用于抓包的
AF_PACKET原始套接字,内核实现了对应的环形缓冲区映射逻辑,可用于高性能数据包收发,但通用TCP流式套接字无相关支持。
内容的提问来源于stack exchange,提问作者T0maas
相关产品推荐
相关产品推荐

