13、操作系统——posix信号量(无名信号量)
目录
一、无名信号量的介绍
二、信号量的使用步骤
三、sem_init、sem_destroy
四、system-V 信号量和 POSIX 信号量(named-sem 和 unnamed-sem)的区别
五、代码
一、无名信号量的介绍
因为有名信号量的线程共享一个内存空间,若要解决进程内部的线程间的同步互斥,需要使用更加轻量化、基于内存的(不再任何文件系统内部)无名信号量,
二、信号量的使用步骤
1,在这些线程都能访问到的区域定义这种变量(比如全局变量),类型是 sem_t。
2,在任何线程使用它之前,用 sem_init( )初始化他。
3,使用 sem_wait( )/sem_trywait( )和 sem_post( )来分别进行 P、V 操作。
4,不再需要时,使用 sem_destroy( )来销毁他
三、sem_init、sem_destroy
无名信号量一般用在进程内的线程间,因此 pshared 参数一般都为 0。当将此种信号 量用在进程间时,必须将他定义在各个进程都能访问的地方——比如共享内存之中
四、system-V 信号量和 POSIX 信号量(named-sem 和 unnamed-sem)的区别
1、sys-V 信号量较古老,语法艰涩。POSIX 信号量简单,轻量。
2、sys-V 信号量可以对代表多种资源的多个信号量元素同一时间进行原子性的 P/V 操作,POSIX 信号量每次只能操作一个信号量。
3、sys-V 信号量和 named-sem 是系统范围的资源,进程消失之后继续存在,而 unnamed-sem 是进程范围的资源,随着进程的退出而消失。
4、sys-V 信号量的 P/V 操作可以对信号量元素加减大于 1 的数值,而 POSIX 信号量 每次 P/V 操作都是加减 1
5、sys-V 信号量甚至还支持撤销操作——一个进程对 sys-V 信号量进行 P/V 操作时可以给 该 操作贴上需要撤销的标识,那么当进程退出之后,系统会自动撤销那些做了标识的操作。而 POSIX 信 号没有此功能。
6、sys-V 信号量和 named-sem 适合用在进程间同步互斥,而 unamed-sem 适合用在线程 间同步互斥。
总的来说,system-V 的信号量功能强大,强大到臃肿啰嗦,如果在现实工作中不需要 那些高级功能,建议使用接口清晰、逻辑简单的 POSIX 信号量
五、代码
#include <stdio.h>
#include <semaphore.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
// 定义线程间共享的资源
sem_t sem ;
// 定义一个指针作用与线程之间的共享内存
char * mem_map = NULL ;
void * FUNCTION(void * arg)
{
// 由于接收到的arg 是 void 型的, 因此先进行强转
char * msg = (char *)arg ;
printf("线程号:%ld , 收到参数为:%s \n" , pthread_self() , msg );
while(1)
{
sem_wait(&sem) ;
printf("msg : %s \n" , mem_map) ;
sem_post(&sem);
usleep(1000);//要有延时
}
}
int main(int argc, char const *argv[])
{
// 划分一个用于线程间通信的共享内存
mem_map = calloc(1, 32) ;//申请一片32字节的内存
// 初始化无名信号量信号量 0 表示线程间, 1 表示初始化资源量为1
if(sem_init( &sem , 0 , 1 ))
{
perror("sem init error");
return -1 ;
}
// 创建线程
pthread_t thread;
pthread_create(&thread, NULL, FUNCTION , "Hello GZ2123");
while(1)
{
// P 操作, 等待获取资源
sem_wait(&sem) ;
fgets(mem_map , 32 , stdin) ;//获取数据
sem_post(&sem);//释放资源
usleep(1000);
}
return 0;
}