php网站建设案例教程,简单的dw制作网页步骤,杰奇网站地图怎么做,怎么用手机做刷赞网站#x1f320; 作者#xff1a;阿亮joy. #x1f386;专栏#xff1a;《学会Linux》 #x1f387; 座右铭#xff1a;每个优秀的人都有一段沉默的时光#xff0c;那段时光是付出了很多努力却得不到结果的日子#xff0c;我们把它叫做扎根 目录#x1f449;system V共… 作者阿亮joy. 专栏《学会Linux》 座右铭每个优秀的人都有一段沉默的时光那段时光是付出了很多努力却得不到结果的日子我们把它叫做扎根 目录system V共享内存共享内存的原理对共享内存的认识共享内存函数system V消息队列了解system V信号量进程互斥总结system V共享内存
共享内存的原理 共享内存区是最快的 IPC 形式。一旦这样的内存映射到共享它的进程的地址空间这些进程间数据传递不再涉及到内核。换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据进程如果要读写直接进行内存即的读和写接口。而之前学习的 pipe 和 fifo 都要通过 read 和 write 系统调用才能进行通信原因就是管道的本质是文件文件是内核中的一种数据结构由操作系统维护3 到 4 G的内核空间用户无权进行直接访问只能通过系统调用来进行访问。注堆栈之间的共享内存属于用户空间内核空间是 3 到 4 G 之间的 1 G 内存空间。 对共享内存的认识 共享内存不属于通信的任意一个进程其属于操作系统由操作系统所管理。管道的本质是文件操作系统已经有相应的内核数据结构来管理文件因此不需要再去设计新的内核数据结构去管理管道。而共享内存是专门为了进程间通信而设计的操作系统可能会有很多共享内存那么操作系统就需要将这些共享内存管理起来。管理的方式是先描述再组织那么共享内存就等于共享内存块加上共享内存对应的内核数据结构。对共享内存的修改包括对属性的修改和对内容的修改。 共享内存内核数据结构
struct shmid_ds
{struct ipc_perm shm_perm; /* operation perms */int shm_segsz; /* size of segment (bytes) */__kernel_time_t shm_atime; /* last attach time */__kernel_time_t shm_dtime; /* last detach time */__kernel_time_t shm_ctime; /* last change time */__kernel_ipc_pid_t shm_cpid; /* pid of creator */__kernel_ipc_pid_t shm_lpid; /* pid of last operator */unsigned short shm_nattch; /* no. of current attaches */unsigned short shm_unused; /* compatibility */void *shm_unused2; /* ditto - used by DIPC */void *shm_unused3; /* unused */
};共享内存函数 shmget 函数的功能是创建或获取共享内存需要指明共享内存的权限失败时的返回值是 -1。 ftok 函数的功能将 pathname 和 project id 经过一定的算法转化成 system V IPC key。pathname 必须存在project id 不能为 0。失败时的返回值是 -1。 shmat 函数的功能是将共享内存段连接到进程地址空间建立页表映射关系。第一个参数是共享内存的标识符 shmid第二个参数是指定连接的地址为 nullptr 时则让操作系统指定连接到合适的地址上第三个参数是 shmflg它的两个可能取值是 SHM_RND 和 SHM_RDONLY。shmflg 等于 SHM_RDONLY 时表示连接操作用来只读共享内存。成功返回一个指针指向共享内存第一个字节失败返回 (void*) -1。 shmdt 函数的功能是将共享内存段与当前进程脱离。shmaddr 是由 shmat 函数所返回的指针成功返回 0失败返回 -1。注意将共享内存段与当前进程脱离不等于删除共享内存段。shmctl 函数的功能是用于控制共享内存。shmid 是由 shmget 函数返回的共享内存标识符cmd 是将要采取的动作有三个可取值buf 为指向一个保存着共享内存的模式状态和访问权限的数据结构不关心共享内存的内核数据结果是buf 可以设置为 nullptr。 注当进程运行结束进程创建的共享内存还会存在。这是因为 system V IPC 资源的生命周期是随着其内核的其内核可以通过代码删除上述的 shmctl 函数也可以通过 ipcrm -m shmid 指令手动删除共享内存。使用 ipcs -m 指令可以查看操作系统中已经创建的共享内存。 key 和 shmid 的区别只有在创建共享内存时使用到 key。大部分情况下用户都是通过 shmid 来访问共享内存的。 客户端和服务端的模拟实现
# Makefile
.PHONY:all
all:shmClient shmServershmClient:shmClient.ccg -o $ $^ -stdc11
shmServer:shmServer.ccg -o $ $^ -stdc11.PHONY:clean
clean:rm -f shmClient shmServer// Log.hpp
#ifndef _LOG_H_
#define _LOG_H_#include iostream
#include ctime#define Debug 0
#define Notice 1
#define Warning 2
#define Error 3const std::string msg[]
{Debug,Notice,Warning,Error
};std::ostream Log(std::string message, int level)
{std::cout | (unsigned)time(nullptr) | msg[level] | message;return std::cout;
}#endif// Comm.h
#pragma once#include iostream
#include cstdio
#include cassert
#include string
#include cstring
#include unistd.h
#include sys/types.h
#include sys/ipc.h
#include sys/shm.h
#include sys/stat.h
#include fcntl.h
#include Log.hppusing namespace std; // 将std直接展开简答,但不推荐#define PATH_NAME /home/Joy
#define PROJ_ID 0x66
#define SHM_SIZE 4096 //共享内存的大小,最好是页(PAGE:4096KB)的整数倍// 将十进制转为十六进制
string TransToHex(key_t k)
{char buffer[32];snprintf(buffer, sizeof buffer, 0x%x, k);return buffer;
}// shmServer.cc
#include Comm.hppint main()
{// 1. 创建公共的key值key_t k ftok(PATH_NAME, PROJ_ID);assert(k ! -1);Log(create key done, Debug) server key: TransToHex(k) endl;// 2. 创建共享内存(建议通信的发起者创建一个全新的共享内存)// 创建共享内存是也要指定权限int shmid shmget(k, SHM_SIZE, IPC_CREAT | IPC_EXCL | 0666);if(shmid -1){Log(create shm fail, Debug) endl;exit(1);}Log(create shm done, Debug) shmid: shmid endl;// 3. 建立页表映射(将共享内存挂接到当前进程地址空间)char* shmaddr (char*)shmat(shmid, nullptr, 0);if(shmaddr (char*)-1){Log(attch shm fail, Debug) shmid: shmid endl;}Log(attch shm done, Debug) shmid: shmid endl;// 4. 进程通信// 可以将共享内存看成一个大的字符串// 注意共享内存创建好全部都会被置成0for(;;){printf(%s\n, shmaddr);if(strcmp(shmaddr, quit) 0) break;sleep(1);}// 5. 将指定的共享内存从自己的进程空间中去关联int n shmdt(shmaddr);assert(n ! -1);(void)n;Log(detach shm done, Debug) shmid: shmid endl; // 6. 删除共享内存,IPC_RMID即便还有进程挂接该共享内存,依旧删除该共享内存n shmctl(shmid, IPC_RMID, nullptr);assert(n ! -1);(void)n;Log(delete shm done, Debug) shmid: shmid endl; return 0;
}// shmClient.cc
#include Comm.hppint main()
{// 1. 客户端只需要获取服务端创建的共享内存即可key_t k ftok(PATH_NAME, PROJ_ID);if(k -1){Log(create key fail, Error) client key: TransToHex(k) endl;exit(1);}Log(create key done, Debug) client key: TransToHex(k) endl;// 2. 获取共享内存int shmid shmget(k, SHM_SIZE, 0);if(shmid -1){Log(create shm fail, Error) client key: TransToHex(k) endl;exit(2);}Log(create shm done, Debug) client key: TransToHex(k) endl;// 3. 挂接共享内存char* shmaddr (char*)shmat(shmid, nullptr, 0);if(shmaddr (char*)-1){Log(attach shm failed, Error) client key : TransToHex(k) endl;exit(3);}Log(attach shm success, Debug) client key : TransToHex(k) endl;// 4. 使用,客户端将共享内存看做一个char类型的bufferwhile(true){ssize_t s read(0, shmaddr, SHM_SIZE - 1);if(s 0){shmaddr[s - 1] \0; // 清除\nif(strcmp(shmaddr, quit) 0) break;}}// 以下代码是自动向共享内存中写入数据// char a a;// for(; a z; a)// {// // shmaddr[a-a] a;// // 我们是每一次都向shmaddr[共享内存的起始地址]写入// // snprintf(shmaddr, SHM_SIZE - 1, hello server, 我是其他进程,我的pid: %d, inc: %c\n, getpid(), a);// // sleep(5);// }// strcpy(shmaddr, quit);// 5. 去关联int n shmdt(shmaddr);assert(n ! -1);Log(detach shm done, Debug) client key: TransToHex(k) endl;// 客户端不需要删除共享内存return 0;
}现象 就算客户端没有向共享内存中写入数据服务端也会一直读取。只要通信双方使用共享内存一方直接向共享内存中写入数据另一方就可以马上看到对方写入的数据。共享内存是所有进程间通信IPC中速度最快的因为其不需要过多的拷贝不需要将数据给操作系统 以共享内存的方式进行进程间通信缺乏访问控制会带来并发控制比如写端还没将全部数据写入读端就已经开始读取了这将会带来巨大的问题 给共享内存添加访问控制
// Comm.hpp
#pragma once#include iostream
#include cstdio
#include cassert
#include string
#include cstring
#include unistd.h
#include sys/types.h
#include sys/ipc.h
#include sys/shm.h
#include sys/stat.h
#include fcntl.h
#include Log.hppusing namespace std; // 将std直接展开简答,但不推荐#define PATH_NAME /home/Joy
#define PROJ_ID 0x66
#define SHM_SIZE 4096 //共享内存的大小,最好是页(PAGE:4096KB)的整数倍
#define FIFO_NAME ./fifo// 将十进制转为十六进制
string TransToHex(key_t k)
{char buffer[32];snprintf(buffer, sizeof buffer, 0x%x, k);return buffer;
}class Init
{
public:Init(){umask(0);int n mkfifo(FIFO_NAME, 0666);assert(n 0);(void)n;Log(create fifo success, Notice) endl;}~Init(){unlink(FIFO_NAME);Log(delete fifo success, Notice) endl;}
};#define READ O_RDONLY
#define WRITE O_WRONLYint OpenFIFO(std::string pathname, int flags)
{int fd open(pathname.c_str(), flags);assert(fd ! -1);return fd;
}// 服务端等待客户端唤醒
void Wait(int fd)
{Log(等待中......, Notice) endl;uint32_t temp 0;ssize_t s read(fd, temp, sizeof(uint32_t));assert(s sizeof(uint32_t));(void)s;}// 客户端唤醒服务端
void Signal(int fd)
{uint32_t temp 1;ssize_t s write(fd, temp, sizeof(uint32_t));assert(s sizeof(uint32_t));(void)s;Log(唤醒中......, Notice) endl;
}void CloseFIFO(int fd)
{close(fd);
}// shmServer.cc
#include Comm.hpp// 对应的程序在加载的时候,会自动构建全局变量,就要调用该类的构造函数 -- 创建管道文件
// 程序退出的时候,全局变量会被析构,自动调用析构函数,会自动删除管道文件
Init init; // 管道文件只有在服务端创建即可int main()
{// 1. 创建公共的key值key_t k ftok(PATH_NAME, PROJ_ID);assert(k ! -1);Log(create key done, Debug) server key: TransToHex(k) endl;// 2. 创建共享内存(建议通信的发起者创建一个全新的共享内存)// 创建共享内存是也要指定权限int shmid shmget(k, SHM_SIZE, IPC_CREAT | IPC_EXCL | 0666);if(shmid -1){Log(create shm fail, Debug) endl;exit(1);}Log(create shm done, Debug) shmid: shmid endl;// 3. 建立页表映射(将共享内存挂接到当前进程地址空间)char* shmaddr (char*)shmat(shmid, nullptr, 0);if(shmaddr (char*)-1){Log(attch shm fail, Debug) shmid: shmid endl;}Log(attch shm done, Debug) shmid: shmid endl;// 4. 进程通信// 可以将共享内存看成一个大的字符串// 注意共享内存创建好全部都会被置成0// 服务端以读方式打开管道文件int fd OpenFIFO(FIFO_NAME, READ);for(;;){// 服务端等待客户端唤醒Wait(fd);printf(%s\n, shmaddr);if(strcmp(shmaddr, quit) 0) break;//sleep(1);}// 5. 将指定的共享内存从自己的进程空间中去关联int n shmdt(shmaddr);assert(n ! -1);(void)n;Log(detach shm done, Debug) shmid: shmid endl; // 6. 删除共享内存,IPC_RMID即便还有进程挂接该共享内存,依旧删除该共享内存n shmctl(shmid, IPC_RMID, nullptr);assert(n ! -1);(void)n;Log(delete shm done, Debug) shmid: shmid endl;CloseFIFO(fd); return 0;
}// shmClient.cc
#include Comm.hppint main()
{// 1. 客户端只需要获取服务端创建的共享内存即可key_t k ftok(PATH_NAME, PROJ_ID);if(k -1){Log(create key fail, Error) client key: TransToHex(k) endl;exit(1);}Log(create key done, Debug) client key: TransToHex(k) endl;// 2. 获取共享内存int shmid shmget(k, SHM_SIZE, 0);if(shmid -1){Log(create shm fail, Error) client key: TransToHex(k) endl;exit(2);}Log(create shm done, Debug) client key: TransToHex(k) endl;// 3. 挂接共享内存char* shmaddr (char*)shmat(shmid, nullptr, 0);if(shmaddr (char*)-1){Log(attach shm failed, Error) client key : TransToHex(k) endl;exit(3);}Log(attach shm success, Debug) client key : TransToHex(k) endl;// 客户端以写方式打开管道文件int fd OpenFIFO(FIFO_NAME, WRITE);// 4. 使用,客户端将共享内存看做一个char类型的bufferwhile(true){ssize_t s read(0, shmaddr, SHM_SIZE - 1);if(s 0){shmaddr[s - 1] \0; // 清除\nSignal(fd); // 客户端唤醒服务端if(strcmp(shmaddr, quit) 0) break;}}// 以下代码是自动向共享内存中写入数据// char a a;// for(; a z; a)// {// // shmaddr[a-a] a;// // 我们是每一次都向shmaddr[共享内存的起始地址]写入// // snprintf(shmaddr, SHM_SIZE - 1, hello server, 我是其他进程,我的pid: %d, inc: %c\n, getpid(), a);// // sleep(5);// }// strcpy(shmaddr, quit);// 5. 去关联int n shmdt(shmaddr);assert(n ! -1);Log(detach shm done, Debug) client key: TransToHex(k) endl;// 客户端不需要删除共享内存return 0;
}因为管道具有访问控制我们只要给共享内存加个管道就可以实现进程通信的访问控制了。该管道文件并不是用来通信的而是用来访问控制的管道文件内的数据是多少并不重要
system V消息队列了解 消息队列先进先出提供了一个从一个进程向另外一个进程发送一块数据的方法。每个数据块都被认为是有一个类型接收者进程接收的数据块可以有不同的类型值。IPC 资源必须删除否则不会自动清除除非重启所以 system V IPC 资源的生命周期随内核。常用系统调用ftokmsgget创建消息队列msgctl控制消息队列msgsnd向消息队列发送数据msgrcv从消息队列中读取数据等。 注共享内存只有在当前映射连接数为 0 时才会被删除释放。 system V信号量
信号量主要用于同步和互斥的下面先来看看什么是同步和互斥。
进程互斥 我们之前学习的所有的通信方式本质都是优先解决一个问题让不同的进程看到同一个资源让不同的进程看到同一个资源比如共享内存也带了一些时序问题造成数据不一致问题。多个进程执行流看到的公共的一份资源称为临界资源或互斥资源。进程中访问临界资源的代码称为临界区。多个执行流互相运行时互相干扰是因为我们不加保护地访问了同样的资源临界资源。在非临界区多个执行流不会互相干扰。为了更好地进行临界区的保护可以让多执行流在任何时候都只有一个进程进入临界区这种特征称为互斥。原子性是指事务的不可分割性一个事务的所有操作要么不间断地全部被执行要么一个也没有执行没有任何其他的中间状态。 通过看电影买票的例子来理解信号量 信号量是对临界资源的预定机制
总结 本篇博客主要讲解了什么是共享内存、共享内存的原理、用共享内存实现客户端和服务端的通信、什么是消息队列、消息量以及进程互斥等等。那么以上就是本篇博客的全部内容了如果大家觉得有收获的话可以点个三连支持一下谢谢大家❣️
文章转载自: http://www.morning.sfnjr.cn.gov.cn.sfnjr.cn http://www.morning.bppml.cn.gov.cn.bppml.cn http://www.morning.trzzm.cn.gov.cn.trzzm.cn http://www.morning.plhhd.cn.gov.cn.plhhd.cn http://www.morning.qmfhh.cn.gov.cn.qmfhh.cn http://www.morning.rzdpd.cn.gov.cn.rzdpd.cn http://www.morning.kwqcy.cn.gov.cn.kwqcy.cn http://www.morning.ygqhd.cn.gov.cn.ygqhd.cn http://www.morning.bdzps.cn.gov.cn.bdzps.cn http://www.morning.kbqws.cn.gov.cn.kbqws.cn http://www.morning.qcwck.cn.gov.cn.qcwck.cn http://www.morning.sgrwd.cn.gov.cn.sgrwd.cn http://www.morning.zffps.cn.gov.cn.zffps.cn http://www.morning.dmsxd.cn.gov.cn.dmsxd.cn http://www.morning.yhglt.cn.gov.cn.yhglt.cn http://www.morning.ntzbr.cn.gov.cn.ntzbr.cn http://www.morning.pmghz.cn.gov.cn.pmghz.cn http://www.morning.nbsbn.cn.gov.cn.nbsbn.cn http://www.morning.pwmpn.cn.gov.cn.pwmpn.cn http://www.morning.xwnnp.cn.gov.cn.xwnnp.cn http://www.morning.bdzps.cn.gov.cn.bdzps.cn http://www.morning.stpkz.cn.gov.cn.stpkz.cn http://www.morning.nykzl.cn.gov.cn.nykzl.cn http://www.morning.xtqr.cn.gov.cn.xtqr.cn http://www.morning.nwnbq.cn.gov.cn.nwnbq.cn http://www.morning.qnbzs.cn.gov.cn.qnbzs.cn http://www.morning.zwznz.cn.gov.cn.zwznz.cn http://www.morning.nynpf.cn.gov.cn.nynpf.cn http://www.morning.jqswf.cn.gov.cn.jqswf.cn http://www.morning.wschl.cn.gov.cn.wschl.cn http://www.morning.mlffg.cn.gov.cn.mlffg.cn http://www.morning.nckzt.cn.gov.cn.nckzt.cn http://www.morning.nxkyr.cn.gov.cn.nxkyr.cn http://www.morning.zwdrz.cn.gov.cn.zwdrz.cn http://www.morning.mhmcr.cn.gov.cn.mhmcr.cn http://www.morning.jrqbr.cn.gov.cn.jrqbr.cn http://www.morning.rdymd.cn.gov.cn.rdymd.cn http://www.morning.tqbqb.cn.gov.cn.tqbqb.cn http://www.morning.kjnfs.cn.gov.cn.kjnfs.cn http://www.morning.gbfzy.cn.gov.cn.gbfzy.cn http://www.morning.cbczs.cn.gov.cn.cbczs.cn http://www.morning.mfmbn.cn.gov.cn.mfmbn.cn http://www.morning.krklj.cn.gov.cn.krklj.cn http://www.morning.rhkmn.cn.gov.cn.rhkmn.cn http://www.morning.qlrwf.cn.gov.cn.qlrwf.cn http://www.morning.bflws.cn.gov.cn.bflws.cn http://www.morning.slkqd.cn.gov.cn.slkqd.cn http://www.morning.zzaxr.cn.gov.cn.zzaxr.cn http://www.morning.bnfsw.cn.gov.cn.bnfsw.cn http://www.morning.rmxgk.cn.gov.cn.rmxgk.cn http://www.morning.hfytgp.cn.gov.cn.hfytgp.cn http://www.morning.yqpck.cn.gov.cn.yqpck.cn http://www.morning.krlsz.cn.gov.cn.krlsz.cn http://www.morning.xqndf.cn.gov.cn.xqndf.cn http://www.morning.tsnq.cn.gov.cn.tsnq.cn http://www.morning.cknrs.cn.gov.cn.cknrs.cn http://www.morning.bgpb.cn.gov.cn.bgpb.cn http://www.morning.qzpsk.cn.gov.cn.qzpsk.cn http://www.morning.pmlgr.cn.gov.cn.pmlgr.cn http://www.morning.sgpny.cn.gov.cn.sgpny.cn http://www.morning.gbybx.cn.gov.cn.gbybx.cn http://www.morning.jfqqs.cn.gov.cn.jfqqs.cn http://www.morning.ddtdy.cn.gov.cn.ddtdy.cn http://www.morning.qbfqb.cn.gov.cn.qbfqb.cn http://www.morning.rhmpk.cn.gov.cn.rhmpk.cn http://www.morning.qwwcf.cn.gov.cn.qwwcf.cn http://www.morning.qngcq.cn.gov.cn.qngcq.cn http://www.morning.bfhrj.cn.gov.cn.bfhrj.cn http://www.morning.xkqjw.cn.gov.cn.xkqjw.cn http://www.morning.bmgdl.cn.gov.cn.bmgdl.cn http://www.morning.rnqnp.cn.gov.cn.rnqnp.cn http://www.morning.rkbly.cn.gov.cn.rkbly.cn http://www.morning.pjzcp.cn.gov.cn.pjzcp.cn http://www.morning.fdfsh.cn.gov.cn.fdfsh.cn http://www.morning.krkwh.cn.gov.cn.krkwh.cn http://www.morning.qpqb.cn.gov.cn.qpqb.cn http://www.morning.nrxsl.cn.gov.cn.nrxsl.cn http://www.morning.qdscb.cn.gov.cn.qdscb.cn http://www.morning.dqrhz.cn.gov.cn.dqrhz.cn http://www.morning.swimstaracademy.cn.gov.cn.swimstaracademy.cn