如何利用小游戏解决方案提升企业在金融和物联网领域的运营效率
602
2022-09-20
(unix domain socket)使用udp发送>=128K的消息会报ENOBUFS的错误
1、Unix domain socket简介
unix域协议并不是一个实际的协议族,而是在单个主机上执行客户/服务器通信的一种方法,所用API于在不同主机上执行客户/服务器通信所有的API(套接字API,如AF_INET、AF_INET6等类型的API)相同。unix域协议可以视为是进程之间本地通信IPC的一种。
unix域提供两类套接口:字节流套接口(类似TCP)和数据报套接口(类似UDP)。使用Unix域套接口的理由有三:
Unix域套接口往往比位于同一主机的TCP套接口快出一倍。Unix域套接口可用于在同一主机上的不同进程之间传递描述字。Unix域套接口把客户的凭证(用户ID和用户组ID)提供给服务器,从而实现能够提供额外的安全检查措施。
Unix域中用域标识客户和服务器的协议地址是普通文件系统中的路径名(类比:IPv4协议的地址由一个32位地址和一个16位端口号构成,IPv6协议的地址由一个128位地址和16位端口号构成。)。
2、问题描述
简单介绍了Unix域套接口之后,进入主题——描述我碰到的问题。由于unix域套接口用于本机间进程通信比网络套接口效率高,因为它是不经过协议栈的!在项目中选择了unix域的数据报套接口。在使用过程中碰到了如下,问题:发送<128K的消息时,客户、进程可以正常收发消息;发送>=128K的消息时,发送端(sendto)返回ENOBUFS的错误。
服务器的代码如下:
#include
客户端的代码如下:
#include
3、可能碰到的另外一个问题
如果你没有设置足够大的发送缓冲区大小,你很有可能碰到EMSGSIZE的错误!因为应用程序写了一个大于套机口发送缓冲区大小的数据报,内核报EMSGSIZE错误。如下图:
(注意:UDP套接口有发送缓冲区的大小,并且可以通过SO_SNDBUF套接口选项修改。不过它仅仅是写到套接口的UDP数据报的大小,因为UDP是不可靠的,它不必保存应用进程的数据拷贝,因此无需一个真正的发送缓冲区。)上面的代码已经设置了足够大的发送缓冲区大小。
4、我的尝试
在sendto发送>=128K大小的消息时,返回ENOBUFS错误。
5、最终原因及解决办法(都是内核惹得祸!!)
至此,我实在没有办法了,不知道如何解决!但是从错误ENOBUFS的说明:
ENOBUFS means there is no sufficient memory available and the system(kernel) can not allocate any more. Application will usually retry the operation when it detects this error from a system call since it indicates there is a transient resource shortage. It is the Operating system that refuses the resource request from the listener. The virtual memory allocation routine of the OS will determine if a swap can be made to disk of a real memory segment thereby allowing the listener access to some more real memory.
可以看出一些端倪,这肯定跟内存分配有关!而且限制在分配128K就失败!利用Socket进行进程间的通信,需要经过Linux内核:进程1将数据写到内核,进程2从内核读取数据。内核必须申请一个空间来存放数据包!实际上,socket发送数据包时,需要从slab中申请一块cache存放数据包。
在2.6.21内核中(这就是我们公司服务器的内核版本),slab分配器最大支持的size为128K(详情可见/proc/slabinfo)。在2.6.31内核中,slab分配器最大支持的size大小为32M。
所以2.6.21内核上,发送大于128K的数据包时,Kmalloc()会失败,并返回no buffer的错误。建议:对于本地进程通信,可以使用其它的IPC方式,进行数据通信,如shm、pipe等。
找出了原因,可以采用以下方式来解决该问题:
升级内核,或修改内核的这个限制。改用unix 域udp套接口为unix域tcp套接口(最终我们采用的方式)。改用其它的IPC方式(这个涉及到太多的修改,故我们放弃使用)。
附/proc/slabinfo 信息:size-131072即128K的限制!
。。。。。。 size-131072(DMA) 0 0 131072 1 32 : tunables 8 4 0 : slabdata 0 0 0 size-131072 0 0 131072 1 32 : tunables 8 4 0 : slabdata 0 0 0 size-65536(DMA) 0 0 65536 1 16 : tunables 8 4 0 : slabdata 0 0 0 size-65536 0 0 65536 1 16 : tunables 8 4 0 : slabdata 0 0 0 size-32768(DMA) 0 0 32768 1 8 : tunables 8 4 0 : slabdata 0 0 0 size-32768 0 0 32768 1 8 : tunables 8 4 0 : slabdata 0 0 0 size-16384(DMA) 0 0 16384 1 4 : tunables 8 4 0 : slabdata 0 0 0 size-16384 0 0 16384 1 4 : tunables 8 4 0 : slabdata 0 0 0 size-8192(DMA) 0 0 8192 1 2 : tunables 8 4 0 : slabdata 0 0 0 size-8192 0 0 8192 1 2 : tunables 8 4 0 : slabdata 0 0 0 size-4096(DMA) 0 0 4096 1 1 : tunables 24 12 0 : slabdata 0 0 0 size-4096 4 4 4096 1 1 : tunables 24 12 0 : slabdata 4 4 0 size-2048(DMA) 0 0 2048 2 1 : tunables 24 12 0 : slabdata 0 0 0 size-2048 12 14 2048 2 1 : tunables 24 12 0 : slabdata 7 7 0 size-1024(DMA) 0 0 1024 4 1 : tunables 54 27 0 : slabdata 0 0 0 size-1024 11 12 1024 4 1 : tunables 54 27 0 : slabdata 3 3 0 size-512(DMA) 0 0 512 8 1 : tunables 54 27 0 : slabdata 0 0 0 size-512 208 208 512 8 1 : tunables 54 27 0 : slabdata 26 26 0 size-256(DMA) 0 0 256 15 1 : tunables 120 60 0 : slabdata 0 0 0 size-256 75 75 256 15 1 : tunables 120 60 0 : slabdata 5 5 0 size-192(DMA) 0 0 192 20 1 : tunables 120 60 0 : slabdata 0 0 0 size-192 40 40 192 20 1 : tunables 120 60 0 : slabdata 2 2 0 size-128(DMA) 0 0 128 30 1 : tunables 120 60 0 : slabdata 0 0 0 size-128 86 90 128 30 1 : tunables 120 60 0 : slabdata 3 3 0 size-96(DMA) 0 0 96 40 1 : tunables 120 60 0 : slabdata 0 0 0 size-96 388 400 96 40 1 : tunables 120 60 0 : slabdata 10 10 0 size-64(DMA) 0 0 64 59 1 : tunables 120 60 0 : slabdata 0 0 0 size-32(DMA) 0 0 32 113 1 : tunables 120 60 0 : slabdata 0 0 0 size-64 451 472 64 59 1 : tunables 120 60 0 : slabdata 8 8 0 size-32 871 904 32 113 1 : tunables 120 60 0 : slabdata 8 8 0 。。。。。。
我在Ubuntu 10.10上测试,不会报ENOBUFS的错误。内核版本为:
/proc/slabinfo的信息如下,跟上面的有些差异:
kmalloc的最大限制是8192K,故我们运行上述程序没有问题!
原来都是内核惹得祸阿,害我困惑那么久!!!baidu和google都没有找到原因,因此分享此文,以警惕后者。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~