Linux共享内存
共享内存就是允许两个或多个进程共享一定的存储区。就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针。当一个进程改变了这块地址中的内容的时候,其它进程都会察觉到这个更改。因为数据不需要在客户机和服务器端之间复制,数据直接写到内存,不用若干次数据拷贝,所以这是最快的一种IPC。
共享内存的使用,主要有以下几个API:
1.获得一个ID号:ftok()
key_t ftok( const char * fname, int id )
fname就是你指定的文件名(已经存在的文件名),一般使用当前目录,如:
key_t key;
key = ftok(".", 1); 这样就是将fname设为当前目录。
2.创建共享内存 shmget()
int shmget(key_t key, size_t size, int shmflg);
第一个参数key,shmget()函数成功时返回一个与key相关的共享内存标识符(非负整数),用于后续的共享内存函数。调用失败返回-1.
第二个参数size,size以字节为单位指定需要共享的内存容量
第三个参数shmflg,shmflg是权限标志,它的作用与open函数的mode参数一样,如果要想在key标识的共享内存不存在时,创建它的话,可以IPC_CREAT做或操作。共享内存的权限标志与文件的读写权限一样,举例来说,0644,它表示允许一个进程创建的共享内存被内存创建者所拥有的进程向共享内存读取和写入数据,同时其他用户创建的进程只能读取共享内存。
3.绑定共享内存 (映射) shmat()
void *shmat( int shmid , char *shmaddr , int shmflag );
int shmid是那块共享内存的ID。
char *shmaddr是共享内存的起始地址,如果shmaddr为0,内核会把共享内存映像到调用进程的地址空间中选定位置;如果shmaddr不为0,内核会把共享内存映像到shmaddr指定的位置。所以一般把shmaddr设为0。
int shmflag是本进程对该内存的操作模式。如果是SHM_RDONLY的话,就是只读模式。其它的是读写模式
成功时,这个函数返回共享内存的起始地址。失败时返回-1
4.脱离共享内存 shmdt()
int shmdt( char *shmaddr );
参数char *shmaddr是那块共享内存的起始地址。
返回值:成功0,失败-1
5.控制共享内存 shmctl()
int shmctl( int shmid , int cmd , struct shmid_ds *buf );
ishmid是共享内存的ID。
cmd是控制命令,可取值如下:
IPC_STAT 得到共享内存的状态
IPC_SET 改变共享内存的状态
IPC_RMID 删除共享内存
struct shmid_ds *buf是一个结构体指针。IPC_STAT的时候,取得的状态放在这个结构体中。如果要改变共享内存的状态,用这个结构体指定。
返回值:成功0,失败-1
读端代码
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main()
{
int shmid;
char *shmaddr;
key_t key=1;
ftok(".",1);
shmid=shmget(key,1024*4,0);
if(shmid==-1){
printf("shmid failed\n");
exit(-1);
}
shmaddr=shmat(shmid,0,0);
printf("shmat ok\n");
printf("data:%s\n",shmaddr);
shmdt(shmaddr);
printf("quit\n");
return 0;
}
写端代码
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main()
{
int shmid;
char *shmaddr;
key_t key=1;
ftok(".",1);
shmid=shmget(key,1024*4,IPC_CREAT|0666);
if(shmid==-1){
printf("shmid failed\n");
exit(-1);
}
shmaddr=shmat(shmid,0,0);
printf("shmat ok\n");
strcpy(shmaddr,"lhg");
sleep(5);
shmdt(shmaddr);
shmctl(shmid,IPC_RMID,0);
printf("quit\n");
return 0;
}