Linux——信号量
目录
一、信号量定义
二、信号量种类
三、信号量操作
3.1 P操作
3.2 V操作
四、信号量的代码实现
4.1 信号量创建,初始化
4.2 销毁信号量
4.3 p操作
4.4 v操作
五、使用PV操作代码实现
5.1 d.c
5.2 e.c
一、信号量定义
信号量是一种用于同步多线程或进程之间的机制,用于控制对共享资源的访问。信号量可以用来保护临界区,防止多个线程同时访问某个共享资源导致数据不一致或竞争条件的发生。
二、信号量种类
信号量是用来实现进程之间的同步和互斥的一种机制。信号量种类主要分为两种:
-
二进制信号量(Binary Semaphore):也称为互斥信号量,只能取两个值,通常是0和1。用于实现互斥访问共享资源(互斥锁(Mutex)),保证同一时间只有一个线程访问共享资源。
-
计数信号量(Counting Semaphore):可以取多个值,用来进行进程间的同步。用于管理有限数量的共享资源,允许多个线程同时访问资源,但访问数量有限制。它可以表示一定数量的资源可用或者表示某种事件发生的次数。
除了这两种主要的信号量种类,还有一些其他类型的信号量,如忙等待信号量、无忙等待信号量、实时信号量等,这些信号量种类可以根据具体的应用场景和需求进行选择和使用。
三、信号量操作
信号量操作通常包括两种:P操作和V操作。
3.1 P操作
1.申请资源。
2.如果信号量的值大于 0,则将其减 1,表示成功获取资源。
3.如果信号量的值为 0,则线程进入等待状态,直到信号量的值大于 0。
3.2 V操作
1.释放资源。
2.将信号量的值加 1,表示释放一个资源。
3.如果有线程因等待该信号量而阻塞,V 操作会唤醒其中一个线程。
临界资源:同一时刻值运行一个进程访问的资源。
临界区:访问临界资源的代码段。
四、信号量的代码实现
4.1 信号量创建,初始化
sem_init()
static int semid = -1;void sem_init()
{semid = semget((key_t)1234,1,IPC_CREAT|IPC_EXCL|0600);//全新创建一个信号量if(semid==-1)//如果失败,说明已经创建,直接获取id即可{semid=semget((key_t)1234,1,0600);//获取别人创建的信号量if(semid==-1){printf("semget err\n");return;}}else{union semun a;a.val=1;if( semctl(semid,0,SETVAL,a) == -1){printf("semctl init err\n");}}
}
4.2 销毁信号量
sem_destroy()
void sem_destroy()
{if(semctl(semid,0,IPC_RMID) == -1){printf("semctl rm err\n");}
}
4.3 p操作
sem_p()
void sem_p()
{struct sembuf buf;buf.sem_num = 0;buf.sem_op = -1;//pbuf.sem_flg = SEM_UNDO;if(semop(semid,&buf,1) ==-1){printf("p err\n");}
}
4.4 v操作
sem_v()
void sem_v()
{struct sembuf buf;buf.sem_num = 0;buf.sem_op = 1;//vbuf.sem_flg = SEM_UNDO;if(semop(semid,&buf,1) ==-1){printf("v err\n");}
}
五、使用PV操作代码实现
5.1 d.c
#include"sem.h"int main()
{sem_init();for(int i=0;i<5;i++){sem_p();printf("A");fflush(stdout);int n=rand()%3;sleep(n);printf("A");fflush(stdout);sem_v();n=rand()%3;sleep(n);}
}
5.2 e.c
下面的示例是程序通过信号量来保证在打印字符'B'时不会有多个线程或进程同时执行,从而避免出现混乱。
#include"sem.h"int main()
{sem_init();for(int i=0;i<5;i++){sem_p();printf("B");fflush(stdout);int n=rand()%3;sleep(n);printf("B");fflush(stdout);sem_v();n=rand()%3;sleep(n);}sleep(10);sem_destroy();
}
编译通过后,运行结果如下: