当前位置: 技术问答>linux和unix
如何 删除所有的消息队列 (高分)
来源: 互联网 发布时间:2017-03-12
本文导语: 申请临时的消息队列后,如果程序不是正常退出,消息队列则会留在内核中,并一直累加. 当消息队列数大于配置支持的最大数时,则会出错.我如何才能清除掉那些无效了的消息队列(非手动)? 如:int Key = ms...
申请临时的消息队列后,如果程序不是正常退出,消息队列则会留在内核中,并一直累加.
当消息队列数大于配置支持的最大数时,则会出错.我如何才能清除掉那些无效了的消息队列(非手动)?
如:int Key = msgget(IPC_PRIVATE, IPC_CREAT|00666);
msgctl(__Key, IPC_RMID, NULL);
当消息队列数大于配置支持的最大数时,则会出错.我如何才能清除掉那些无效了的消息队列(非手动)?
如:int Key = msgget(IPC_PRIVATE, IPC_CREAT|00666);
msgctl(__Key, IPC_RMID, NULL);
|
可以用ipcrm彻底删除:
ipcrm `ipcs |grep username| grep "^m" |awk '{print "-m " $2}'`
ipcrm `ipcs |grep username|grep "^s" |awk '{print "-s " $2}'`
ipcrm `ipcs |grep username| grep "^m" |awk '{print "-m " $2}'`
ipcrm `ipcs |grep username|grep "^s" |awk '{print "-s " $2}'`
|
不要用ipc_private参数,用正常的ftok, 加msgget可以避免。
另外一种不可靠的方式是在进程退出前主动去msgctl加ipc_rmid去删除自己创建的消息队列
另外一种不可靠的方式是在进程退出前主动去msgctl加ipc_rmid去删除自己创建的消息队列
|
你可以用shell写一段脚本做查询及删除操作。
然后用system调用该脚本.
然后用system调用该脚本.
|
可以把你用msgget创建出来的key_t都记录起来(可以是记录到文件中,但是最好是记录到其它机器重启后清空的东东里面,比如一个已知key的消息队列,或者共享内存等),下次程序启动之后检查这些key,然后逐个删除。这样也避免了删除别人创建的消息队列
|
程序为什么会不正常退出呢?
程序不正常退出通常是因为有些信号的动作
用信号处理函数来抓取信号
当异常信号出现的时候捕获,然后跳到信号处理函数那里释放申请的消息队列,再exit进程
进程的退出都是因为信号的作用的
例如你发kill 这就是向进程发SIGKILL信号
如果发生段错误进程终止,也是因为向进程发了SIGSEGV信号的原因
相关问题请阅读Linux环境高级编程。
程序不正常退出通常是因为有些信号的动作
用信号处理函数来抓取信号
当异常信号出现的时候捕获,然后跳到信号处理函数那里释放申请的消息队列,再exit进程
进程的退出都是因为信号的作用的
例如你发kill 这就是向进程发SIGKILL信号
如果发生段错误进程终止,也是因为向进程发了SIGSEGV信号的原因
相关问题请阅读Linux环境高级编程。
|
正常开发程序必须要做信号处理的,这属于默认的规范了,我这有一个信号的处理函数,是linux系统下的
void set_sig()
{
struct sigaction act;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
act.sa_handler = sig_child_exit_handler;
sigaction(SIGCHLD, &act, NULL);
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
act.sa_handler = sig_exit_handler;
sigaction(SIGTERM, &act, NULL);
sigaction(SIGQUIT, &act, NULL);
sigaction(SIGILL, &act, NULL);
sigaction(SIGABRT, &act, NULL);
sigaction(SIGFPE, &act, NULL);
sigaction(SIGBUS, &act, NULL);
sigaction(SIGSEGV, &act, NULL);
}
其中sig_child_exit_handler和sig_exit_handler是你自定义的处理逻辑
|
对于IPC_PRIVATE方式创建的消息队列,每次msgget()应该都是一个新的key值
除非知道当时创建时返回的key,否则没有办法再次获取。
或者,可以通过ipcs命令查看,然后ipcrm删除
除非知道当时创建时返回的key,否则没有办法再次获取。
或者,可以通过ipcs命令查看,然后ipcrm删除
|
在程序中检查此key的attach值,如果为0则调用msgctl 将其删除即可。
|
拿分走人~~~~~~~~~(~ o ~)~zZ
|
拿分走人~~~~~~~~~(~ o ~)~zZ
|
拿分走人~~~~~~~~~(
|
先看看·····
|
|
来拿分的 ……
|
int msgctl(int msqid,int cmd,struct msqid_ds *buf);
返回:若成功则为0,出错则为-1
cmd参数指定对于由msqid规定的队列要执行的命令:
•IPC_STAT取此队列的msqid_ds结构,并将其存放在buf指向的结构中。
•IPC_SET按由buf指向的结构中的值,设置与此队列相关的结构中的下列四个字段:
msg_perm.uid、msg_perm.gid、msg_perm;mode和msg_qbytes。此命令只能由下列两种进程执
行:一种是其有效用户ID等于msg_perm.cuid或msg_perm.uid;另一种是具有超级用户特权的进
程。只有超级用户才能增加msg_qbytes的值
•IPC_RMID从系统中删除该消息队列以及仍在该队列上的所有数据。这种删除立即生效。
仍在使用这一消息队列的其他进程在它们下一次试图对此队列进行操作时,将出错返回
EIDRM。此命令只能由下列两种进程执行:一种是其有效用户ID等于msg_perm.cuid或
msg_perm.uid;另一种是具有超级用户特权的进程。
这三条命令(IPC_STAT、IPC_SET和IPC_RMID)也可用于信号量和共享存储。
返回:若成功则为0,出错则为-1
cmd参数指定对于由msqid规定的队列要执行的命令:
•IPC_STAT取此队列的msqid_ds结构,并将其存放在buf指向的结构中。
•IPC_SET按由buf指向的结构中的值,设置与此队列相关的结构中的下列四个字段:
msg_perm.uid、msg_perm.gid、msg_perm;mode和msg_qbytes。此命令只能由下列两种进程执
行:一种是其有效用户ID等于msg_perm.cuid或msg_perm.uid;另一种是具有超级用户特权的进
程。只有超级用户才能增加msg_qbytes的值
•IPC_RMID从系统中删除该消息队列以及仍在该队列上的所有数据。这种删除立即生效。
仍在使用这一消息队列的其他进程在它们下一次试图对此队列进行操作时,将出错返回
EIDRM。此命令只能由下列两种进程执行:一种是其有效用户ID等于msg_perm.cuid或
msg_perm.uid;另一种是具有超级用户特权的进程。
这三条命令(IPC_STAT、IPC_SET和IPC_RMID)也可用于信号量和共享存储。
|
用IPC_RMID
|
我的建议, 不使用, unix域套接字, 帮你解决各种IPC难题
|
pure JF
|
拿分走人~~~
|
个人觉得直接调system就OK了
|
我现在也遇到这样的问题,问一下,当产生消息队列的进程退出后,接收消息的进程没有接收完的消息队列中的消息会不会出现与传输的不一致?