进程、线程间通信机制

来源:互联网 发布:2016高速公路数据分析 编辑:程序博客网 时间:2024/06/09 14:45

进程、线程间通信机制

1. 管道(pipe)

管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程。

2. 有名管道(named pipe)

有名管道也是半双工的通信方式,但是它允许无亲缘关系的进程间通信。

3. 信号量(semophore)

信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。

4. 消息队列(message queue)

消息队列是由消息链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。

5. 信号(sinal)

信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。

6. 共享内存(share memory)

共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存最快的IPC(Inter-process communication)方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。

7. 套接字(socket)

套接字也是一种进程间的通信机制,与其他通信机制不同的是,它可用于不同机器间的进程通信。

为什么要进行进程间通信(IPC—inter process communication)

  1. 数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M字节之间
  2. 共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立即看到
  3. 通知事件:一个进程需要向另一个或一组进程发送消息,通知它们发生了某种事件(如进程终止时需要通知父进程)。
  4. 资源共享: 多个进程之间共享同样的资源。为了做到这一点,需要内核提供锁和同步机制。
  5. 进程控制: 有些进程希望完成控制另一个进程的执行(如debug进程),此时控制进程希望能够拦截另一进程的所有陷入和异常,并能够及时知道它的状态改变。

线程间通信机制

1. 锁机制

  1. 互斥锁:提供了以排它方式阻止数据结构被并发修改的方法
  2. 读写锁:允许多个线程同时读共享数据,而对写操作互斥
  3. 条件变量:以原子的方式阻塞进程,知道某个特定条件为真为止。对条件测试是在互斥锁的保护下进行的。条件变量始终与互斥锁一起使用

2. 信号量机制:包括无名线程信号量与有名线程信号量

3.信号机制:类似于进程间信号处理

线程间通信的主要目的是用于线程同步,所以线程没有像进程通信中用于数据交换的通信机制

线程同步机制

  1. 临界区(CCriticalSection)

    当多个线程访问一个独占性共享资源时,可以使用临界区对象。拥有临界区的线程可以访问被保护起来的资源或代码段,其他线程若想访问,则被挂起,直到拥有临界区的线程放弃临界区为止。具体应用方式:

    1、定义临界区对象CcriticalSection g_CriticalSection;

    2、 在访问共享资源(代码或变量)之前,先获得临界区对象,g_CriticalSection.Lock();

    3、 访问共享资源后,则放弃临界区对象,g_CriticalSection.Unlock();

  2. 事件(CEvent)

    事件(Event)是WIN32提供的最灵活的线程间同步方式,事件可以处于激发状态(signaled or true)或未激发状态(unsignal or false)。根据状态变迁方式的不同,事件可分为两类:

    (1)手动设置:这种对象只可能用程序手动设置,在需要该事件或者事件发生时,采用SetEvent及ResetEvent来进行设置。
    (2)自动恢复:一旦事件发生并被处理后,自动恢复到没有事件状态,不需要再次设置。

    使用”事件”机制应注意以下事项:
    (1)如果跨进程访问事件,必须对事件命名,在对事件命名的时候,要注意不要与系统命名空间中的其它全局命名对象冲突;
    (2)事件是否要自动恢复;
    (3)事件的初始状态设置。

    由于event对象属于内核对象,故进程B可以调用OpenEvent函数通过对象的名字获得进程A中event对象的句柄,然后将这个句柄用于ResetEvent、SetEvent和WaitForMultipleObjects等函数中。此法可以实现一个进程的线程控制另一进程中线程的运行,例如:

    HANDLE hEvent=OpenEvent(EVENT_ALL_ACCESS,true,"MyEvent"); ResetEvent(hEvent);
  3. 全部变量

  4. 互斥量(CMutex)

    互斥对象和临界区对象非常相似,只是其允许在进程间使用,而临界区只限制与同一进程的各个线程之间使用,但是更节省资源,更有效率。

  5. 信号量(CSemphore)

    当需要一个计数器来限制可以使用某共享资源的线程数目时,可以使用“信号量”对象。CSemaphore类对象保存了对当前访问某一个指定资源的线程的计数值,该计数值是当前还可以使用该资源的线程数目。如果这个计数达到了零,则所有对这个CSemaphore类对象所控制的资源的访问尝试都被放入到一个队列中等待,直到超时或计数值不为零为止。

    信号量是维护0到指定最大值之间的同步对象。信号量状态在其计数大于0时是有信号的,而其计数是0时是无信号的。信号量对象在控制上可以支持有限数量共享资源的访问。

    信号量的特点和用途可用下列几句话定义:

    (1)如果当前资源的数量大于0,则信号量有效;
    (2)如果当前资源数量是0,则信号量无效;
    (3)系统决不允许当前资源的数量为负值;
    (4)当前资源数量决不能大于最大资源数量。

    创建信号量

    HANDLE CreateSemaphore (  PSECURITY_ATTRIBUTE psa,   LONG lInitialCount, //开始时可供使用的资源数   LONG lMaximumCount, //最大资源数  PCTSTR pszName);

    释放信号量

    通过调用ReleaseSemaphore函数,线程就能够对信标的当前资源数量进行递增,该函数原型为:

    BOOL WINAPI ReleaseSemaphore(  HANDLE hSemaphore,  LONG lReleaseCount, //信号量的当前资源数增加lReleaseCount  LPLONG lpPreviousCount  );

    打开信号量 

    和其他核心对象一样,信号量也可以通过名字跨进程访问,打开信号量的API为:

    HANDLE OpenSemaphore (  DWORD fdwAccess,  BOOL bInherithandle,  PCTSTR pszName );

阅读全文
1 0
原创粉丝点击