前篇介绍了共享内存中mmap函数和munmap函数,下面接着学习总结System V共享内存,包括共享内存数据结构、共享内存函数、共享内存示例。
1.共享内存数据结构
1 2 3 4 5 6 7 8 9 10 11 |
struct shmid_ds { struct ipc_perm shm_perm; //Ownership and permissions size_t shm_segs; //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 ... }; |
2.共享内存函数
1 2 3 4 5 6 7 |
#include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg); void *shmat(int shmid, const void *shmaddr, int shmflg); int shmdt(const void *shmaddr); int shmctl(int shmid, int cmd, struct shmid_ds *buf); |
(1)shmget函数
- 功能:用来创建共享内存
- 原型:
int shmget(key_t key, size_t size, int shmflg); - 参数:
- key:这个共享内存段名字
- size:共享内存大小
- shmflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的
- 返回值:成功返回一个非负整数,即该共享内存段的标识码;失败返回-1
(2)shmat函数
- 功能:将共享内存段连接到进程地址空间
- 原型:
void *shmat(int shmid, const void *shmaddr, int shmflg); - 参数:
- shmid:共享内存标识
- shmaddr:指定连接的地址
- shmflg:它的两个可能取值是SHM_RND和SHM_RDONLY
- 返回值:成功返回一个指针,指向共享内存第一个字节;失败返回-1
其中,
1)shmaddr为NULL,内核自动选择一个地址
2)shmaddr不为NULL且shmflg无SHM_RND标记,则以shmaddr为连接地址
3)shmaddr不为NULL且shmflg设置了SHM_RND标记,则连接的地址会自动向下调整为SHMLBA的整数倍。公式:shmaddr-(shmaddr%SHMLBA)
4)shmflg=SHM_RDONLY,表示连接操作用来只读共享内存
(3)shmdt函数
- 功能:将共享内存段与当前进程脱离
- 原型:
int shmdt(const void *shmaddr); - 参数:
- shmaddr:由shmat所返回的指针
- 返回值:成功返回0;失败返回-1
将共享内存段与当前进程脱离不等于删除共享内存段
(4)shmctl函数
- 功能:用来创建和访问一个共享内存
- 原型:
int shmctl(int shmid, int cmd, struct shmid_ds *buf); - 参数:
- shmid:由shmget返回的共享内存标识码
- cmd:将要采取的动作,有三个可取值(与消息队列相同:IPC_STAT, IPC_SET, IPC_RMID)
- buf:指向一个保存着共享内存的模式状态和访问权限的数据结构
- 返回值:成功返回0;失败返回-1
3.共享内存示例
(1)写共享内存shmwrite.c
1)首先创建一块共享内存:
int shmid;
shmid = shmget(1234, sizeof(STU), IPC_CREAT|0666);
2)数据写入内存之后,进入死循环,等待quit字节写入内存…(写入之后即可跳出循环–>解除映射–>删除共享内存段)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
#include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/mman.h> #include <string.h> #include <sys/ipc.h> #include <sys/shm.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> #define ERR_EXIT(m)\ do\ {\ perror(m);\ exit(EXIT_FAILURE);\ }while(0) typedef struct stu { 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, "Leo"); p->age = 25; while(1){ if (memcmp(p, "quit", 4) == 0) break; } shmdt(p); shmctl(shmid, IPC_RMID, NULL); return 0; } |
(2)读共享内存,读完数据之后,将“quit”拷贝到共享内存中前四个字节,上述程序收到”quit”四个字节后解除映射并删除共享内存
shmread.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
#include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/mman.h> #include <string.h> #include <sys/ipc.h> #include <sys/shm.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> #define ERR_EXIT(m)\ do\ {\ perror(m);\ exit(EXIT_FAILURE);\ }while(0) typedef struct stu { char name[32]; int age; }STU; int main(int argc, char *argv[]) { int shmid; 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; } |