第二十九章 System V共享内存
共享内存数据结构
共享内存函数
shmget
int shmget(key_t key, size_t size, int shmflg);
功能:
用于创建共享内存
参数:
key : 这个共享内存段名字
size : 共享内存大小
shmflg : 由9个权限位标志构成,它们的用法与创建文件时使用的mode模式标志是一样的
返回值:
成功 : 返回一个非负整数,即该共享内存段的标识码
失败 : -1
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while (0)
typedef struct str
{
char name[32];
int age;
}STU;
int main(int argc, char* argv[])
{
int shmid;
shmid = shmget(1234, sizeof(STU), IPC_CREAT|0666);
if(shmid == -1)
ERR_EXIT("shmget");
return 0;
}
结果
ipcs
------------ 共享内存段 --------------
键 shmid 拥有者 权限 字节 连接数 状态
0x000004d2 9011220 dw 666 36 0
shmat
void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:
将共享内存段连接到进程地址空间
参数:
shmid : 共享内存标识
shmaddr : 指定连接的地址
NULL : 核心自动选择一个地址
not NULL && 未设置SHM_RND标记,则以shmaddr为连接地址
not NULL && 设置了SHM_RND标记,则连接的地址会自动往下调整为SHMLBA的整数倍。公式 : shmaddr - (shmaddr % SHMLBA)
shmflg :
SHM_RND
SHM_RDONLY : 表示连接操作用来只读共享内存
返回值:
成功 : 返回一个指针,指向共享内存第一节
失败 : -1
shmdt
int shmdt(const void *shmaddr)
功能:
将共享内存段与当前进程脱离
参数:
shmaddr : 由shmat所返回的指针
返回值:
成功 : 0
失败 : -1
注意:
将共享内存段与当前进程脱离不等于删除共享内存段
shmget_write.c
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while (0)
typedef struct str
{
char name[32];
int age;
}STU;
int main(int argc, char* argv[])
{
int shmid;
shmid = shmget(1234, sizeof(STU), IPC_CREAT|0666);
if(shmid == -1)
ERR_EXIT("shmget");
STU *p;
//自动分配地址且可读可写
p = shmat( shmid, NULL, 0);
if(p == (void*)-1)
ERR_EXIT("shmat");
strcpy(p->name, "xiaoming");
p->age = 20;
sleep(10);
shmdt(p);
return 0;
}
结果
进程退出前
ipcs
------------ 共享内存段 --------------
键 shmid 拥有者 权限 字节 连接数 状态
0x000004d2 9011220 dw 666 36 1
进程退出后
ipcs
------------ 共享内存段 --------------
键 shmid 拥有者 权限 字节 连接数 状态
0x000004d2 9011220 dw 666 36 0
shmget_read.c
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while (0)
typedef struct str
{
char name[32];
int age;
}STU;
int main(int argc, char* argv[])
{
int shmid;
//第二个参数,如果不知道大小可以填0
// shmid = shmget(1234, sizeof(STU), IPC_CREAT|0666);
shmid = shmget(1234, 0, 0);
if(shmid == -1)
ERR_EXIT("shmget");
STU *p;
//自动分配地址且可读可写
p = shmat( shmid, NULL, 0);
if(p == (void*)-1)
ERR_EXIT("shmat");
printf("name : %s age : %d \n",p->name, p->age);
shmdt(p);
return 0;
}
shmctl
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能:
用来控制共享内存
参数:
shmid : 共享内存标识
cmd : 要采取的操作
IPC_STAT:把shmid_ds结构中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖shmid_ds的值。
IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值
IPC_RMID:删除共享内存段
buf : 是一个结构指针,它指向共享内存模式和访问权限的结构
返回值:
成功 : 0
失败 : -1
共享内存示例
shmget_write.c
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while (0)
typedef struct str
{
char name[32];
int age;
}STU;
int main(int argc, char* argv[])
{
int shmid;
shmid = shmget(1234, sizeof(STU), IPC_CREAT|0666);
if(shmid == -1)
ERR_EXIT("shmget");
STU *p;
//自动分配地址且可读可写
p = shmat( shmid, NULL, 0);
if(p == (void*)-1)
ERR_EXIT("shmat");
strcpy(p->name, "xiaoming");
p->age = 20;
while(1)
{
if(memcmp(p, "quit", 4) == 0)
break;
}
shmdt(p);
shmctl(shmid, IPC_RMID, NULL);
return 0;
}
shmget_read.c
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while (0)
typedef struct str
{
char name[32];
int age;
}STU;
int main(int argc, char* argv[])
{
int shmid;
//第二个参数,如果不知道大小可以填0
// shmid = shmget(1234, sizeof(STU), IPC_CREAT|0666);
shmid = shmget(1234, 0, 0);
if(shmid == -1)
ERR_EXIT("shmget");
STU *p;
//自动分配地址且可读可写
p = shmat( shmid, NULL, 0);
if(p == (void*)-1)
ERR_EXIT("shmat");
printf("name : %s age : %d \n",p->name, p->age);
memcpy(p, "quit", 4);
shmdt(p);
return 0;
}