共享内存通信方式效率最高,毕竟是直接操作内存,但是要保证多个进程对同一块内存访问的同步互斥比较麻烦,借助信号量实现
对每个共享存储段,内核维护一个shmid_ds类型的结构体,定义在<sys/shm.h>文件中
C代码
struct shmid_ds
{
struct ipc_perm shm_perm; //共享内存的ipc_perm结构
size_t shm_segsz; //共享内存区域大小,字节表示
pid_t shm_lpid; //最后一次调用shmop函数的进程ID
pid_t shm_cpid; //创建此共享内存的进程ID
unsigned short shm_lkcnt; //共享内存被锁定的时间数
unsigned long shm_nattch; //当前使用共享内存的进程数
time_t shm_atime; //最后一次附加操作时间
time_t shm_dtime; //最后一次分离操作时间
time_t shm_ctime; //最后一次修改时间
}
struct shmid_ds
{
struct ipc_perm shm_perm; //共享内存的ipc_perm结构
size_t shm_segsz; //共享内存区域大小,字节表示
pid_t shm_lpid; //最后一次调用shmop函数的进程ID
pid_t shm_cpid; //创建此共享内存的进程ID
unsigned short shm_lkcnt; //共享内存被锁定的时间数
unsigned long shm_nattch; //当前使用共享内存的进程数
time_t shm_atime; //最后一次附加操作时间
time_t shm_dtime; //最后一次分离操作时间
time_t shm_ctime; //最后一次修改时间
}共享内存基本操作
1,创建或打开一个共享内存(shmget)
C代码
//create_shm.c
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdio.h>
#define BUFSZ 1024
int main()
{
int shm_id; //共享内存ID
shm_id = shmget(IPC_PRIVATE,BUFSZ,0666);
if(shm_id < 0){
printf("shmget failed\n");
return -1;
}
printf("create shared memory succeed: %d\n",shm_id);
system("ipcs -m"); //查看共享内存ID
return 0;
}
//create_shm.c
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdio.h>
#define BUFSZ 1024
int main()
{
int shm_id; //共享内存ID
shm_id = shmget(IPC_PRIVATE,BUFSZ,0666);
if(shm_id < 0){
printf("shmget failed\n");
return -1;
}
printf("create shared memory succeed: %d\n",shm_id);
system("ipcs -m"); //查看共享内存ID
return 0;
}
2,附加共享内存到进程空间(shmat/shmdt)
C代码
//attach_shm.c
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdio.h>
#define BUFSZ 1024
int main()
{
int *shm;
shm = shmat(104529925,NULL,0);
if(*shm == -1){
printf("shmat failed\n");
return -1;
}
printf("attach shared memory succeed: %d\n",*shm);
system("ipcs -m"); //查看共享内存调用状态
if(shmdt(shm) == -1){
printf("shmdt failed\n");
return -1;
}
system("ipcs -m"); //查看共享内存调用状态
return 0;
}
//attach_shm.c
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdio.h>
#define BUFSZ 1024
int main()
{
int *shm;
shm = shmat(104529925,NULL,0);
if(*shm == -1){
printf("shmat failed\n");
return -1;
}
printf("attach shared memory succeed: %d\n",*shm);
system("ipcs -m"); //查看共享内存调用状态
if(shmdt(shm) == -1){
printf("shmdt failed\n");
return -1;
}
system("ipcs -m"); //查看共享内存调用状态
return 0;
}
3,共享内存控制函数(shmctl)
下面写个简单的例子
共享内存写端(write_shm.c)
C代码
//write_shm.c
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdio.h>
typedef struct
{
char name[4];
int age;
}people;
int main()
{
int i;
char *t = 'a';
people *p_shm = NULL;
p_shm = shmat(104529925,NULL,0);
if(p_shm == NULL){
printf("shmat failed\n");
return -1;
}
for(i=0;i<5;i++) {
t += 1;
memcpy((*(p_shm+i)).name,&t,1);
(*(p_shm+i)).age = 20+i;
}
if(shmdt(p_shm) == -1){
printf("shmdt failed\n");
return -1;
}
return 0;
}
//write_shm.c
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdio.h>
typedef struct
{
char name[4];
int age;
}people;
int main()
{
int i;
char *t = 'a';
people *p_shm = NULL;
p_shm = shmat(104529925,NULL,0);
if(p_shm == NULL){
printf("shmat failed\n");
return -1;
}
for(i=0;i<5;i++) {
t += 1;
memcpy((*(p_shm+i)).name,&t,1);
(*(p_shm+i)).age = 20+i;
}
if(shmdt(p_shm) == -1){
printf("shmdt failed\n");
return -1;
}
return 0;
}
共享内存读端(read_shm.c)
C代码
//read_shm.c
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdio.h>
typedef struct
{
char name[4];
int age;
}people;
int main()
{
int i;
char *t = 'a';
people *p_shm = NULL;
p_shm = shmat(104529925,NULL,0);
if(p_shm == NULL){
printf("shmat failed\n");
return -1;
}
for(i=0;i<5;i++) {
printf("name:%s age:%d\n",(*(p_shm+i)).name,(*(p_shm+i)).age);
}
if(shmdt(p_shm) == -1){
printf("shmdt failed\n");
return -1;
}
return 0;
}
//read_shm.c
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdio.h>
typedef struct
{
char name[4];
int age;
}people;
int main()
{
int i;
char *t = 'a';
people *p_shm = NULL;
p_shm = shmat(104529925,NULL,0);
if(p_shm == NULL){
printf("shmat failed\n");
return -1;
}
for(i=0;i<5;i++) {
printf("name:%s age:%d\n",(*(p_shm+i)).name,(*(p_shm+i)).age);
}
if(shmdt(p_shm) == -1){
printf("shmdt failed\n");
return -1;
}
return 0;
}先后编译执行"写代码"与"读代码",结果如下
Txt代码
root$ ./write_shm.out
root$ ./read_shm.out
name:b age:20
name:c age:21
name:d age:22
name:e age:23
name:f age:24