程序设计:信号量 写优先的读写互斥对象(完整源码 代码详解)2

编程入门 行业动态 更新时间:2024-10-10 13:22:59

程序设计:<a href=https://www.elefans.com/category/jswz/34/1769130.html style=信号量 写优先的读写互斥对象(完整源码 代码详解)2"/>

程序设计:信号量 写优先的读写互斥对象(完整源码 代码详解)2

        承接上文:程序设计:信号量 写优先的读写互斥对象(完整源码 代码详解)-CSDN博客

        完整源码在上文已经给出。本文解释其中的主要代码。以下代码删除了一些辅助功能。

目录

一、核心数据

二、创建信号量

三、销毁信号量

四、连接到信号量

五、获取信号量创建时间

 六、读锁定

七、写锁定

八、释放读锁定

九、释放写锁定


一、核心数据

		int sem_id{ -1 };//信号量ID

        一切都围绕这个进行。sem_id是系统的信号量的标识,所有信号量操作都针对这个。

        这个值通过创建(semget)获得,然后把获得的ID存储在合适的位置,其它程序可以通过ID操作这个信号量。

二、创建信号量

		//创建新信号量bool Create(){#ifdef _LINUXOSsem_id = semget(IPC_PRIVATE, 4, IPC_CREAT | IPC_EXCL | 0666);
#elsesem_id = semget(IPC_PRIVATE, 4, IPC_CREAT | IPC_EXCL | SEM_R | (SEM_R >> 3) | (SEM_R >> 6) | SEM_A | (SEM_A >> 3) | (SEM_A >> 6));
#endifif (-1 == sem_id){m_errid = __LINE__;m_errmsg.str("");m_errmsg << errno2str();return false;}union semun sem;sem.val = 1;if (semctl(sem_id, 0, SETVAL, sem) < 0){m_errid = __LINE__;m_errmsg.str("");m_errmsg << errno2str();return false;}sem.val = 0;if (semctl(sem_id, 1, SETVAL, sem) < 0){m_errid = __LINE__;m_errmsg.str("");m_errmsg << errno2str();return false;}sem.val = 0;if (semctl(sem_id, 2, SETVAL, sem) < 0){m_errid = __LINE__;m_errmsg.str("");m_errmsg << errno2str();return false;}sem.val = 0;if (semctl(sem_id, 3, SETVAL, sem) < 0){m_errid = __LINE__;m_errmsg.str("");m_errmsg << errno2str();return false;}return true;}

        这个代码首先创建一个信号量,包含四个值。第一个参数key为IPC_PRIVATE,表示由系统分配。由于信号量是全系统范围的,因此必须保证在全系统范围内没有冲突。对于socket端口,由国际组织分配服务端口号,而对于信号量,并没有什么国际组织管理这个,所以我总是使用系统分配。还有些老代码喜欢用磁盘路径创建一个唯一值作为key,但是如果路径被删除重建,key就会改变,从而导致互斥失败。所以归根结底,没有靠谱的方法。

        创建信号量之后就要初始化每个值,然后才能使用。

三、销毁信号量

        一般情况下创建了就不用删除了,除非发生了BUG。

		//删除信号量bool Destory(){union semun sem;sem.val = 0;if (semctl(sem_id, 0, IPC_RMID, sem) < 0){m_errid = __LINE__;m_errmsg.str("");m_errmsg << errno2str();return false;}else{sem_id = -1;return true;}}

四、连接到信号量

        这个功能只是设置这个类要操作的sem_id而已。作为一个实用代码,做了一些检查,以确认这个信号量是自己系统的信号量,而不是别的系统的。

		bool Attach(int id, time_t const& ctime){sem_id = id;//检查time_t tmp_ctime;if (!_GetCTime(tmp_ctime)){m_errid = __LINE__;m_errmsg.str("");m_errmsg << errno2str();sem_id = -1;return false;}else{if (tmp_ctime != ctime){m_errid = __LINE__;m_errmsg.str("");m_errmsg << "ctime不匹配";sem_id = -1;return false;}}return -1 != sem_id;}

        具体检查方式就是检查信号量的创建时间和预期是否一致。信号量创建时间和ID是一起保存的。

五、获取信号量创建时间

        创建时间可以用来确认信号量确实是自己的。

		bool _GetCTime(time_t& ctime)const{semid_ds ds;union semun sem;int ret;memset(&ds, 0, sizeof(semid_ds));sem.buf = &ds;if ((ret = semctl(sem_id, 0, IPC_STAT, sem)) < 0){*(int*)&m_errid = __LINE__;(*(stringstream*)&m_errmsg).str("");*(stringstream*)&m_errmsg << "获得sem " << sem_id << " 状态出错(" << ret << "):" << errno2str();return false;}ctime = ds.sem_ctime;return true;}

 六、读锁定

		bool _RLock(bool no_wait)const{constexpr short int flag = SEM_UNDO;constexpr short int flag_nowait = SEM_UNDO | IPC_NOWAIT;struct sembuf sops_wait[] = { {1,0,flag},{2,1,flag},{3,0,flag} };struct sembuf sops_nowait[] = { {1,0,flag_nowait},{2,1,flag_nowait},{3,0,flag_nowait} };struct sembuf* sops = sops_wait;if (no_wait)sops = sops_nowait;if (-1 != semop(sem_id, sops, 3)){after_RLock();return true;}else{*(int*)&m_errid = __LINE__;(*(stringstream*)&m_errmsg).str("");*(stringstream*)&m_errmsg << errno2str();return false;}}

七、写锁定

		bool _WLock(bool no_wait)const{STATIC_C short int const flag = SEM_UNDO;STATIC_C short int const flag_nowait = SEM_UNDO | IPC_NOWAIT;struct sembuf sops_wait[] = { {0,-1,flag},{1,1,flag},{2,0,flag},{3,1,flag} };struct sembuf sops_nowait[] = { {0,-1,flag_nowait},{1,1,flag_nowait},{2,0,flag_nowait},{3,1,flag_nowait},{3,-1,flag_nowait} };struct sembuf* sops = sops_wait;if (no_wait)sops = sops_nowait;//先增加写等待数,阻止读请求被激活if (-1 == semop(sem_id, &sops[3], 1)){*(int*)&m_errid = __LINE__;(*(stringstream*)&m_errmsg).str("");*(stringstream*)&m_errmsg << errno2str();return false;}if (-1 != semop(sem_id, sops, 3)){after_WLock();return true;}else if (no_wait && EAGAIN == errno){//撤销写等待if (-1 == semop(sem_id, &sops[4], 1)){*(int*)&m_errid = __LINE__;(*(stringstream*)&m_errmsg).str("");*(stringstream*)&m_errmsg << errno2str();}return false;}else{*(int*)&m_errid = __LINE__;(*(stringstream*)&m_errmsg).str("");*(stringstream*)&m_errmsg << errno2str();return false;}}

八、释放读锁定

		bool RUnLock()const{struct sembuf sops[] = { {2,-1,SEM_UNDO} };if (-1 != semop(sem_id, sops, 1)){after_RUnLock();return true;}else{*(int*)&m_errid = __LINE__;(*(stringstream*)&m_errmsg).str("");*(stringstream*)&m_errmsg << errno2str();return false;}}

九、释放写锁定

		bool WUnLock()const{struct sembuf sops[] = { {0,1,SEM_UNDO},{1,-1,SEM_UNDO},{3,-1,SEM_UNDO} };if (-1 != semop(sem_id, sops, 3)){after_WUnLock();return true;}else{*(int*)&m_errid = __LINE__;(*(stringstream*)&m_errmsg).str("");*(stringstream*)&m_errmsg << errno2str();return false;}}

(这里是结束)

更多推荐

程序设计:信号量 写优先的读写互斥对象(完整源码 代码详解)2

本文发布于:2023-11-15 19:41:36,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1605211.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:信号量   程序设计   详解   源码   对象

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!