shmat
第一个参数是想和哪一个共享内存关联,第二个参数是想把这个共享内存映射到地址空间的哪个地方(不常用),第三个权限是读写权限(一般设置为0)。
返回值是将映射到虚拟地址空间的起始地址位置返回。(等价于C语言的malloc)
失败返回-1。
void* attachshm(int shmid) { void* p = shmat(shmid, nullptr, 0); if((long long)p == -1L)//因为linux系统是64位,一个地址是8个字节,所以要变成8个字节大小的数据类型做对比 { std::cerr << errno << ":" << strerror(errno) << std::endl; exit(4); } return p; }
这里就代表挂接成功了,这个共享内存挂接了一个进程。
那么如何去关联呢?
shmdt
其实就是调用去卸载当前进程共享内存的地虚拟地址空间,参数就是shmat的返回值。
返回值成功是0,错误是-1.
void detachshm(void* p) { if(shmdt(p) == -1) { std::cerr << errno << ":" << strerror(errno) << std::endl; } }
然后完善一下另一个文件中的代码:
这一份不需要他释放掉共享内存。
这里让server多休息一会。
通信
然后来完善通信的一下代码:
#ifndef _COMM_HPP_ #define _COMM_HPP_ #include<iostream> #include<cassert> #include<cstring> #include<cerrno> #include<sys/ipc.h> #include<sys/shm.h> #include<cstdlib> #include<unistd.h> #define PATHNAME "."//ftok的第一个参数,是一个合法路径 #define PROJ_IO 0X666//ftok的第二个参数 #define MAX_SIZE 4096//共享内存的大小 key_t getkey() { key_t k = ftok(PATHNAME, PROJ_IO); if(k < 0) { std::cerr << errno << ":" << strerror(errno) << std::endl; exit(1); } return k; } int getshmhelper(key_t k, int flags) { int shmid = shmget(k, MAX_SIZE, flags); if(shmid < 0) { std::cerr << errno << ":" << strerror(errno) << std::endl; exit(2); } return shmid; } int getshm(key_t k)//获取共享内存 { return getshmhelper(k, IPC_CREAT);//没有就创建,有就获取 } int createshm(key_t k)//创建共享内存 { return getshmhelper(k, IPC_CREAT | IPC_EXCL | 0600);//没有创建,有就报错,这里创建内存需要给对应的权限 } void delshm(int shmid) { if(shmctl(shmid, IPC_RMID, nullptr) == -1) { std::cerr << errno << ":" << strerror(shmid) << std::endl; exit(3); } } void* attachshm(int shmid) { void* p = shmat(shmid, nullptr, 0); if((long long)p == -1L)//因为linux系统是64位,一个地址是8个字节,所以要变成8个字节大小的数据类型做对比 { std::cerr << errno << ":" << strerror(errno) << std::endl; exit(4); } return p; } void detachshm(void* p) { if(shmdt(p) == -1) { std::cerr << errno << ":" << strerror(errno) << std::endl; } } #endif
#include"shm.hpp" int main() { key_t k = getkey(); printf("0x%x\n",k); int shmid = getshm(k);//接收共享内存 printf("shmid : %d\n", shmid); char* p = (char*)attachshm(shmid);//关联 printf("attach sucess, address p: %p\n",p); //使用 const char* str = "hello server, 我是另一个进程,我在和你通信"; pid_t id = getpid(); int count = 0; while(true) { sleep(1); snprintf(p, MAX_SIZE, "%S[pid:%d][消息编号:%d]", str, id, count++); } detachshm(p);//去关联 return 0; }
#include"shm.hpp" int main() { key_t k = getkey(); printf("0x%x\n",k); int shmid = createshm(k);//创建共享内存 printf("shmid : %d\n", shmid); char* p = (char*)attachshm(shmid);//关联 printf("attach sucess, address p: %p\n",p); //使用 while(true) { printf("client say: %s\n",p); sleep(1); } detachshm(p);//去关联 sleep(10); delshm(shmid);//删除共享内存 return 0; }