共享内存
- 共享内存就是允许两个或更多进程访问同一个块内存。共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常安排为同一段物理内存。进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc分配的内存一样。而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程。
注意点:
共享内存并未提供同步与互斥机制,通常需要与信号量等搭配使用
共享内存图示
共享内存的使用
命令查看和删除共享内存
ipcs -m
ipcrm -m shmid
共享内存创建
int shmget(key_t key, size_t size, int shmflg)
key:标识共享内存的键值(可以用ftok函数产生)
size: size以字节为单位指定需要共享的内存容量(4096的整数倍)
shmflg:IPC_CREAT 已创建则打开,反之创建。
IPC_CREAT|IPC_EXCL 如果已创建则出错返回-1,反之创建新的(两个一起用保证是新创建的)返回值:成功–shmid;错误– -1
共享内存的删除
int shmctl(int shmid, int cmd, struct shmid_ds *buf)
shmid: shmget函数返回的shmid
cmd: IPC_RMID 删除共享内存段
**buf:**buf是一个结构指针,它指向共享内存模式和访问权限的结构
struct shmid_ds {
struct ipc_perm shm_perm; /* Ownership and permissions */
size_t shm_segsz; /* Size of segment (bytes) */
time_t shm_atime; /* Last attach time */
time_t shm_dtime; /* Last detach time */
time_t shm_ctime; /* Last change time */
pid_t shm_cpid; /* PID of creator */
pid_t shm_lpid; /* PID of last shmat(2)/shmdt(2) */
shmatt_t shm_nattch; /* No. of current attaches */
...
};
返回值:成功 0 ;失败 -1- 共享内存的挂接
void *shmat(int shmid, const void *shmaddr, int shmflg)
shmid: shmget函数返回的shmid
shmaddr:指定共享内存连接到当前进程中的地址位置,通常为NULL,表示让系统来选择共享内存的地址。
shmflg:通常为0IPC_CREAT 已创建则打开,反之创建。
IPC_CREAT|IPC_EXCL 如果已创建则出错返回-1,反之创建新的(两个一起用保证是新创建的)
返回值:成功调用shmat()返回的地址连接共享内存段,返回错误(void *)-1,和errno设置为指示错误的原因。 - 共享内存去挂接
int shmdt(const void *shmaddr)
shmaddr:调用shmat()返回的shmaddr
返回值:成功shmdt()返回0;错误返回-1,errno设置为指示错误的原因 使用共享内存进行进程间通信
<comm.h> #ifndef _COMM_H_ #define _COMM_H_ #include<stdio.h> #include<sys/ipc.h> #include<sys/shm.h> #include<sys/types.h> #include<errno.h> #define PATHNAME "." #define PROJ_ID 0x6666 int create_shm(int size);//创建共享内存 int get_shm();//获取共享内存 int destory_shm(int shmid);//删除共享内存 char* attach_shm(int shmid);//共享内存挂接 int dttach_shm(char* shmaddr);//共享内存去挂接 #endif
<comm.c> #include"comm.h" static int comm_shm(int size,int shmflg) { key_t key = ftok(PATHNAME,PROJ_ID);//键值 int shmid = shmget(key,size,shmflg); if(shmid < 0) { perror("shmget"); return -1; } return shmid; } int create_shm(int size)//共享内存创建 { return comm_shm(size,IPC_CREAT|IPC_EXCL|0666); } int get_shm()//共享内存获取 { return comm_shm(0,IPC_CREAT); } int destory_shm(int shmid)//删除 { int ret = shmctl(shmid,IPC_RMID,NULL); if(ret < 0) { perror("shmctl"); return -2; } return ret; } char* attach_shm(int shmid)//挂接 { //void* shmat(int shmid,const void*shmaddr,int shmflg) shmaddr:通常为NULL shmflg:通常为0 return (char*)shmat(shmid,NULL,0); } int dttach_shm(char* shmaddr)//去挂接 { return shmdt(shmaddr); }
<sever.c> //写入 #include"comm.h" int main() { int shmid = create_shm(4096);//创建 char* buf = attach_shm(shmid);//挂接 int count = 0; while(1) { sleep(1); buf[count++] = 'A'+count%26; } dttach_shm(buf); destory_shm(shmid); return 0; }
<client.c> //输出 #include"comm.h" int main() { int shmid = get_shm();//获取 char* buf = attach_shm(shmid);//挂接 sleep(20); while(1) { sleep(1); printf("%s\n",buf); } dttach_shm(buf); destory_shm(shmid); return 0; }
<makefile> .PHONY:all all:client sever client:client.c comm.c gcc -o $@ $^ sever:sever.c comm.c gcc -o $@ $^ .PHOMY:clean clean: rm -f client sever
程序运行结果
sever 写—–client 读