返回

通过信号量和信号实现进程间通信

前端

进程间通信之信号量和信号

在上一篇博文中,我们探讨了共享内存,并编写了一个示例来展示如何实现内存通信,读写内存数据。我们的示例只涉及单次写入和单次读取的过程。然而,在现实世界的应用程序中,进程通常需要在一段时间内同步操作,或者需要信号来通知其他进程事件的发生。为了满足这些需求,Unix系统提供了信号量和信号机制。

信号量

信号量是一种数据结构,用于协调对共享资源的访问。它是一个整数值,初始化时为正数。当进程需要访问共享资源时,它会检查信号量的值。如果信号量为正,进程可以继续执行。如果信号量为 0 或负,则进程将被阻塞,直到信号量变为正值。

当进程完成对共享资源的访问后,它会对信号量进行递增操作,以释放对该资源的访问权限。其他进程现在可以检查信号量并继续执行。

信号量的主要优点是它们提供了一种高效且可靠的机制来协调对共享资源的访问。它们特别适合需要防止竞争条件的应用程序。

信号

信号是一种异步通知机制,用于向进程发送事件通知。每个信号都有一个唯一的编号。进程可以注册对特定信号的处理程序。当系统向进程发送信号时,将调用处理程序。

信号非常适合需要通知进程发生事件的应用程序。例如,信号可用于通知进程有新的数据可用、有进程终止或系统即将关闭。

使用信号量和信号

以下是使用信号量和信号的示例代码:

// 包含必要的头文件
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <signal.h>

// 定义信号量的名称
#define SEM_NAME "/my_sem"

// 定义信号的编号
#define SIG_NUM SIGUSR1

// 全局变量
int shared_data = 0;
sem_t *sem;

// 信号处理程序
void sig_handler(int signo)
{
  // 当进程接收到信号时执行此函数
  printf("接收到信号 %d\n", signo);
  sem_post(sem);
}

int main()
{
  // 创建信号量
  sem = sem_open(SEM_NAME, O_CREAT, 0666, 1);
  if (sem == SEM_FAILED)
  {
    perror("sem_open");
    exit(EXIT_FAILURE);
  }

  // 安装信号处理程序
  if (signal(SIG_NUM, sig_handler) == SIG_ERR)
  {
    perror("signal");
    exit(EXIT_FAILURE);
  }

  // 进程 1 的操作
  while (1)
  {
    // 获取信号量
    sem_wait(sem);

    // 访问共享数据
    shared_data++;
    printf("进程 1: shared_data = %d\n", shared_data);

    // 休眠一段时间
    sleep(1);

    // 信号其他进程
    kill(getpid(), SIG_NUM);
  }

  return 0;
}

在这个示例中,进程 1 不断递增共享数据。每次递增之前,它都会获取信号量来防止其他进程同时访问共享数据。进程 1 还会发送信号给其他进程,通知它们可以访问共享数据了。

结论

信号量和信号是用于进程间通信的强大机制。它们提供了一种高效且可靠的方式来协调对共享资源的访问以及通知进程事件的发生。通过理解和使用这些机制,开发人员可以编写更高效、更可靠的并发应用程序。