ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Linux进程通信——共享内存、消息队列和信号量

Linux进程通信——共享内存、消息队列和信号量 共享内存通信共享内存是 Linux 下速度最快的进程间通信方式核心思想是在物理内存中开辟一块共享内存块多个进程通过页表映射将这块物理内存挂载到各自独立的虚拟地址空间中。进程直接读写虚拟地址就等价于操作同一块物理内存省去内核缓冲区拷贝通信效率极高。⚠️ 重要缺陷共享内存没有自带同步互斥机制。多个进程同时读写共享区域会产生竞态问题需要额外搭配信号量、互斥锁来控制访问时序。创建时会使用的函数:获取 shmid:shmget(key_t key(用户给的键值), int size(内存块大小), shmflag(IPC_CREAT|IPC_EXCL|0666))挂接: shmat(shmid, nullptr, 0);返回值为起始虚拟空间地址解除挂接: shmdt(shmaddr(起始虚拟空间地址))删除内存块: shmctl(_shmid, IPC_RMID, nullptr)下面是小demo:基本结构#pragmaonce#includeiostream#includesys/ipc.h#includesys/shm.h#includesys/types.h#includecstdio#includeunistd.h#includecstring#definePATHNAME/tmp#defineproj_id066#defineSIZE128classshared_memory{public:shared_memory():_shmid(-1),_size(SIZE),_start_shmaddr(nullptr){}~shared_memory(){}private:int_shmid;//给用户使用的id,跟fd文件描述符类似功能都是供给用户使用int_size;//内存块大小void*_start_shmaddr;//映射到虚拟地址空间的共享区起始地址};创建内存块和获取:ftok()函数是根据路径加用户给的随便的八进制数字组成的key(标识内存块的唯一值跟inode的作用类似)//创建共享内存块voidCreate(){_shmidGet_shmid(IPC_CREAT|IPC_EXCL|0666);if(_shmid0){std::cerrfile already existsstd::endl;exit(1);}std::coutcreate success!!! shmid _shmidstd::endl;}voidGet(){_shmidGet_shmid(IPC_CREAT);}intGet_key(){key_t keyftok(PATHNAME,proj_id);if(key0){std::cerrkey already existsstd::endl;exit(1);}printf(key:%d\n,key);returnkey;}intGet_shmid(intshmflag){key_t keyGet_key();returnshmget(key,SIZE,shmflag);}挂接、解挂接和删除://挂接到进程中voidsh_attach(){_start_shmaddrshmat(_shmid,nullptr,0);if(_start_shmaddr(void*)(-1))exit(1);std::cout进程挂接共享内存块成功!std::endl;}//解除进程挂接voidsh_Dattach(){intnshmdt(_start_shmaddr);}//删除内存块voidDelete(){intnshmctl(_shmid,IPC_RMID,nullptr);}消息队列通信了解即可消息队列是另一种进程间通信方式通过在内核中维护一个消息链表进程间以「消息」为单位传递数据。相比共享内存它自带一定的同步机制但传输效率较低适合传递小数据量、需要顺序保证的场景。这里仅作了解重点掌握共享内存即可。信号量了解即可信号量主要用于解决共享内存的同步互斥问题本质是一个计数器通过 P 操作申请资源计数器减一和 V 操作释放资源计数器加一来保护临界区。它与共享内存搭配使用这里仅需了解其作用即可不必深入实现细节。后面有更好的信号量来搭配共享内存
返回列表