system V信号量

本文详细阐述了SystemV信号量相较于Posix信号量的丰富操作特性,包括创建、打开、操作和控制等,并解释了其创建与初始化过程中的同步需求。通过实例代码展示了如何实现信号量的初始化与使用。

    相对于Posix信号量,system V信号量提供了更为丰富的操作,如Posix信号量一次只能增减1,而system V则没有此限制;另外,可以用一个函数(semget)创建一组(多个)信号量,而Posix信号量一次只能创建一个;因此可用其模拟Posix信号量。功能丰富的同时也决定了System V信号量的复杂性。

1)       相关函数:

头文件:<sys/sem.h>

创建或打开:semget

操作:semop  包含的操作有:挂出和等待(对应增减的信号量只可以大于1)

控制操作:semctl,主要用于初始化信号量集中信号量的初始值、获取相关状态(信号量值,semid_ds结构,相关操作的线程数信息)、删除、设置uid、gid、sem_perm.mode(读写权限)

更详细的说明可以查看man手册,如man semget将获取函数的相关说明。

2)       要点

需要注意的是,由于System V信号量的创建和初始化工作是分两步进行的(不像Posix信号量创建和初始化是一个原子操作),这就需要相关的同步工作,确保A进程创建的信号量在被其他进程使用前已经被初始化。

原理:当semget创建一个新的信号量集时,其semid_ds结构的sem_otime成员保证被置为0,因此,其他线程在成功调用semget打开信号量后,必须以IPC_STAT命令调用semctl.然后等待sem_otime变为非零值,这时就可以断定信号量已被初始化。

代码表述如下:

#define MSG_W(0400)
#define MSG_R(0200)
//permission formessage queues 660
#defineSVMSG_MODE (MSG_R | MSG_W | MSG_R >> 3 | MSG_W >> 3)
#define MAX_TIMES100
union senum {
int val;
struct semid_ds *buf;
usigned short*array;
};
int semid;
int oflag =IPC_CREAT | IPC_EXEL | SVSEM_MODE;
union senum arg;
struct semid_ds seminfo;
if (semid = semget(ftok(“/tmp/sem1”),1, oflag) >= 0)
{
         // create successed, now set theinitial value
         arg.val = 1;
         semctl(semid, 0, SETVAL, arg);
}
else if (EEXIST== errno)
{
         semid = semget(ftok(“/tmp/sem1”), 1,oflag);
         arg.buf = &seminfo;
         for (int i = 0; i < MAX_TIMES; i++)
         {
                   semctl(semid, 0, IPC_STAT,arg);
                   if (arg.buf->sem_otime !=0)
                   {
                            //here indicates initialsuccessed
                            break;
                   }
                   sleep(1);
         }
         if (MAX_TIMES == i)
         {
                  //aftertry MAX_TIMES, the semaphore still no been initialized
         }
}
System V 信号量是一种经典的进程间同步机制,广泛用于早期的 Unix 和 Linux 系统中。它通过一个信号量集合来管理多个信号量,每个信号量表示一种资源的可用数System V 信号量的使用主要包括以下几个步骤:创建或获取信号量集合、初始化信号量、执行 P/V 操作、以及最终的控制和删除操作。 ### 创建或获取信号量集合 使用 `semget` 系统调用可以创建一个新的信号量集合或获取一个已存在的集合。其原型如下: ```c int semget(key_t key, int nsems, int semflg); ``` - `key` 是信号量集合的唯一标识符,通常使用 `ftok` 函数生成。 - `nsems` 指定集合中信号量的数。 - `semflg` 指定操作标志,如 `IPC_CREAT` 表示如果不存在则创建。 例如: ```c key_t key = ftok("semaphore_example", 65); int sem_id = semget(key, 1, 0666 | IPC_CREAT); ``` ### 初始化信号量 创建信号量集合后,需要使用 `semctl` 系统调用来初始化信号量的值。 ```c union semun { int val; /* Value for SETVAL */ struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ unsigned short *array; /* Array for GETALL, SETALL */ struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific) */ }; union semun arg; arg.val = 1; // 初始值设为1,表示可用资源 semctl(sem_id, 0, SETVAL, arg); ``` ### 执行 P/V 操作 P/V 操作是信号量的核心机制。P 操作(wait)用于申请资源,V 操作(signal)用于释放资源。这些操作通过 `semop` 系统调用实现。 ```c struct sembuf operations; // P 操作(减少信号量值) operations.sem_num = 0; operations.sem_op = -1; operations.sem_flg = 0; semop(sem_id, &operations, 1); // V 操作(增加信号量值) operations.sem_op = 1; semop(sem_id, &operations, 1); ``` ### 控制和删除信号量 使用 `semctl` 可以对信号量进行控制操作,例如删除信号量集合。 ```c semctl(sem_id, 0, IPC_RMID); ``` ### 完整示例 以下是一个完整的示例,演示了创建信号量、执行 P/V 操作并最终删除信号量的过程: ```c #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> union semun { int val; struct semid_ds *buf; unsigned short *array; }; int main() { key_t key = ftok("semaphore_example", 65); int sem_id = semget(key, 1, 0666 | IPC_CREAT); if (sem_id == -1) { perror("semget"); exit(EXIT_FAILURE); } union semun arg; arg.val = 1; if (semctl(sem_id, 0, SETVAL, arg) == -1) { perror("semctl"); exit(EXIT_FAILURE); } // P 操作 struct sembuf operations; operations.sem_num = 0; operations.sem_op = -1; operations.sem_flg = 0; if (semop(sem_id, &operations, 1) == -1) { perror("semop P"); exit(EXIT_FAILURE); } printf("Resource acquired\n"); // 模拟资源使用 sleep(2); // V 操作 operations.sem_op = 1; if (semop(sem_id, &operations, 1) == -1) { perror("semop V"); exit(EXIT_FAILURE); } printf("Resource released\n"); // 删除信号量 if (semctl(sem_id, 0, IPC_RMID) == -1) { perror("semctl IPC_RMID"); exit(EXIT_FAILURE); } return 0; } ``` ### 注意事项 - System V 信号量需要手动管理,包括创建、初始化、使用和删除。 - 由于其复杂性和接口的繁琐性,System V 信号量在现代多线程编程中使用较少,通常被更高级的同步机制(如 POSIX 信号量)所取代。 - 在多进程环境中,必须确保所有进程使用相同的 `key` 来访问同一个信号量集合。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值