1.概述
共享内存是最快的进程间通信方式,系统在内存中维护一个特殊大小的内存块,进程可以将这快内存使用自己的页表映射到自己的内存空间中,则该内存就可以被两个进程访问实现了通信的功能.而且建立映射关系后传输数据时不用再进入内核,相比于消息队列而言更快.
2.基本数据结构
struct shmid_ds {
struct ipc_perm
shm_perm;
/* operation perms */
int
shm_segsz;
/* size of segment (bytes) */
__kernel_time_t
shm_atime;
/* last attach time */
__kernel_time_t
shm_dtime;
/* last detach time */
__kernel_time_t
shm_ctime;
/* last change time */
__kernel_ipc_pid_t
shm_cpid;
/* pid of creator */
__kernel_ipc_pid_t
shm_lpid;
/* pid of last operator */
unsigned short
shm_nattch;
/* no. of current attaches */
unsigned short
shm_unused;
/* compatibility */
void
*shm_unused2; /* ditto - used by DIPC */
void
*shm_unused3; /* unused */
};
该结构体是内核关于共享内存的抽象,其中shm_segsz表示该内存块的大小.
3.API
int shmget ( key_t key, int size, int shmflg);
打开一个共享内存块,size大小.
void* shmat ( int shmid, char *shmaddr, int shmflg);
将一个共享内存块链接到当前进程的地址空间中.返回下面可以进行数据操纵的指针.
int shmdt ( char *shmaddr );
卸载共享内存
int shmctl ( int shmqid, int cmd, struct shmid_ds *buf );
对共享内存进行管理,如获取权限值,修改结构体shmid等,删除共享内存等.
4
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <string.h>
int main(){
key_t key;
int value;
int running = 1;
int semid;
void* sharem = NULL;
key =ftok(".",1);
semid = semget(key,1,IPC_CREAT | 0660);
if(semid == -1){
perror("semget");
exit(0);
}
printf("semid is %d\n",semid);
if(semctl(semid,0,SETVAL,0) == -1){
perror("semctl");
exit(0);
}
int shmid;
shmid = shmget(key,(size_t)2048,IPC_CREAT |0660);
if(shmid == -1){
perror("shmid");
exit(0);
}
printf("shmid is %d\n",shmid);
sharem = shmat(shmid,NULL,0);
if(sharem == NULL){
perror("shmat");
exit(0);
}
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_flg = SEM_UNDO;
while(running){
if((value = semctl(semid, 0 ,GETVAL)) == 0){
printf("write data operarte\n");
printf("pls input something:\n");
scanf("%s",(char*)sharem);
sem_b.sem_op = 1;
if(semop(semid,&sem_b,1) == -1){
perror("semop");
exit(0);
}
if(strcmp(sharem,"end") == 0)
running --;
}
}
shmdt(sharem);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <string.h>
int main(){
int value;
int running = 1;
key_t key;
int shmid,semid;
key = ftok(".",1);
void* sharem = NULL;
semid = semget(key,1,IPC_CREAT|0660);
if(semid == -1){
perror("semid");
exit(0);
}
printf("the semid is%d\n",semid);
shmid = shmget(key,(size_t)2048,IPC_CREAT|0660);
if(shmid == -1){
perror("shmget");
exit(0);
}
printf("the shmid is%d\n",shmid);
sharem = shmat(shmid,NULL,0);
if(sharem == NULL){
perror("shmat");
exit(0);
}
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_flg = SEM_UNDO;
while(running){
if((value = semctl(semid,0,GETVAL)) == 1){
printf("read data operate\n");
printf("recving message is %s\n",(char*)sharem);
sem_b.sem_op = -1;
if(semop(semid,&sem_b,1) == -1){
perror("semop");
exit(0);
}
if(strcmp(sharem,"end") == 0)
running--;
}
}
shmdt(sharem);
return 0;
}
共享内存的使用需要配合信号量的使用,来避免两个进程同时读写进程,使用0-1信号量可以实现两个进程的互斥访问.