shm进程间通信失败了!!!

举报
看,未来 发表于 2020/12/29 23:01:44 2020/12/29
【摘要】 稍安勿躁。 先解决问题 如果你是在网上辗转而不得其解,那就来我这儿吧。 之前那篇写的比较急,讲的还是蛮有条理的,就是东西少了点,这篇一次性写完。 那天,我和共享内存、shmid不眠不休只吃一点喝一点奋战了十个小时,只为了把我的项目进度赶在大家前面,却被进程间通信始终无法打通而拦住。解决问题之后,有感而作。 如果放在今天,我会选择采用TCP流协议的方式来进行...

在这里插入图片描述

稍安勿躁。

先解决问题

如果你是在网上辗转而不得其解,那就来我这儿吧。

之前那篇写的比较急,讲的还是蛮有条理的,就是东西少了点,这篇一次性写完。

那天,我和共享内存、shmid不眠不休只吃一点喝一点奋战了十个小时,只为了把我的项目进度赶在大家前面,却被进程间通信始终无法打通而拦住。解决问题之后,有感而作。

如果放在今天,我会选择采用TCP流协议的方式来进行进程间通信,详情:你会不会分布式系统进程间通信

不过我们现在讲的是shm,好。

以下内容基于在一个进程里至少准备挂两个共享内存,一个用来发,一个用来收

既然用到shm,那自然和key值要打交道。
key值有fotk函数生成,如果对ftok函数不熟,有空可以看一下这篇:ftok
讲的是极好的,不是我写的。

我遇到的第一个问题,是:不同参数的ftok生成同样的shmid值
为什么呢?不知道。
但是我还不算傻,至少知道做个demo把key值打印出来看,全是-1。
ftok的第一个参数得是有效的文件路径。

看了上面那篇文章之后,我将代码进行了修改,接下来就遇到了第二个问题:同样参数的ftok函数生成了不同的key值
这个就不好找咯,上面那个还能在网上找到点蛛丝马迹,这个要是找到希望能在下面给我留个网址,感激不尽。

这个就不好找咯,上面那个还能在网上找到点蛛丝马迹,这个要是找到希望能在下面给我留个网址,感激不尽。

这个就要分两种情况了(我遇到两种),第一种就是代码的问题,刚开始我写的花里胡哨的,后面老实了,拿到key值之后直接就shm_get, 这下shmid也老实了,不过还是会差,因为key值会偏差一点。

第二种情况,
其实问题也很简单,就是目录的差别。如果你用的是绝对目录那就比较好,但是如果给ftok传参传的是相对目录,而你运行的两个执行文件所在的目录又不同,那么ftok计算key值时从当前进程所在目录出发,自然是会有偏差的。
怎么办?怎么办?

小事情,这里有两个方法:
1、将两个执行文件放在统一目录底下,方法是好方法,不过最好你得会写Makefile
2、使用绝对路径,其实这个方法也能另辟蹊径,什么呢, / ,就是这个斜杠,杠杠的绝对路径

shm共享内存

创建或打开共享内存

  #include <sys/ipc.h>
  #include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg);

  
 
  • 1
  • 2
  • 3
  • 4

参数不释义,后面有例子

挂载共享内存

 #include <sys/types.h> #include <sys/shm.h> void *shmat(int shmid, const void *shmaddr, int shmflg);

  
 
  • 1
  • 2
  • 3
  • 4

分离共享内存

 #include <sys/shm.h> int shmdt(const void *shmaddr);

  
 
  • 1
  • 2
  • 3

控制共享内存

 #include <sys/ipc.h> #include <sys/shm.h> int shmctl(int shmid, int cmd, struct shmid_ds *buf);

  
 
  • 1
  • 2
  • 3
  • 4

示例

#include "f_shm.h"

#include <sys/types.h>
#include <unistd.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <semaphore.h>

typedef struct shmhead_st
{ int shmid;			// 共享内存ID unsigned int blksize;		// 块大小 unsigned int blocks;		// 总块数 unsigned int rd_index;		// 读索引 unsigned int wr_index;		// 写索引 //必须放在共享内存内部才行 sem_t sem_mutex;	// 用来互斥用的信号量 sem_t sem_full;		// 用来控制共享内存是否满的信号量 sem_t sem_empty;	// 用来控制共享内存是否空的信号量

}shmhead_t;

F_Shm::F_Shm(key_t key, int blksize, int blocks)
{ this->open_shm(key, blksize, blocks);
}

F_Shm::F_Shm()
{ shmhead = NULL; payload = NULL; open = false;
}

F_Shm::~F_Shm()
{ this->close_shm();
}
//返回头地址
bool F_Shm::creat_shm(key_t key, int blksize, int blocks)
{ int shmid = 0; //1. 查看是否已经存在共享内存,如果有则删除旧的 shmid = shmget(key, 0, 0); if (shmid != -1) { shmctl(shmid, IPC_RMID, NULL); 	//	删除已经存在的共享内存 } //2. 创建共享内存 shmid = shmget(key, sizeof(shmhead_t) + blksize*blocks, 0666 | IPC_CREAT | IPC_EXCL); if(shmid == -1) { ERR_EXIT("shmget"); } printf("Create shmid=%d size=%u \n", shmid, sizeof(shmhead_t) + blksize*blocks); //3.连接共享内存 shmhead = shmat(shmid, (void*)0, 0); //连接共享内存 if(shmhead == (void*)-1) { ERR_EXIT("shmat"); } memset(shmhead, 0, sizeof(shmhead_t) + blksize*blocks);		//初始化 //4. 初始化共享内存信息 shmhead_t * pHead = (shmhead_t *)(shmhead); pHead->shmid	= shmid; //共享内存shmid pHead->blksize	= blksize;			//共享信息写入 pHead->blocks	= blocks; //写入每块大小 pHead->rd_index = 0; //一开始位置都是第一块 pHead->wr_index = 0; // sem_init(&pHead->sem_mutex, 1, 1);	// 第一个1表示可以跨进程共享,第二个1表示初始值 sem_init(&pHead->sem_empty, 1, 0);	// 第一个1表示可以跨进程共享,第二个0表示初始值 sem_init(&pHead->sem_full, 1, blocks);// 第一个1表示可以跨进程共享,第二个blocks表示初始值 //5. 填充控制共享内存的信息 payload = (char *)(pHead + 1);	//实际负载起始位置 open = true; return true;
}

void F_Shm::dsy_shm()
{ shmhead_t *pHead = (shmhead_t *)shmhead; int shmid = pHead->shmid; //删除信号量 sem_destroy (&pHead->sem_full); sem_destroy (&pHead->sem_empty); sem_destroy (&pHead->sem_mutex); shmdt(shmhead); //共享内存脱离 //销毁共享内存 if(shmctl(shmid, IPC_RMID, 0) == -1)		//删除共享内存 { printf("Delete shmid=%d \n", shmid); ERR_EXIT("shmctl rm"); } shmhead = NULL; payload = NULL; open = false;
}

void F_Shm::Destroy(key_t key)
{ int shmid = 0; //1. 查看是否已经存在共享内存,如果有则删除旧的 shmid = shmget(key, 0, 0); if (shmid != -1) { printf("Delete shmid=%d \n", shmid); shmctl(shmid, IPC_RMID, NULL); 	//	删除已经存在的共享内存 }
}

//返回头地址
bool F_Shm::open_shm(key_t key, int blksize, int blocks)
{ int shmid; this->close_shm(); //1. 查看是否已经存在共享内存,如果有则删除旧的 shmid = shmget(key, 0, 0); if (shmid == -1) { return this->creat_shm(key, blksize, blocks); } //2.连接共享内存 shmhead = shmat(shmid, (void*)0, 0); //连接共享内存 if(shmhead == (void*)-1) { ERR_EXIT("shmat"); } printf("Open shmid=%d size=%u \n", shmid, sizeof(shmhead_t) + blksize*blocks); //3. 填充控制共享内存的信息 payload = (char *)((shmhead_t *)shmhead + 1);	//实际负载起始位置 open = true; return true;
}


//关闭共享内存
void F_Shm::close_shm(void)
{ if(open) { shmdt(shmhead); //共享内存脱离 shmhead = NULL; payload = NULL; open = false; }
}

void F_Shm::write_into_shm(const void *buf)
{ shmhead_t *pHead = (shmhead_t *)shmhead; sem_wait(&pHead->sem_full); //是否有资源写?	可用写资源-1 sem_wait(&pHead->sem_mutex); //是否有人正在写? printf("write to shm[%d] index %d \n", pHead->shmid, pHead->rd_index); memcpy(payload + (pHead->wr_index) * (pHead->blksize), buf, pHead->blksize); pHead->wr_index = (pHead->wr_index+1) % (pHead->blocks);	//写位置偏移 sem_post(&pHead->sem_mutex); //解除互斥 sem_post(&pHead->sem_empty); //可用读资源+1
}

void F_Shm::read_from_shm(void *buf)
{ shmhead_t *pHead = (shmhead_t *)shmhead; sem_wait(&pHead->sem_empty); //检测写资源是否可用 printf("read from shm[%d] index %d \n", pHead->shmid, pHead->rd_index); memcpy(buf, payload + (pHead->rd_index) * (pHead->blksize), pHead->blksize); //读位置偏移 pHead->rd_index = (pHead->rd_index+1) % (pHead->blocks); sem_post(&pHead->sem_full); //增加可写资源
}


  
 
  • 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
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198

文章来源: lion-wu.blog.csdn.net,作者:看,未来,版权归原作者所有,如需转载,请联系作者。

原文链接:lion-wu.blog.csdn.net/article/details/106691117

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。