目录
1 概念
2 操作流程
fork(获取key值)
shmget(申请对象)
shmat(内存映射)
读写共享内存:类似堆区内存的直接读写
shmdt(解除映射)
shmctl(删除对象)
范例:
共享内存是进程间通信中最简单最高效的方式之一。共享内存允许两个或更多进程访问同一块内存,就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针。当一个进程改变了这块地址中的内容的时候,其它进程都会察觉到这个更改。
1 获取K值 ftok
2 申请对象 shmget
3 内存映射 shmat
4 读写共享内存
5 解除映射 shmdt
6 删除对象 shmctl
key_t ftok(const char *pathname, int proj_id);
功能:
通过该函数可以将pathname指定的路径用来以proj_id生成唯一的临时键值。
参数:pathname 路径 ,任意路径,只要不会被删除即可。但是读写端路径指向必须一致proj_id 代号,整形的数据,一般用ASCII码的单字符表示
返回值:
成功 返回唯一键值
失败 -1;
int shmget(key_t key, size_t size, int shmflg);
功能:
创建共享内存
参数:
key:键值
size:共享内存大小
shmflg:
IPC_CREAT 创建 (低9个bits表示用户,同组用户,其他人的权限)
IPC_EXCL 检测是否存在
返回值:
成功返回共享内存ID
失败返回-1
void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:
将指定shmid对应的共享内存映射到本地内存。
参数:shmid 要映射的共享内存id
shmaddr 本地可用的地址,如果不确定则用NULL,表示由系统自动分配。
shmflg :操作权限
SHM_RDONLY,只读
!SHM_RDONLY 读写
返回值:成功 返回映射的地址,一般等于shmaddr
失败 (void*) -1
int shmdt(const void *shmaddr);
功能:
将本地内存与共享内存断开映射关系。
参数:shmaddr 要断开的映射地址。
返回值:成功 0
失败 -1;
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能:
修改共享内存属性,也可以删除指定的共享内存对象。
参数:shmid 要删除的共享内存对象
cmd
IPC_STAT 获得信息
IPC_SET 设置权限
IPC_RMID 删除
buff
NULL 表示只删除对象。
返回值:成功 0
编写两个进程任务利用共享内存通信,一个负责从终端接写入共享内存中,另一个负责打印共享内存数据,直到输入quit两个进程任务结束
进程1发送
#include
#include #include #include #include #include #include #include #include #include #include #include #include #include int main(int argc, char const *argv[]) {key_t key;printf("\33[35m\33[1mmess_t\33[0m\33[36m\33[1m开始配对...\33[0m\n");key = ftok(".",258);//获取k值-----1if(-1 == key){perror("fail to ftok");return 0;}printf("key: 0X%x\n",key);int shm_id = shmget(key,4096,IPC_CREAT | 0666);//申请对象-----2if(-1 == shm_id){perror("fail to shmget");return 0;}printf("shmID: %d\n",shm_id);void *pmem = shmat(shm_id,NULL,!SHM_RDONLY);//内存映射-----3if((void *)-1 == pmem){perror("fail to shmat");return 0;}pid_t R_pid = *(pid_t *)pmem;printf("R_pid = %d\n",R_pid);char tmpbuf[4096] = {0};printf("\33[32m\33[1mmess_t配对成功!\33[0m\n");while (1)//写共享内存-----4{printf("\33[35m\33[1mmess_t发送:\33[0m");fgets(tmpbuf,sizeof(tmpbuf),stdin);if(!strcmp("quit\n",tmpbuf))break;memcpy(pmem,tmpbuf,sizeof(tmpbuf));kill(R_pid,12);}shmdt(pmem);//解除映射-----5shmctl(shm_id,IPC_RMID,NULL);//删除对象-----6printf("BAIBAI!!!\n");kill(R_pid,10);return 0; }
进程2接收
#include
#include #include #include #include #include #include #include #include #include #include #include #include #include int stat_0_1 = 1; void handler(int arg) {alarm(0); } void end(int arg) {stat_0_1 = 0; } int main(int argc, char const *argv[]) {signal(SIGALRM, SIG_DFL); // 缺省默认signal(12, handler); // 缺省默认signal(10, end);key_t key;printf("\33[31m\33[1mmess_r\33[0m\33[36m\33[1m开始配对...\33[0m\n");key = ftok(".", 258); // 获取k值-----1if (-1 == key){perror("fail to ftok");return 0;}printf("key: 0X%x\n", key);int shm_id = shmget(key, 4096, IPC_CREAT | 0666); // 申请对象-----2if (-1 == shm_id){perror("fail to shmget");return 0;}printf("shmID: %d\n", shm_id);void *pmem = shmat(shm_id, NULL, !SHM_RDONLY); // 内存映射-----3if ((void *)-1 == pmem){perror("fail to shmat");return 0;}pid_t *pid = pmem;*pid = getpid();char tmpbuf[4096] = {0};printf("\33[32m\33[1mmess_r配对成功!\33[0m\n");while (1){if (stat_0_1){pause(); // 挂起,等待信号printf("\33[31m\33[1mmess_r收到:\33[0m\33[1m%s", (char *)pmem);}else{break;}}shmdt(pmem); // 解除映射-----5shmctl(shm_id, IPC_RMID, NULL); // 删除对象-----6printf("BAIBAI!!!\n");return 0; }
运行结果
上一篇:微信小程序开发过程整理