Linux 下管理 Semaphore 的深入指南142


Semaphore 是一种同步机制,允许进程之间安全地共享资源。它特别适用于多进程应用程序,需要协调对共享数据的访问。在 Linux 系统中,semaphore 的实现遵循 POSIX 标准,为开发者提供了强大的工具来管理并发。

创建 Semaphore

要在 Linux 中创建 semaphore,可以使用 semget() 系统调用。它需要以下参数:* key:一个整数,用于标识 semaphore 集。
* nsems: semaphore 数组的大小。
* semflg:指定 semaphore 的权限和标志。

下面的示例创建一个包含 1 个 semaphore 的 semaphore 集,具有读写权限:```
#include
#include
#include
key_t key = ftok("/", 'S');
int semid = semget(key, 1, IPC_CREAT | IPC_EXCL | 0666);
if (semid < 0) {
perror("semget");
exit(1);
}
```

获取 Semaphore 值

要获取 semaphore 的当前值,可以使用 semctl() 系统调用。它需要以下参数:* semid: semaphore 集的标识符。
* semnum: semaphore 数组中的索引。
* cmd:指定要执行的命令,例如 GETVAL。

下面的示例获取 semaphore 的当前值:```
int val = semctl(semid, 0, GETVAL);
if (val < 0) {
perror("semctl");
exit(1);
}
```

操作 Semaphore

要操作 semaphore,可以使用 semop() 系统调用。它需要以下参数:* semid: semaphore 集的标识符。
* sops:一个 sembuf 结构数组,指定要执行的操作。
* nsops: sops 数组的大小。

sembuf 结构具有以下成员:* sem_num: semaphore 数组中的索引。
* sem_op:要执行的操作,例如加 1 或减 1。
* sem_flg:指定操作的标志,例如等待或不等待。

下面的示例将 semaphore 的值加 1:```
struct sembuf sop = {0, 1, 0};
if (semop(semid, &sop, 1) < 0) {
perror("semop");
exit(1);
}
```

删除 Semaphore

要删除 semaphore,可以使用 semctl() 系统调用。它需要以下参数:* semid: semaphore 集的标识符。
* semnum: semaphore 数组中的索引。
* cmd:指定要执行的命令,例如 IPC_RMID。

下面的示例删除 semaphore:```
if (semctl(semid, 0, IPC_RMID) < 0) {
perror("semctl");
exit(1);
}
```

使用 Semaphore

semaphore 可用于各种并发场景,例如:* 保护共享数据: semaphore 可用于确保同时只能有一个进程访问共享数据。
* 控制资源访问: semaphore 可用于控制对有限资源的访问,例如打印机或数据库连接。
* 同步进程: semaphore 可用于同步多个进程之间的操作,例如等待一个进程完成任务后再继续。

示例:读者-写者问题

读者-写者问题是一个经典的并发问题,说明了 semaphore 的有用性。在该问题中,多个读者可以同时访问共享数据,但写者在任何时候只能访问数据。可以使用 semaphore 来实现以下规则:* 当一个写者正在写时,没有读者可以读。
* 当一个或多个读者正在读时,没有写者可以写。

下面的示例代码实现了读者-写者问题:```
#include
#include
#include
#include
#include
#define READERS 5
#define WRITERS 3
int main() {
key_t key = ftok("/", 'R');
int semid = semget(key, 1, IPC_CREAT | IPC_EXCL | 0666);
if (semid < 0) {
perror("semget");
exit(1);
}
// 初始化 semaphore 为 1,允许一个写者写
semctl(semid, 0, SETVAL, 1);
// 创建读者线程
pthread_t reader_threads[READERS];
for (int i = 0; i < READERS; i++) {
pthread_create(&reader_threads[i], NULL, reader, NULL);
}
// 创建写者线程
pthread_t writer_threads[WRITERS];
for (int i = 0; i < WRITERS; i++) {
pthread_create(&writer_threads[i], NULL, writer, NULL);
}
// 等待所有线程完成
for (int i = 0; i < READERS; i++) {
pthread_join(reader_threads[i], NULL);
}
for (int i = 0; i < WRITERS; i++) {
pthread_join(writer_threads[i], NULL);
}
// 删除 semaphore
semctl(semid, 0, IPC_RMID);
return 0;
}
void* reader(void* arg) {
while (1) {
// 等待 semaphore 为正,表示可以读
struct sembuf sop = {0, -1, 0};
semop(semid, &sop, 1);
// 读共享数据
// 释放 semaphore,允许其他线程读
sop.sem_op = 1;
semop(semid, &sop, 1);
}
}
void* writer(void* arg) {
while (1) {
// 等待 semaphore 为 0,表示可以写
struct sembuf sop = {0, -1, 0};
semop(semid, &sop, 1);
// 写共享数据
// 释放 semaphore,允许其他线程读或写
sop.sem_op = 1;
semop(semid, &sop, 1);
}
}
```

semaphore 是多线程 Linux 应用程序中管理并发的重要工具。通过使用 semget()、semctl() 和 semop() 系统调用,开发者可以创建、获取和操作 semaphore,从而协调对共享资源的访问并确保进程之间安全地进行通信。

2025-01-20


上一篇:云托管服务器如何优化网站搜索引擎排名

下一篇:快手短视频平台搜索引擎优化指南