Linux学习笔记27——共享内存
一 共享内存
共享内存是由IPC为进程创建的一个特殊的地址范围,它将出现在该进程的地址空间中。其他进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址。如果某个进程向共享内存写入了数据,所做的改动将立刻被可以访问同一段共享内存的任何其他进程看到。
二 相关函数
#include <sys/shm.h>
//shmget创建共享内存 int shmget(key_t key, //为共享内存段命名
size_t size, //以字节为单位指定需要共享的内存容量
int shmflg //权限标志。允许一个进程创建的共享内存可以被共享内存的创建者所拥有的进程写入,同时其他用户创建的进程只能读取该共享内存。
); //如果共享内存创建成功,返回一个非负整数,即共享内存标识符,如果失败,就返回-1
//shmat将共享内存连接它在程序进入临界区域时设置信号量到一个进程的地址空间中
void *shmat(int shm_id, //由shmget返回的共享内存标识符
const void *shm_addr, //指定的是共享内存连接到当前进程中的地址位置,它通常是一个空指针,表示让系统来选择共享内存出现的地址
int shmflg //一组位标志。通常设为0,让系统来选择一个地址,否则就会使应用程序对硬件的依赖性过高
); //如果调用成功,返回一个指向共享内存第一个字节的指针,如果失败,返回-1
//shmctl控制共享内存 int shmctl(int shm_id, //shmget返回的共享内存标识符
int cmd, //要采取的动作,可以取3个值: IPC_STAT,IPC_SET,IPC_RMID
struct shmid_ds *buf //是一个指向包含共享内存模式和访问权限的结构
); //成功时返回0,失败时返回-1
//shmdt将共享内存从当前进程中分离 int shmdt(const void *shm_addr); //参数是shmat返回的地址指针。成功时返回0,失败时返回-1
shmctl中第二个参数的取值:
IPC_STAT:把shmid_ds结构中的数据设置为共享内存的当前关联值
IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值
IPC_RMID:删除共享内存段
struct shmid_ds{
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_perm.mode;
}
三 例子
shm_com.h
#define TEXT_SZ 2048 struct shared_use_st{ int written_by_you; char some_text[TEXT_SZ]; };
shm1.c
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <sys/shm.h> #include "shm_com.h" int main(){ int running =1; void *shared_memory=(void*)0; struct shared_use_st *shared_stuff; int shmid; srand((unsigned int)getpid()); shmid=shmget((key_t)1234,sizeof(struct shared_use_st),0666|IPC_CREAT); if(shmid==-1){ fprintf(stderr,"shmget failed\n"); exit(EXIT_FAILURE); } //现在可以让程序访问这个共享内存 shared_memory=shmat(shmid,(void*)0,0); if(shared_memory==(void*)-1){ fprintf(stderr,"shmat failed\n"); exit(EXIT_FAILURE); } printf("Memory attached at %X\n",(int)shared_memory); //将shared_memory分配给shared_stuff,然后它输出written_by_you中的文本 shared_stuff=(struct shared_use_st *)shared_memory; shared_stuff->written_by_you=0; while(running){ if(shared_stuff->written_by_you){ printf("You wrote:%s",shared_stuff->some_text); sleep(rand()%4); shared_stuff->written_by_you=0; if(strncmp(shared_stuff->some_text,"end",3)==0){ running=0; } } } if(shmdt(shared_memory)==-1){ fprintf(stderr,"shmdt failed\n"); exit(EXIT_FAILURE); } if(shmctl(shmid,IPC_RMID,0)==-1){ fprintf(stderr,"shmctl(IPC_RMID) failed\n"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); }
shm2.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/shm.h> #include "shm_com.h" int main(){ int running=1; void *shared_memory=(void *)0; struct shared_use_st *shared_stuff; char buffer[BUFSIZ]; int shmid; shmid=shmget((key_t)1234,sizeof(struct shared_use_st),0666|IPC_CREAT); if(shmid==-1){ fprintf(stderr,"shmget failed\n"); exit(EXIT_FAILURE); } shared_memory=shmat(shmid,(void*)0,0); if(shared_memory==(void *)-1){ fprintf(stderr,"shmat failed\n"); exit(EXIT_FAILURE); } printf("Memory attached at %X\n",(int)shared_memory); shared_stuff=(struct shared_use_st *)shared_memory; while(running){ while(shared_stuff->written_by_you==1){ sleep(1); printf("Waiting for client...\n"); } printf("Enter some text:"); fgets(buffer,BUFSIZ,stdin); strncpy(shared_stuff->some_text,buffer,TEXT_SZ); shared_stuff->written_by_you=1; if(strncmp(buffer,"end",3)==0){ fprintf(stderr,"shmdt failed\n"); exit(EXIT_FAILURE); } } if(shmdt(shared_memory)==-1){ fprintf(stderr,"shmdt failed\n"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); }