POSIX命名信号量是POSIX标准下的一个进程间同步原语,允许多个进程共享同一个信号量,从而实现进程间的同步和通信。这与无名信号量不同,无名信号量主要用于线程之间的同步,而不是进程之间。
命名信号量是“命名”的,因为它们使用特定的名称,这使得不同的进程可以打开并使用相同的信号量。
以下是关于POSIX命名信号量的一些关键点和功能:
-
创建/打开: 使用
sem_open
函数来创建或打开一个已存在的命名信号量。 -
关闭: 使用
sem_close
来关闭一个信号量的引用。这并不会删除该信号量,只是关闭当前进程对其的引用。 -
删除: 使用
sem_unlink
来删除一个命名信号量。它会将信号量标记为删除状态,并在所有进程都关闭了对它的引用后真正删除它。 -
增加:
sem_post
可以用于增加信号量的值。 -
减少:
sem_wait
和sem_trywait
可以用于减少信号量的值。如果信号量的值为0,sem_wait
会阻塞,而sem_trywait
会立即返回一个错误。 -
查询: 使用
sem_getvalue
可以查询信号量的当前值。 -
持久性: 命名信号量在系统中是持久的,即使没有进程引用它,它仍然存在,直到使用
sem_unlink
显式删除。 -
位置: 命名信号量通常在
/dev/shm
或/run/shm
中作为一个文件出现(取决于系统),尽管它们不是真正的文件,但这为诊断和调试提供了便利。
使用场景:
POSIX命名信号量在需要进程间同步或通信的场景中很有用,例如:
- 一个进程生成数据,而另一个进程消费这些数据。信号量可以用来同步这两个进程,确保数据在被消费之前已经被生成。
- 限制对共享资源的并发访问,例如一个配置文件或共享数据库。
使用POSIX命名信号量时,应注意避免死锁,并确保在所有情况下都正确地释放已获取的信号量。
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
#define SEM_NAME "namedsem" // Defines the name of the semaphore
int main()
{
sem_t *p_sem = NULL;
// Create a semaphore
p_sem = sem_open(SEM_NAME, O_CREAT|O_EXCL, 0666, 0);
sem_wait(p_sem); // Wait the sempahore
sem_unlink(SEM_NAME); // Delete the semaphore
return 0;
}
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
#define SEM_NAME "namedsem"
int main() {
sem_t *p_sem = NULL;
p_sem = sem_open(SEM_NAME, O_RDWR); // Open the semaphore
sem_post(p_sem); // Release semaphore
return 0;
}
以上两个程序,它们分别展示了如何使用POSIX命名信号量(named semaphore)。
-
第一个程序: 创建并等待信号量
- 定义了一个命名信号量的名称
namedsem
。 - 使用
sem_open
函数,结合O_CREAT|O_EXCL
标志,尝试创建并打开一个新的命名信号量。如果该信号量已经存在,调用会失败。 - 设置的信号量初始值为0,这意味着信号量在创建后不可用。
- 然后,程序调用
sem_wait
,尝试获取这个信号量。因为信号量的初始值为0,所以该调用会阻塞,直到有其他进程或线程使用sem_post
释放信号量。 - 最后,它调用
sem_unlink
来删除命名信号量。但请注意,只有在所有进程都关闭了该信号量的引用后,信号量才会被真正删除。
- 定义了一个命名信号量的名称
-
第二个程序: 打开并释放信号量
- 使用相同的命名信号量名称
namedsem
。 - 使用
sem_open
函数,结合O_RDWR
标志,尝试打开一个已存在的命名信号量。这里不再创建新的信号量,而是打开一个现有的信号量。 - 然后,调用
sem_post
来释放这个信号量。这实际上会增加信号量的计数值。如果第一个程序在sem_wait
中等待,它现在可以获取信号量并继续执行。
- 使用相同的命名信号量名称
结论:
这两个程序组合起来演示了进程间同步的一个简单场景。第一个程序创建并等待一个信号量,而第二个程序打开这个信号量并释放它,从而允许第一个程序继续执行。这是进程间通信和同步的一个简单但非常有用的例子,它展示了如何使用命名信号量进行协作。