做免费网站,wordpress函数调用函数,深圳公司做年报网站,打开网站后直接做跳转目录
共享内存的原理
共享内存通信的实现步骤
通信实例 共享内存的原理
原理#xff1a;可以说#xff0c;共享内存是一种最为高效的进程间通信方式。因为进程可以直接读写内存#xff0c;不需要任何数据的复制。为了在多个进程间交换信息#xff0c;内核专门留出一块内…
目录
共享内存的原理
共享内存通信的实现步骤
通信实例 共享内存的原理
原理可以说共享内存是一种最为高效的进程间通信方式。因为进程可以直接读写内存不需要任何数据的复制。为了在多个进程间交换信息内核专门留出一块内存区。这段内存区可以由需要访问的进程将其映射到自己的私有地址空间。因此进程就可以直接读写这一内存区而不需要进行数据的复制从而大大提高了效率。当然由于多个进程共享一段内存因此也需要依靠某种同步机制如互斥锁和信号量等。其原理示意图如下 总结共享内存的通信原理就是让不同的进程看到同一份内存。
共享内存通信的实现步骤
1、创建key,通过调用ftok()生成标识共享内存的key值。
2、创建共享内存使用shmget()向OS申请一段内存。
3、将共享内存和要进行通信的进程关联。
4、进行数据通信和通信数据的处理。
5、通信完成后将所有进程和共享内存去关联。
6、删除共享内存。
注意共享内存的创建只需一个进程进行即可其余要进行通信的进程则需要获取共享内存。
共享内存的创建
调用shmget( )创建共享内存
函数原型
int shmget(key_t key, size_t size, int shmflg);
功能用来创建共享内存。
参数 key:这个共享内存段名字。 size:共享内存大小。 shmflg:由九个权限标志构成它们的用法和创建文件时使用的mode模式标志是一样的。 返回值成功返回一个非负整数即该共享内存段的标识码失败返回-1。 关于shmget( )的第一个参数key,是用于标识共享内存的唯一性通过调用ftok( )使用一定的算法生成的。
ftok原型
key_t ftok(const char *pathname, int proj_id);
参数说明
pathname:一个已存在的路径。
proj_id:项目id。
函数功能将一个已存在的路径和项目id转换为一个key值。
shmget( )的第三个参数shmflg创建共享内存的方式,常见的是用方式 单独使用IPC_CREAT: 创建一个共享内存如果共享内存不存在就创建之如果已经存在获取已经存在的共享内存并返回。IPC_EXCL不能单独使用一般都要配合IPC_CREAT。 IPC_CREAT | IPC_EXCL: 创建一个共享内存如果共享内存不存在就创建之, 如果已经存在则立马出错返回 -- 如果创建成功对应的shm一定是最新的 这里我们先记住在多个进程要使用同一个共享内存时仅需一个进程使用IPC_CREAT | IPC_EXCL组合其余进程单独使用IPC_CREAT。
进程和共享内存关联
shmat()
原型 void *shmat(int shmid, const void *shmaddr, int shmflg);
功能将共享内存段连接到进程地址空间 。
参数 shmid: 共享内存标识。 shmaddr:指定连接的地址。 shmflg:它的两个可能取值是SHM_RND和SHM_RDONLY。 返回值成功返回一个指针指向共享内存第一个节失败返回-1。 说明 shmaddr为NULL核心自动选择一个地址。 shmaddr不为NULL且shmflg无SHM_RND标记则以shmaddr为连接地址。 shmaddr不为NULL且shmflg设置了SHM_RND标记则连接的地址会自动向下调整为SHMLBA的整数倍。 公式shmaddr - (shmaddr % SHMLBA) shmflgSHM_RDONLY表示连接操作用来只读共享内存。 进程和共享内存去关联
shmdt
函数原型
int shmdt(const void *shmaddr); 功能将共享内存段与当前进程脱离。 参数 shmaddr: 由shmat所返回的指针。 返回值成功返回0失败返回-1。 注意将共享内存段与当前进程脱离不等于删除共享内存段。
shmctl( )
原型 int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能用于控制共享内存.
参数 shmid:由shmget返回的共享内存标识码. cmd:将要采取的动作有三个可取值. buf:指向一个保存着共享内存的模式状态和访问权限的数据结构. 返回值成功返回0失败返回-1
通信实例
server.cc
#includecomm.hpp
#includeunistd.hint main(){//1、创建key
key_t k getKey();
coutserver key:toHex(k)endl;//2、创建共享内存
int shmidcreateShm(k,gsize);
coutserver shmid: shmidendl;
sleep(3);//3、将当前进程和共享内存内存关联
char* startattachShm(shmid);
//sleep(20);//4、进行通信
//char* startattachShm(shmid);//init.getStart();
int n0;
while(n30)
{coutclient - server# startendl;sleep(1);n;
}//5、通信完成 将当前进程和共享内存去关联
detachShm(start);//删除共享内存delShm(shmid);return 0;} client.cc
#includecomm.hpp
#includeunistd.h
int main()
{//1、获取共享内存
key_t kgetKey();
coutclient key: toHex(k)endl;int shmidgetShm(k,gsize);
coutclient shmid: shmidendl;//2、将当前进程和共享内存关联
char* startattachShm(shmid);
//3、进行通信
//char* start(char*)attachShm(shmid);//init.getStart();
char cA;
while(cZ)
{start[c-A]c;c;start[c-A]\0;sleep(1);
}
//sleep(15);//4、将当前进程和共享内存去关联
detachShm(start);
return 0;} comm.hpp
#ifndef __COMM_HPP__
#define __COMM_HPP__#includeiostream
#includecerrno
#includecstdio
#includecstring
#includecassert
#includesys/ipc.h
#includesys/shm.h
#includesys/types.h
#includesys/stat.husing namespace std;
#define PATHNAME .
#define PROJID 0X6666const int gsize 4096;key_t getKey()
{key_t k ftok(PATHNAME,0X6666);if(k-1){cerrerror: errno : strerror(errno)endl;exit(1);}return k;
}
string toHex(int x)
{char buffer[64];snprintf(buffer,sizeof buffer,0x%x,x);return buffer;
}static int createShmHelper(key_t k,int gsize,int flog)
{int shmidshmget(k,gsize,flog);if(shmid-1){cerrcerror: errno : strerror(errno)endl;exit(2);}return shmid;
}int createShm(key_t k,int size)
{umask(0);return createShmHelper(k,size,IPC_CREAT|IPC_EXCL|0666);
}int getShm(key_t k,int size)
{return createShmHelper(k,size,IPC_CREAT);
}char* attachShm(int shmid)
{char*start(char*)shmat(shmid,nullptr,0);return start;
}
void detachShm(char*start)
{int nshmdt(start);assert(n!-1);(void)n;
}void delShm(int shmid)
{int nshmctl(shmid,IPC_RMID,nullptr);assert(n!-1);(void)n;
}#endif 运行结果