后台程序使用SystemV消息队列遇到的资源泄漏问题

114 篇文章 1 订阅

2014-12-11 wcdj

后台程序使用SystemV消息队列遇到的资源泄漏问题

目录

0 问题背景...1

1 原因分析...1

2解决方法...2

 

0 问题背景

后台某程序在使用SystemV消息队列进行IPC通信,一段时间后发现部署此程序机器的消息队列资源被耗尽了(可以查看/proc/sys/kernel/msgmni),从而导致进程创建新的消息队列返回ENOSPC错误。

 

注释

ENOSPC A message queue has to be created but the system limit for the maximum number of message queues (MSGMNI) would be exceeded.

 

1 原因分析

通过ipcs –q命令可以看到本机存在很多键值为0x00000000的消息队列。受到之前共享内存nattch(the number of currently attached processes)思维的影响,以为此问题是消息队列创建完成后被ipcrm删除,且当前使用消息队列的进程没有退出导致的(实际上,消息队列被ipcrm后会立刻删除,进程在下次使用时就会报错)。后来把所有进程都干掉了,发现问题依旧。

再查看下man msgget的解释,找到了问题原因。

 

A message queue identifier, associatedmessage queue, and data structure (see <sys/msg.h>), shall be created forthe argument key if one of the following is true:

       * The argument key is equal to IPC_PRIVATE.

       * The argument key does not already have a message queue identifier associatedwith it, and (msgflg & IPC_CREAT) is non-zero.

 

问题程序会从XML配置文件中读取两个key1和key2值并分别创建消息队列,但是配置文件中少指定了一个key2从而导致程序在调用msgget创建消息队列的key为0,即man中所说的IPC_PRIVATE。而程序本意是使用一个显式固定的key进行IPC通信的,且此消息队列创建后程序不会主动将其删除,从而导致了前文所描述的问题。对于IPC_PRIVATE而言,通常的用法是在两个相关的父子进程间通信使用的,并且在使用后会通过msgid调用msgctl将消息队列从系统中删除。

 

find /usr/include -name "*.h" |xargs grep "IPC_PRIVATE"

./usr/include/bits/ipc.h:#defineIPC_PRIVATE    ((__key_t) 0)   /* Private key.  */

./usr/include/linux/ipc.h:#defineIPC_PRIVATE ((__kernel_key_t) 0) 

 

2解决方法

(1) 在配置文件里将缺失的key分配一个非零且合法的键值;
(2) 将程序服务停止;
(3) 清理泄漏不用的0x00000000 key;
ipcs -q | grep program | grep "0x00000000" | awk '{print $2}' | while read f;do ipcrm -q $f;done
(4) 将程序服务拉起;



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值