Windows+C语言 共享内存与互斥量

如有错误,望请赐教,非常感谢。
一、共享内存
1、什么是共享内存?
共享内存,就是多个进程共用一块逻辑内存,每个进程均可对该内存进行读写,是实现进程间通信(本地通信)的一种方式。在Windows和linux平台均可实现,实现流程相似,但调用的函数有所不同,这里只记录Windows平台下的实现方法。

2、实现流程
既然名为共享内存,在使用前肯定要先向系统申请内存。以两个进程共享一块内存为例,进程A调用函数向系统申请一块共享内存(包括共享内存的大小、名称以及安全设置)后,便可以对该内存进行读写。当进程B需要对该内存进行读写操作时,可以根据进程A申请的共享内存的名称打开该内存,然后对内存进行存取。总的来说,就是要先申请,后使用。

Tip:共享内存未提供同步机制,在真正使用过程中,需要额外加信号量或者互斥锁实现同步。

3、所需函数(函数参数可在网上自查)
1)CreateFileMapping()函数
作用:1)创建一个文件映射内核对象并返回该对象的句柄。2)CreateFileMapping()函数也可用于打开共享内存,总结其功能应是创建一个确定名称的文件映射内核对象,若该名称的对象已存在,就打开它。
2)MapViewOfFile()函数
作用:根据句柄将创建的内核对象映射到当前进程的地址空间。
3)OpenFileMapping()函数
作用:根据共享内存的名称打开已经存在的共享内存。
4)UnmapViewOfFile()函数
作用:取消内核对象到进程地址空间的映射,使该内核对象之前映射到进程地址空间所占范围失效,使该地址空间可用于其他分配。
5)CloseHandle()函数
作用:关闭一个内核对象。其中包括文件、文件映射、进程、线程、安全和同步对象等。这里将所创建的互斥锁的句柄释放掉。虽然进程结束后系统会自动释放,但是为避免进程运行中出现负面影响,不再使用的句柄还是应及时释放。

Tip1:打开共享内存时尽量通过调用CreateFileMapping()函数实现。相比于调用OpenFileMapping()函数打开共享内存,使用CreateFileMapping()函数打开共享内存时,可避免打开未创建的共享内存而导致的错误。(例如:进程A创建共享内存,进程B使用OpenFileMapping()函数打开共享内存。启动进程时应先启动进程A,后启动进程B。若误操作先启动进程B,在启动进程A则会报错或者在运行过程中,进程A崩溃,进程B继续运行,再次启动进程A后,无法实现进程A和进程B的通信。使用CreateFileMapping()函数则可以避免这两种情况)
Tip2:共享内存命名时最好在名称前面加上Global,如 “Global\NameOfMappingObject”,可避免共享内存创建后打不开的问题。至于加Global可解决该问题的原理,还不清楚,知道的还请赐教,不胜感激。

二、互斥量
共享内存未提供同步机制,如果不添加互斥量,很有可能出现两个或三个进程对一块内存同时读写的情况。所以在使用共享内存时需要额外添加互斥锁,这里记录了互斥锁的使用,在最后会给出共享内存加互斥锁的例程。
1、什么是互斥量?
互斥量,又称为互斥锁(Mutex), 是一种用来保护临界区的特殊变量, 它可以处于锁定(locked) 状态, 也可以处于解锁(unlocked) 状态;通俗来讲,互斥锁就像一个物件,这个物件在某一时刻只能被一个线程持有。如此一来,便可以通过互斥锁来实现线程的同步。
使用Mutex实现Windows下进程间互斥访问同一资源的原理:
1)如果某一时刻互斥锁是锁定的, 就是某个线程此时正持有这个互斥锁;
2)如果某一时刻互斥锁处于解锁状态,就是此时没有线程持有这个互斥锁;
3)每个互斥锁内部有一个线程等待队列,用来保存等待该互斥锁的线程。当互斥锁处于解锁状态时, 如果某个线程试图获取这个互斥锁, 那么这个线程就可以得到这个互斥锁而不会阻塞;当互斥锁处于锁定状态时, 如果A线程试图获取这个互斥锁, 那么A线程将被挂起,阻塞在互斥锁的等待队列内,当互斥锁被释放后,A进程会获取互斥锁,A进程继续执行。

2、调用函数
1)CreateMutex(&sa, bInitialOwner, szName)函数
参数:
第一个参数是一个指向SECURITY_ATTRIBUTES结构体的指针,一般的情况下,可以是nullptr。
第二个参数类型为BOOL,表示互斥锁创建出来后是否被当前线程持有。
第三个参数类型为字符串(const TCHAR*),是这个互斥锁的名称,如果是nullptr,则互斥锁是匿名的。(系统通过互斥锁名称内核对象,根据名称判断该对象是否已经存在,说法不太恰当,大概是这个意思,请指正)
作用:创建一个互斥锁的内核对象,返回内核对象的句柄。如果该名称互斥锁的内核对象不存在,就创建一个内核对象,如果已将存在,就获取该对象的句柄。
2)WaitForSingleObject(hMutex, dwTimeout)函数,这个函数的作用比较多。这里只介绍第一个参数为互斥锁句柄时的作用。
参数:
第一个参数是等待的互斥锁的句柄
第二个参数是等待的时间(单位:毫秒),如果该参数为INFINITE,则该函数会一直等待下去。
作用:WaitForSingleObject是一种Windows API函数,WaitForSingleObject函数用来检测hHandle事件的信号状态。在某一线程中调用该函数时,当hHandle事件的信号状态为无信号时,线程暂时挂起,如果在挂起的dwMilliseconds毫秒内,线程所等待的对象变为有信号时,则该函数立即返回,线程继续执行;如果超时时间已经到达dwMilliseconds毫秒,但hHandle所指向的对象还没有变成有信号状态,函数照样返回。
3)ReleaseMutex(HANDLE hMutex)函数
参数:释放的互斥锁的句柄。
作用:释放被线程占用的互斥锁,释放后,互斥锁的信号状态变为有信号。
4)CloseHandle(HANDLE hMutex)
参数:要关闭互斥说的句柄。
作用:关闭一个内核对象。其中包括文件、文件映射、进程、线程、安全和同步对象等。这里将所创建的互斥锁的句柄释放掉。虽然进程结束后系统会自动释放,但是为避免进程运行中出现负面影响,不再使用的句柄还是应及时释放。

三、流程
进程A:

创建共享内存句柄hMapFile;
映射共享内存句柄地址空间pBuf;
创建互斥量mutex
 while(1)

    {

        申请mutex;
        
        写pBuf;
        
        释放mutex;

        其他操作;

    }

进程B:

while(1)

{

    申请mutex;
    
    读pBuf;

    释放mutex;

    其他操作;

}
  • 4
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值