概要
共享的内存段是用户内存的一部分。每一个进程都有一个指向此内存段的指针。依靠访问权限的设置,所有进程都可以读取这一块空间中的数据。因此进程间的资源是共享的,而不是复制来复制去的。共享内存段对于进程而言,就类似于共享变量对于线程一样。
API
函数原型 | int shmget(key_t key, size_t size, int shmflg); |
头文件 | #include<sys/ipc.h> #include<sys/shm.h> |
描述 | 创建共享内存段。如果该内存段存在,函数找到它的位置。如果不存在,则创建此共享内存段。 |
参数说明 | key标识共享内存的键值: 0/IPC_PRIVATE。 当key的取值为IPC_PRIVATE,则函数shmget()将创建一块新的共享内存;如果key的取值为0,而参数shmflg中设置了IPC_PRIVATE这个标志,则同样将创建一块新的共享内存。 |
size(单位byte)是要建立共享内存的长度。所有的内存分配操作都是以页为单位的。所以如果一段进程只申请一块只有一个字节的内存,内存也会分配整整一页(在i386机器中一页的缺省大小PACE_SIZE=4096字节)这样,新创建的共享内存的大小实际上是从size这个参数调整而来的页面大小。即如果size为1至4096,则实际申请到的共享内存大小为4K(一页);4097到8192,则实际申请到的共享内存大小为8K(两页),依此类推。 | |
shmflg主要和一些标志有关。其中有效的包括IPC_CREAT和IPC_EXCL,它们的功能与open()的O_CREAT和O_EXCL相当。 IPC_CREAT 如果共享内存不存在,则创建一个共享内存,否则打开操作。 IPC_EXCL 只有在共享内存不存在的时候,新的共享内存才建立,否则就产生错误。 如果单独使用IPC_CREAT,shmget()函数要么返回一个已经存在的共享内存的操作符,要么返回一个新建的共享内存的标识符。如果将IPC_CREAT和IPC_EXCL标志一起使用,shmget()将返回一个新建的共享内存的标识符;如果该共享内存已存在,则返回-1。IPC_EXEL标志本身并没有太大的意义,但是和IPC_CREAT标志一起使用可以用来保证所得的对象是新建的,而不是打开已有的对象。 | |
返回值 | 成功返回共享内存的标识符;不成功返回-1,errno储存错误原因。 EINVAL 参数size小于SHMMIN或大于SHMMAX。 EEXIST 预建立key所致的共享内存,但已经存在。 EIDRM 参数key所致的共享内存已经删除。 ENOSPC 超过了系统允许建立的共享内存的最大值(SHMALL )。 ENOENT 参数key所指的共享内存不存在,参数shmflg也未设IPC_CREAT位。 EACCES 没有权限。 ENOMEM 核心内存不足。 |
函数原型 | void *shmat( int shmid , char *shmaddr , int shmflag ); |
头文件 | #include<sys/ipc.h> #include<sys/shm.h> |
描述 | 在进程的地址空间中创建共享内存段的部分 |
参数说明 | shmid是那块共享内存的ID |
shmaddr是共享内存的起始地址,NULL | |
是本进程对该内存的操作模式。如果是SHM_RDONLY(1)的话,就是只读模式。其它的是读写模式 | |
返回值 | 成功时,这个函数返回共享内存的起始地址。失败时返回-1 |
函数原型 | int shmdt( char *shmaddr ); |
头文件 | #include<sys/ipc.h> #include<sys/shm.h> |
描述 | 将共享内存与当前进程分离。分离共享内存并不会删除他;他只是使得内存对于当前进程不可用。 |
参数说明 | shmat获得的地址 |
返回值 | 成功时,返回0。失败时返回-1 |
函数原型 | int shmctl( int shmid , int cmd , struct shmid_ds *buf ); |
头文件 | #include<sys/ipc.h> #include<sys/shm.h> |
描述 | 删除开辟的共享内存。如果不删除的话,那块内存将一直存在。 |
参数说明 | shmid:是共享内存的ID |
cmd: 是控制命令,可取值如下: IPC_STAT 得到共享内存的状态, IPC_SET 改变共享内存的状态 IPC_RMID 删除共享内存 struct shmid_ds *buf是一个结构体指针。IPC_STAT的时候,取得的状态放在这个结构体中。如果要改变共享内存的状态,用这个结构体指定。 | |
与参数二配套使用,一般设置为NULL | |
返回值 | 成功时,返回0。失败时返回-1 |
命令行查看
取得ipc信息:
ipcs [-m|-q|-s]
-m 输出有关共享内存(shared memory)的信息
-q 输出有关信息队列(message queue)的信息
-s 输出有关“遮断器”(semaphore)的信息
%ipcs –m
删除ipc:
ipcrm -m|-q|-s shm_id
%ipcrm -m 105
Sample
使用共享内存的C/S
S:获取当前用户输入,并存放至SM
C:访问SM,取得用户输入
server.c
// the server get a string from the stdio, and put it into the shared memory
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#define SM_KEY 8888 // the key of the shared memory
#define SM_SIZE 1024 // size of the shared memory
#define oops(m) {perror(m); exit(1);} // exception handling
int main()
{
int sm_id;
char *mem_ptr;
int iTemp;
// create the shared memory if not exist, and get the sm_id of this shared memory
sm_id = shmget(SM_KEY, SM_SIZE, IPC_CREAT|0777);
if(sm_id == -1)
oops("shmget");
// attach to it and get a pointer to this memory
mem_ptr = shmat(sm_id, NULL, 0); // read and write
if(mem_ptr == NULL)
oops("shmat");
// input sth
bzero(mem_ptr, 1024);
printf("---------------------------------------------------------------------->/n");
printf("Input a string whose size is less than 1024:/n");
gets(mem_ptr);
// remove the shared memory
printf("Press any key to remove the shared memory!/n");
iTemp = getchar();
iTemp = shmctl(sm_id, IPC_RMID, NULL);
if(iTemp == -1)
oops("shmctl");
return 0;
}
client.c
// the client get the string in the shared memory which is put by the server
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#define SM_KEY 8888 // the key of the shared memory
#define SM_SIZE 1024 // size of the shared memory
#define oops(m) {perror(m); exit(1);} // exception handling
int main()
{
int sm_id;
char *mem_ptr;
int iTemp;
// create the shared memory if not exist, and get the sm_id of this shared memory
sm_id = shmget(SM_KEY, SM_SIZE, 0777);
if(sm_id == -1)
{
printf("No shared memory to use, please run server first!/n");
oops("shmget");
}
// attach to it and get a pointer to this memory
mem_ptr = shmat(sm_id, NULL, 0); // read and write
if(mem_ptr == NULL)
oops("shmat");
while(strlen(mem_ptr) == 0)
{
printf("Please wait for the server put sth in the shared memory first/n");
sleep(1);
}
// get the string
printf("---------------------------------------------------------------------->/n");
printf("The string in the shared memory which is put by the server is: %s/n", mem_ptr);
return 0;
}