【Linux 进程间通信 —— systemV 信号量】

SystemV 信号量

信号量相关概念

信号量是一种用于实现进程间同步和互斥的机制。它可以用来控制对共享资源的访问,确保多个进程之间的互斥访问。信号量可以被认为是一个计数器,它用来表示某个共享资源的可用数量。当一个进程想要访问共享资源时,它必须首先获取信号量,然后才能执行对资源的操作。在操作完成后,进程需要释放信号量,以便其他进程可以继续使用资源。

信号量有两种类型:二进制信号量和计数信号量。

  1. 二进制信号量: 二进制信号量只有两个取值:0 和 1。它通常用于实现互斥锁(Mutex),以确保临界资源一次只能被一个进程访问。当信号量的值为 1 时,表示资源可用,进程可以访问资源;当值为 0 时,表示资源已被占用,其他进程需要等待。

  2. 计数信号量: 计数信号量的取值范围大于等于 0。它用来表示某个资源的可用数量,允许多个进程同时访问资源,但是需要控制访问的数量。当一个进程获取计数信号量时,信号量的值会减少;当释放信号量时,值会增加。

信号量数据结构

struct semid_ds {
	struct ipc_perm sem_perm;       /* permissions .. see ipc.h */
	__kernel_time_t sem_otime;      /* last semop time */
	__kernel_time_t sem_ctime;      /* last change time */
	struct sem  *sem_base;      /* ptr to first semaphore in array */
	struct sem_queue *sem_pending;      /* pending operations to be processed */
	struct sem_queue **sem_pending_last;    /* last pending operation */
	struct sem_undo *undo;          /* undo requests on this array */
	unsigned short  sem_nsems;      /* no. of semaphores in array */
};

信号量数据结构的第一个成员也是ipc_perm类型的结构体变量,ipc_perm结构体的定义如下:

struct ipc_perm{
	__kernel_key_t  key;
	__kernel_uid_t  uid;
	__kernel_gid_t  gid;
	__kernel_uid_t  cuid;
	__kernel_gid_t  cgid;
	__kernel_mode_t mode;
	unsigned short  seq;
};

struct ipc_perm

struct ipc_perm 是 Linux 中用于描述 System V IPC 对象权限的结构体。它定义了 IPC 对象的关键信息,包括键值、用户 ID、组 ID、创建者用户 ID、创建者组 ID、访问权限模式和序列号等。

  • key:IPC 对象的键值,用于标识该对象的唯一性。
  • uid:IPC 对象的所有者用户 ID,表示该对象的创建者。
  • gid:IPC 对象的所有者组 ID,表示该对象的创建者所属的组。
  • cuid:创建者的有效用户 ID(effective user ID),用于权限检查。
  • cgid:创建者的有效组 ID(effective group ID),用于权限检查。
  • mode:IPC 对象的访问权限模式,指定了对象的读、写和执行权限等。
  • seq:IPC 对象的序列号,用于区分不同的对象。

这些成员变量组成了 IPC 对象的权限信息,用于控制对对象的访问和操作。在创建 IPC 对象时,会分配相应的权限,以便确定对象的所有者和访问权限。在操作 IPC 对象时,会使用这些权限信息进行权限检查,以确保操作的合法性和安全性。

struct ipc_perm 的定义通常位于头文件 <linux/ipc.h> 中,它是 Linux 中实现 System V IPC 机制的基础之一,为进程间通信提供了一种可靠的权限控制机制。

信号量相关函数

信号量集的创建

创建信号量集我们需要用semget函数,semget函数的函数原型如下:

int semget(key_t key, int nsems, int semflg);

在这里插入图片描述

key:用于标识信号量集的键值。不同的进程可以通过相同的键值来访问同一个信号量集。

nsems:表示要创建的信号量的数量,或者用于获取已存在信号量集的数量。每个信号量集包含多个信号量。

semflg:是一个标志参数,用于指定创建信号量的权限和行为。可以通过按位或操作来组合多个选项。

参数:

  • key:用于标识信号量集的键值。不同的进程可以通过相同的键值来访问同一个信号量集。

  • nsems:表示要创建的信号量的数量,或者用于获取已存在信号量集的数量。每个信号量集包含多个信号量。

  • semflg:是一个标志参数,用于指定创建信号量的权限和行为。可以通过按位或操作来组合多个选项。

返回值:

  • 成功调用 semget 函数将返回一个信号量集的标识符,即一个非负整数。这个标识符将用于后续对该信号量集进行操作,比如获取信号量的值、设置信号量的值、删除信号量集等。

  • 如果调用失败,semget 函数将返回 -1,并设置全局变量 errno 来指示错误的原因。

semget 函数是 System V IPC 机制中创建和获取信号量的基础操作之一。通常情况下,它与 semop 和 semctl 函数一起使用,用于实现进程间的同步和互斥,以及对共享资源的访问控制。

进程互斥

什么是进程互斥

在并发编程中,多个进程或线程可能同时访问共享资源,如果不加以限制,就会出现竞态条件(Race Condition)。竞态条件指的是多个进程或线程在相同的资源上进行读写操作时,由于执行顺序的不确定性,导致程序的行为出现异常或结果不一致的情况。

为什么需要进程互斥

为了避免竞态条件,需要引入进程互斥的概念。常见的实现进程互斥的机制包括互斥锁(Mutex)、信号量(Semaphore)和临界区(Critical Section)等。这些机制都可以确保在任意时刻只有一个进程或线程可以访问共享资源,其他进程或线程需要等待。

如何实现进程互斥

最常用的机制之一是互斥锁(Mutex),它是一种用于实现进程互斥的同步原语。当一个进程或线程获得了互斥锁之后,其他进程或线程就无法获得锁,只能等待锁的释放。这样就确保了对共享资源的互斥访问。

另一个常用的机制是信号量(Semaphore),它是一种更为灵活的同步原语。除了用于实现进程互斥外,信号量还可以用于控制并发线程数量、实现进程间的同步等。

临界区(Critical Section)是一段代码,其中包含对共享资源的访问操作。为了保证对临界区的互斥访问,通常会使用互斥锁或信号量来进行保护,确保同一时间只有一个进程或线程可以执行临界区的代码。

总之,进程互斥是多进程或多线程编程中的重要概念,它通过各种同步机制确保对共享资源的安全访问,从而保证程序的正确性和可靠性。

  • 12
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值