在类UNIX系统中删除所有SYSTEM V共享内存和信号量

39

在类UNIX系统,例如Ubuntu中,我该如何使用单个命令删除所有未使用的信号量和共享内存?


4
这个问题确实需要解释"为什么"。 - Anon.
3
通常来说,对于家庭作业,你知道什么?你尝试了什么?请简明扼要地表达。 - Cascabel
11
各位,表现出一些理解吧。我现在也有一个类似的问题。在注册一些System V共享内存后,需要一段时间后进行清理,谁想要多次调用"ipcrm"命令并先解析"ipcs"命令呢?编程就是懒惰。而Stack Overflow是专门为那些特别懒惰的程序员准备的,不是吗? - Christoph Strasen
所有的解决方案都没有考虑POSIX信号量(命名和未命名)而是只关注XSI aka SystemV信号量。这并不是一个大惊小怪的事情,因为问题本身质量较差。然而,StackExchange社区通常做得更好 - 我很惊讶。 - stefanct
如果你这样做,可能会破坏你正在运行的系统。实际上并没有这种可能性,只有 ipcrm(1) 命令允许你逐个删除其他程序创建的 ipc 资源。 - Luis Colorado
显示剩余2条评论
11个回答

67

在这里,保存并尝试使用此脚本(kill_ipcs.sh)在您的shell上:

#!/bin/bash

ME=`whoami`

IPCS_S=`ipcs -s | egrep "0x[0-9a-f]+ [0-9]+" | grep $ME | cut -f2 -d" "`
IPCS_M=`ipcs -m | egrep "0x[0-9a-f]+ [0-9]+" | grep $ME | cut -f2 -d" "`
IPCS_Q=`ipcs -q | egrep "0x[0-9a-f]+ [0-9]+" | grep $ME | cut -f2 -d" "`


for id in $IPCS_M; do
  ipcrm -m $id;
done

for id in $IPCS_S; do
  ipcrm -s $id;
done

for id in $IPCS_Q; do
  ipcrm -q $id;
done

我们在大学学生服务器上运行 IPCS 程序时会使用它。有些人不会经常进行清理,所以...需要用到它 :P


1
这会删除所有的共享内存,即使nattach不为零吗?那这个呢?:ipcs -m | egrep "0x[0-9a-f]+ [0-9]+"|awk '{ if ($6 == 0) { print $2; } }'|xargs -n1 ipcrm -m - Ben
1
我会用xargs替换for循环:echo $IPCS_S | xargs -n1 ipcrm -s - user1202136
对我来说,上面的正则表达式不起作用。以下内容可以:IPCS_Q=ipcs -q | egrep -i "0x[0-9a-f]+.*[0-9]+" | grep $ME | cut -f2 -d" "` - brainydexter
在 AIx 系统上也不起作用... 对命令进行了一些微小的调整就解决了问题! ipcs -s |grep $ME | awk '{print $2}' awk 命令解决了定位问题。 - LeoPucciBr

11

这在我的 Mac OS 上可行:

for n in `ipcs -b -m | egrep ^m | awk '{ print $2; }'`; do ipcrm -m $n; done

10
#!/bin/bash
ipcs -m | grep `whoami` | awk '{ print $2 }' | xargs -n1 ipcrm -m
ipcs -s | grep `whoami` | awk '{ print $2 }' | xargs -n1 ipcrm -s
ipcs -q | grep `whoami` | awk '{ print $2 }' | xargs -n1 ipcrm -q

这是一个很好的答案,它帮助我删除了键值为0x0的队列(使用ipcrm -Q选项无法删除)。 - Oleg Oleg

10
ipcs -s | grep $USERNAME | perl -e 'while (<STDIN>) { @a=split(/\s+/); print `ipcrm sem $a[1]`}'

或者
ipcs -s | grep $USERNAME | awk ' { print $2 } ' | xargs ipcrm sem

将$USERNAME更改为实际的用户名。


7

我不知道如何一次性删除所有内容,但是您可以使用 ipcs 列出资源,然后使用循环和 ipcrm 删除。这应该可以解决问题,但需要一些工作。我记得在课堂上曾经成功实现过。


3
我们知道他是否正在使用 SysV ipc 而不是 POSIX 吗? - Duck
@Duck 我们知道他正在使用Ubuntu,我在Ubuntu上检查了这些命令。 - MBO
5
没问题,但请注意,我只能翻译您提供的文本。 正确,但是ipcs仅适用于SysV IPC对象。如果他正在使用posix版本,它们将显示在/dev/shm中,他可以通过rm命令删除它们。 - Duck

2

1行代码完成所有操作

对于消息队列

ipcs -q | sed "$ d; 1,2d" |  awk '{ print "Removing " $2; system("ipcrm -q " $2) }'

ipcs -q会给出消息队列的记录。

sed "$ d; 1,2d "将删除最后一个空行("$ d")和前两个标题行("1,2d")。

awk将完成剩下的工作,即根据第二列的值(因为$2)使用命令"ipcrm -q"打印并删除。


2

使用以下命令检查是否有需要删除的内容:

ipcs -a | grep `whoami`

在Linux中,可以通过以下命令删除它们:

ipcs | nawk -v u=`whoami` '/Shared/,/^$/{ if($6==0&&$3==u) print "ipcrm shm",$2,";"}/Semaphore/,/^$/{ if($3==u) print "ipcrm sem",$2,";"}' | /bin/sh

对于Sun而言,应该是这样的:
ipcs -a | nawk -v u=`whoami` '$5==u &&(($1=="m" && $9==0)||($1=="s")){print "ipcrm -"$1,$2,";"}' | /bin/sh

由di.uoa.gr提供

再次检查是否一切正常

删除您的sem/shared mem - 假设您是一个没有管理员权限的工作站用户


1
这是我在FreeBSD中的做法:
#!/usr/local/bin/bash
for i in $(ipcs -a | grep "^s" | awk '{ print $2 }');
do
        echo "ipcrm -s $i"
        ipcrm -s $i
done
(注意:保留html标签)

0
除了bvamos的回答之外,根据文档,使用sem已被弃用:

名称ipcrm - 删除消息队列、信号量集或共享内存ID SYNOPSIS ipcrm [ -M key | -m id | -Q key | -q id | -S key | -s id ] ... 弃用的用法

ipcrm [ shm | msg | sem ] id ...

删除共享内存

使用ipcrm -m通过id删除共享内存段。

#!/bin/bash

set IPCS_M = ipcs -m | egrep "0x[0-9a-f]+ [0-9]+" | grep $USERNAME | cut -f2 -d" "

for id in $IPCS_M; do
  ipcrm -m $id;
done

或者使用 ipcrm -M 命令按照键值删除共享内存段。

#!/bin/bash

set IPCS_M = ipcs -m | egrep "0x[0-9a-f]+ [0-9]+" | grep $USERNAME | cut -f1 -d" "

for id in $IPCS_M; do
  ipcrm -M $id;
done

移除消息队列

使用 ipcrm -q 命令通过 ID 移除共享内存段。

#!/bin/bash

set IPCS_Q = ipcs -q | egrep "0x[0-9a-f]+ [0-9]+" | grep $USERNAME | cut -f2 -d" "

for id in $IPCS_Q; do
  ipcrm -q $id;
done

或者使用ipcrm -Q通过键值删除共享内存段

#!/bin/bash

set IPCS_Q = ipcs -q | egrep "0x[0-9a-f]+ [0-9]+" | grep $USERNAME | cut -f1 -d" "

for id in $IPCS_Q; do
  ipcrm -Q $id;
done

删除信号量

使用ipcrm -s命令通过id删除一个信号量段

#!/bin/bash

set IPCS_S = ipcs -s | egrep "0x[0-9a-f]+ [0-9]+" | grep $USERNAME | cut -f2 -d" "

for id in $IPCS_S; do
  ipcrm -s $id;
done

或者使用ipcrm -S通过键值删除信号量段

#!/bin/bash

set IPCS_S = ipcs -s | egrep "0x[0-9a-f]+ [0-9]+" | grep $USERNAME | cut -f1 -d" "

for id in $IPCS_S; do
  ipcrm -S $id;
done

0

既然你提到你正在使用NFS系统,那么你是否可以访问那些信号量和共享内存?我认为你误解了它们的含义,它们是一种API代码,使进程能够相互通信,信号量是防止竞态条件和线程相互通信的解决方案,简单来说,它们不会在任何文件系统上留下任何残留物。

除非你正在使用套接字或管道?你是否有必要的权限将它们移除,在NFS系统上它们的存在意义是什么?

希望这可以帮助你, 最好的祝愿, 汤姆。


不,这对我没有帮助...我只是在为一个虚假的NFS做一个简单的C项目...我知道什么是信号量和共享内存...我只想对我的代码进行一些测试,并且需要一键删除所有共享数据。 - simone
@simone:你应该在最初的问题中说明“假NFS”,并指出你理解信号量和共享内存...但仍不清楚“共享数据”是什么? - t0mm13b
同时,您可以包含代码以展示您的作业,让我们SO社区的成员们看到。这也会很有帮助。 - t0mm13b

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接