ipcs ipcrm 信号量(命令)+ 共享内存函数shmget、shmat、shmdt、shmctl

 unix/linux下的共享内存、信号量、队列信息管理,在unix/linux下,经常有因为共享内存、信号量,队列等共享信息没有干净地清楚而引起一些问题。

1、ipcs 和 ipcrm 命令实例

查看共享信息的内存的命令是ipcs [-m|-s|-q]。

默认会列出共享内存、信号量,队列信息,-m列出共享内存,-s列出共享信号量,-q列出共享队列

清除命令是ipcrm [-m|-s|-q] id。

ipcrm可用来删除对应的共享内存段、信号量、消息队列;ipcrm本身只能实现单个资源的删除,利用以下命令可实现批量删除(zhangsj版权所有,呵呵):

1.ipcs -s|grep 用户名|cut -d" " -f2|xargs -n1 ipcrm -s
2.ipcs -s|awk '/用户名/{print $2}'|xargs -n1 ipcrm -s
3.ipcs -s|awk '/用户名/{system("ipcrm -s "$2)}'
4.for i in echo `ipcs|grep 用户名|cut -d" " -f2`; do ipcrm -s $i; done

-m 删除共享内存,-s删除共享信号量,-q删除共享队列。

更多参考:http://bbs.chinaunix.net/thread-1620394-1-1.html

[oracle@trade_as02 ~]$ ipcs -a
 
------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status     
0x30024289 32768      futures   777        528384     1                      
0xca2fd414 491521     oracle    640        1730150400 16                     
 
------ Semaphore Arrays --------
key        semid      owner      perms      nsems    
0x00028009 0          futures   666        1        
0x0002800c 32769      futures   666        1        
0x30024003 262146     futures   777        3        
0x3002428a 294915     futures   777        2        
0x3002428b 327684     futures   777        2        
0x3002428c 360453     futures   777        2        
0x3002428d 393222     futures   777        2        
0x3002428e 425991     futures   777        2        
0x52dff7d0 3964936    oracle    640        151      
0x52dff7d1 3997705    oracle    640        151      
0x52dff7d2 4030474    oracle    640        151      
0x52dff7d3 4063243    oracle    640        151      
0x52dff7d4 4096012    oracle    640        151      
 
------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages

共享内存段有时不能马上删除,需使用这个内存段的所有进程向OS发送detach命令时才有释放,此时可以考虑删除进程使用的信号量,帮助释放共享内存段

 

 

2、关键知识


信号量:信号量又称为信号灯,它是用来协调不同进程间的数据对象的,而最主要的应用是共享内存方式的进程间通信。本质上,信号量是一个计数器,它用来记录对某个资源(如共享内存)的存取状况;共享内存是运行在同一台机器上的间通信最快的方式,因为数据不需要在不同的进程间复制。通常由一个进程创建一块共享内存区,其余进程对这块内存区进行读写。在Linux系统下
,常用的方式是通过shmXXX函数族来实现利用共享内存进行存储的。 如Shmget,类似于 malloc函数

3、共享内存函数

由shmget、shmat、shmdt、shmctl四个函数组成。下面的表格列出了这四个函数的函数原型及其具体说明。

shmget函数原型


shmget(得到一个共享内存标识符或创建一个共享内存对象)


所需头文件


#include <sys/ipc.h>

#include <sys/shm.h>


函数说明


得到一个共享内存标识符或创建一个共享内存对象并返回共享内存标识符


函数原型


int shmget(key_t key, size_t size, int shmflg)


函数传入值


key


0(IPC_PRIVATE):会建立新共享内存对象


大于0的32位整数:视参数shmflg来确定操作。通常要求此值来源于ftok返回的IPC键值


size


大于0的整数:新建的共享内存大小,以字节为单位


0:只获取共享内存时指定为0


shmflg


0:取共享内存标识符,若不存在则函数会报错


IPC_CREAT:当shmflg&IPC_CREAT为真时,如果内核中不存在键值与key相等的共享内存,则新建一个共享内存;如果存在这样的共享内存,返回此共享内存的标识符


IPC_CREAT|IPC_EXCL:如果内核中不存在键值与key相等的共享内存,则新建一个消息队列;如果存在这样的共享内存则报错


函数返回值


成功:返回共享内存的标识符


出错:-1,错误原因存于error中


附加说明


上述shmflg参数为模式标志参数,使用时需要与IPC对象存取权限(如0600)进行|运算来确定信号量集的存取权限


错误代码


EINVAL:参数size小于SHMMIN或大于SHMMAX

EEXIST:预建立key所指的共享内存,但已经存在

EIDRM:参数key所指的共享内存已经删除

ENOSPC:超过了系统允许建立的共享内存的最大值(SHMALL)

ENOENT:参数key所指的共享内存不存在,而参数shmflg未设IPC_CREAT位

EACCES:没有权限

ENOMEM:核心内存不足

在Linux环境中,对开始申请的共享内存空间进行了初始化,初始值为0x00。

如果用shmget创建了一个新的消息队列对象时,则shmid_ds结构成员变量的值设置如下:

Ÿ        shm_lpid、shm_nattach、shm_atime、shm_dtime设置为0。

Ÿ        msg_ctime设置为当前时间。

Ÿ        shm_segsz设成创建共享内存的大小。

Ÿ        shmflg的读写权限放在shm_perm.mode中。

Ÿ        shm_perm结构的uid和cuid成员被设置成当前进程的有效用户ID,gid和cuid成员被设置成当前进程的有效组ID。

shmat函数原型


shmat(把共享内存区对象映射到调用进程的地址空间)


所需头文件


#include <sys/types.h>

#include <sys/shm.h>


函数说明


连接共享内存标识符为shmid的共享内存,连接成功后把共享内存区对象映射到调用进程的地址空间,随后可像本地空间一样访问


函数原型


void *shmat(int shmid, const void *shmaddr, int shmflg)


函数传入值


msqid


共享内存标识符


shmaddr


指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核自己决定一个合适的地址位置


shmflg


SHM_RDONLY:为只读模式,其他为读写模式


函数返回值


成功:附加好的共享内存地址


出错:-1,错误原因存于error中


附加说明


fork后子进程继承已连接的共享内存地址。exec后该子进程与已连接的共享内存地址自动脱离(detach)。进程结束后,已连接的共享内存地址会自动脱离(detach)


错误代码


EACCES:无权限以指定方式连接共享内存

EINVAL:无效的参数shmid或shmaddr

ENOMEM:核心内存不足

 shmdt函数原型


shmat(断开共享内存连接)


所需头文件


#include <sys/types.h>

#include <sys/shm.h>


函数说明


与shmat函数相反,是用来断开与共享内存附加点的地址,禁止本进程访问此片共享内存


函数原型


int shmdt(const void *shmaddr)


函数传入值


shmaddr:连接的共享内存的起始地址


函数返回值


成功:0


出错:-1,错误原因存于error中


附加说明


本函数调用并不删除所指定的共享内存区,而只是将先前用shmat函数连接(attach)好的共享内存脱离(detach)目前的进程


错误代码


EINVAL:无效的参数shmaddr

 shmctl函数原型


shmctl(共享内存管理)


所需头文件


#include <sys/types.h>

#include <sys/shm.h>


函数说明


完成对共享内存的控制


函数原型


int shmctl(int shmid, int cmd, struct shmid_ds *buf)


函数传入值


msqid


共享内存标识符


cmd


IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中


IPC_SET:改变共享内存的状态,把buf所指的shmid_ds结构中的uid、gid、mode复制到共享内存的shmid_ds结构内


IPC_RMID:删除这片共享内存


buf


共享内存管理结构体。具体说明参见共享内存内核结构定义部分


函数返回值


成功:0


出错:-1,错误原因存于error中


错误代码


EACCESS:参数cmd为IPC_STAT,确无权限读取该共享内存

EFAULT:参数buf指向无效的内存地址

EIDRM:标识符为msqid的共享内存已被删除

EINVAL:无效的参数cmd或shmid

EPERM:参数cmd为IPC_SET或IPC_RMID,却无足够的权限执行

时间: 2024-09-22 11:04:50

ipcs ipcrm 信号量(命令)+ 共享内存函数shmget、shmat、shmdt、shmctl的相关文章

ipcs与Linux共享内存的示例

一.共享内存相关知识 所谓共享内存,就是多个进程间共同地使用同一段物理内存空间,它是通过将同一段物理内存映射到不同进程的 虚拟空间来实现的.由于映射到不同进程的虚拟空间中,不同进程可以直接使用,不需要像消息队列那样进行复制,所以共享内存的效率很高.共享内存可以通过mmap()映射普通文件机制来实现,也可以System V共享内存机制来实现,System V是通过映射特殊文件系统shm中的文件实现进程间的共享内存通信,也就是说每个共享内存区域对应特殊文件系统shm中的一个文件. 二.共享内存原理

linux网络编程之System V 共享内存和系列函数

跟消息队列一样,共享内存也有自己的数据结构,如下: struct shmid_ds { struct ipc_perm shm_perm;    /* Ownership and permissions */ size_t     shm_segsz;   /* Size of segment (bytes) */ time_t     shm_atime;   /* Last attach time */ time_t     shm_dtime;   /* Last detach time

c#读写共享内存操作函数封装

原文 c#读写共享内存操作函数封装   c#共享内存操作相对c++共享内存操作来说原理是一样,但是c#会显得有点复杂.         现把昨天封装的读写共享内存封装的函数记录下来,一方面希望给需要这块的有点帮助,另一方面则是做个备份吧.   [csharp] view plaincopy /// <summary>           /// 写共享内存           /// </summary>           /// <param name="str

进程间通信之-共享内存Shared Memory--linux内核剖析(十一)

共享内存 共享内存是进程间通信中最简单的方式之一. 共享内存是系统出于多个进程之间通讯的考虑,而预留的的一块内存区. 共享内存允许两个或更多进程访问同一块内存,就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针.当一个进程改变了这块地址中的内容的时候,其它进程都会察觉到这个更改. 关于共享内存 当一个程序加载进内存后,它就被分成叫作页的块. 通信将存在内存的两个页之间或者两个独立的进程之间. 总之,当一个程序想和另外一个程序通信的时候,那内存将会为这两个程序生成一块公共的

unix/linux共享内存应用与陷阱

共享内存是系统出于多个进程之间通讯的考虑,而预留的的一块内存区.在/proc/sys/kernel/目录下,记录着共享内存的一些限制,如一个共享内存区的最大字节数shmmax,系统范围内最大共享内存区标识符数shmmni等,可以手工对其调整,但不推荐这样做. 一.应用 共享内存的使用,主要有以下几个API:ftok().shmget().shmat().shmdt()及shmctl(). 1)用ftok()函数获得一个ID号. 应用说明: 在IPC中,我们经常用用key_t的值来创建或者打开信号

linux共享内存

共享内存共享内存是进程间通信中最简单的方式之一.共享内存允许两个或更多进程访问同一块内存,就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针.当一个进程改变了这块地址中的内容的时候,其它进程都会察觉到这个更改. 快速本地通信 因为所有进程共享同一块内存,共享内存在各种进程间通信方式中具有最高的效率.访问共享内存区域和访问进程独有的内存区域一样快,并不需要通过系统调用或者其它需要切入内核的过程来完成.同时它也避免了对数据的各种不必要的复制. 因为系统内核没有对访问共享内存进

单台服务器的PHP进程之间实现共享内存的方法_php技巧

开发人员要想使php进程实现共享内存的读写,首先就要支持IPC函数,即php编译安装时指定:--enable-shmop  与--enable-sysvsem 两个选项. IPC (Inter-process communication) 是一个Unix标准机制,它提供了使得在同一台主机不同进程之间可以互相的方法.基本的IPC处理机制有3种:它们分别是共享内存.信号量和消息队列.本文中我们主要讨论共享内存和信号量的使用. 在不同的处理进程之间使用共享内存是一个实现不同进程之间相互的好方法.如果你

Linux共享内存使用常见陷阱与分析

所谓共享内存就是使得多个进程可以访问同一块内存空间,是最快的可用IPC形式.是针对其他通信机制运行效率较低而设计的.往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥.其他进程能把同一段共享内存段"连接到"他们自己的地址空间里去.所有进程都能访问共享内存中的地址.如果一个进程向这段共享内存写了数据,所做的改动会即时被有访问同一段共享内存的其他进程看到.共享内存的使用大大降低了在大规模数据处理过程中内存的消耗,但是共享内存的使用中有很多的陷阱,一不注意就很容易导致程序崩溃.

Linux环境进程间通信共享内存

由于多个进程共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以. 采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝.对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只拷贝两次数据[1]:一次从输入文件到共享内存区,另一次从共享内存区到输出文件.实际上,进程之间在共享内存时,并不总是读写少量数据后就解除映射,有新的通信时,再重新建立共享内存区域.而是保持共享区域,直到通信完毕为止,这样,数据内容一直保存