无名信号量的实现、存储及与无名管道的区别,sem_init参数解析
无名信号量的实现与sem_init函数解析
一、无名信号量的实现、存储位置与无名管道的区别
实现方式
无名信号量是用于同步的轻量级原语,底层依赖内核提供的原子操作和等待队列机制:
- 线程间同步时,内核仅需保证对信号量计数的修改是原子性的,无需额外跨进程隔离处理。
- 进程间同步时,内核会将信号量的核心数据(计数、等待队列关联信息)绑定到共享内存区域,确保多个进程能访问到同一个信号量实例。
存储位置
- 线程间使用:可存储在进程私有内存的任意位置——全局变量区、栈上的局部变量、堆内存都可以,只要所有需要同步的线程能访问到这个
sem_t变量的地址就行。 - 进程间使用:必须放在进程间共享的内存区域,比如
mmap创建的匿名共享内存、System V共享内存段,因为不同进程的私有内存空间相互隔离,只有共享内存能让多个进程指向同一个信号量实例。
和无名管道的差异
完全不同:
- 无名管道是字节流通信机制,内核维护缓冲区用于父子进程间传递数据,核心是数据传输。
- 无名信号量是同步协调工具,没有数据传输功能,仅通过维护一个计数实现多个执行单元(线程/进程)的等待、唤醒逻辑,核心是执行顺序的协调。
二、sem_init函数参数详解
函数原型:
int sem_init(sem_t *sem, int pshared, unsigned int value);
sem指针的作用与传入要求
sem是指向sem_t类型变量的指针,这个变量会被内核用来存储信号量的核心状态(比如当前计数、等待队列的引用)。你需要传入一个已经分配好内存的sem_t变量的地址:
- 线程间同步:可以传全局
sem_t变量的地址、栈上局部sem_t变量的地址,或者用malloc在堆上分配的sem_t变量地址。 - 进程间同步:必须传共享内存区域中
sem_t变量的地址,否则其他进程无法访问到这个信号量实例。
pshared的含义与实现逻辑
- 含义:
pshared指定信号量的共享范围:pshared = 0:信号量仅在当前进程的线程间共享,属于线程私有信号量。pshared != 0:信号量可用于多个进程间的同步,属于进程间共享信号量。
- 实现细节:
- 线程间共享场景:内核只需要保证对信号量计数的修改是原子操作(比如CPU原子指令),因为同一进程的线程共享地址空间,直接访问
sem指向的内存即可。 - 进程间共享场景:内核会将信号量的状态与共享内存区域绑定,确保多个进程访问的是同一个内核维护的信号量对象,同时通过跨进程的同步机制(比如内核级锁)保证计数修改的安全性。
- 线程间共享场景:内核只需要保证对信号量计数的修改是原子操作(比如CPU原子指令),因为同一进程的线程共享地址空间,直接访问
内容的提问来源于stack exchange,提问作者satwik das
相关产品推荐
相关产品推荐

