POSIX信号量

1.引言

       信号量是包含一个非负整型变量,并且带有两个原子操作wait 和signal。wait 还可以被称为down、P 或lock,signal 还可以被称为up、V、unlock 或post。在Uinx的API中用的是wait和post

       如果信号量的非负整形变量S大于零,wait就将其减1,如果S 等于0,wait 就将调用线程阻塞。对于signal 操作,如果有线程在信号量上阻塞(此时S 等于0),signal就会解除对某个等待线程的阻塞,使其从wait 中返回,如果没有线程阻塞在信号量上,signal 就将S加1。

       由此可见,S 可以被理解为一种资源的数量,信号量即是通过控制这种资源的分配来实现互斥和同步的。如果把S 设为1,信号量即可实现互斥量的功能。如果S 的值大于1,那么信号量即可使多个线程并发运行。另外,信号量不仅允许使用者申请和释放资源,而且还允许使用者创造资源,这就赋予了信号量实现同步的功能。可见,信号量的功能要比互斥量丰富许多。

       POSIX信号量是一个sem_t 类型的变量,但POSIX 有两种信号量的实现机制:无名信号量和命名信号量。无名信号量可以用在共享内存的情况下,比如实现进程中各个线程之间的互斥和同步。命名信号量通常用于不共享内存的情况下,比如不共享内存的进程之间。

2.POSIX 无名信号量

       在使用信号量之前,必须对其进行初始化。sem_init 函数初始化指定的信号量:

#include <semaphore.h>
int sem_init(sem_t *sem, int pshared,unsigned value);
                                                 //成功返回0,出错返回错误号

       参数value 为信号量的初始值。参数pshared用于说明信号量的共享范围,如果pshared 为0,那么该信号量只能由初始化这个信号量的进程中的线程使用,如果pshared 非零,任何可以访问到这个信号量的进程都可以使用这个信号量。

       函数sem_destroy 销毁一个指定的信号量,它的形式为:

#include <semaphore.h>
int sem_destroy(sem_t *sem);
                                   //成功返回0,出错返回错误号

       信号量的操作函数为sem_post、sem_wait、sem_trywait:

#include <semaphore.h>
int sem_post(sem_t *sem);
int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);
                     //成功返回0,出错返回错误号
//sem_trywait函数试图获取信号量,但是如果获取不了,并不阻塞线程,与//pthread_mutex_trylock类似

       这些函数同样可以使用与命名信号量!

3.POSIX 命名信号量

       之所以称为命名信号量,是因为它有一个名字、一个用户ID、一个组ID和权限,这些是提供给不共享内存的那些进程使用命名信号量的接口。命名信号量的名字是一个遵守路径名构造规则的字符串。

       sem_open函数用于创建或打开一个命名信号量:

#include <semaphore.h>
sem_t *sem_open(const char *name, intoflag);

       参数 name 是一个标识信号量的字符串。参数oflag 用来确定是创建信号量还是连接已有信号量。如果设置了oflag 的O_CREAT 比特位,则会创建一个新的信号量。

       sem_close函数用于关闭命名信号量:

#include <semaphore.h>
int sem_close(sem_t *sem);
                                   //成功返回0,出错返回错误编号

       单个程序可以用sem_close函数关闭命名信号量,但是这样做并不能将信号量从系统中删除,因为命名信号量在单个程序的执行之外是具有持久性的。当进程调用_exit、exit、exec 或从main 返回时,进程打开的命名信号量同样会被关闭。

       sem_unlink函数用于在所有进程关闭了命名信号量之后,将信号量从系统中删除。它的形式为:

#include <semaphore.h>
int sem_unlink(const char *name);
                                   //成功返回0,出错返回-1

4.问题

    建两个线程,这两个线程各自将自己的一个整型变量i从1 递增到100,并通过信号量控制递增的过程,即这两个整型变量的差不能超过5。

#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <stdio.h>  
#define MAX 100
sem_t sem1,sem2;    
void* th_fn1(void* arg)
{    
       inti;    
       for(i = 0; i < MAX; ++i)    
       {        
              sem_wait(&sem1);        
              printf("numberin thread1 is %d\n",i);        
              sem_post(&sem2);    
       }
       pthread_exit((void*)"thread1exit\n");
}
void* th_fn2(void* arg)
{    
       inti;  
       for(i = 0; i < MAX; ++i)
   {        
              sem_wait(&sem2);
       printf("number in thread2 is %d\n",i);       
               sem_post(&sem1);
   }   
        pthread_exit((void*)"thread2exit\n"); }
int main(void)
{   
       void*tret;  
       sem_init(&sem1,0,5);
       sem_init(&sem2,0,5);
       pthread_ttid1,tid2;  
       pthread_create(&tid1,NULL,th_fn1,NULL);           pthread_create(&tid2,NULL,th_fn2,NULL); 
       pthread_join(tid1,&tret);  
       pthread_join(tid2,&tret);  
       sem_destroy(&sem1); 
       sem_destroy(&sem2);  
       return0;
}

5.生产者消费者问题

#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <stdio.h>
#define MAX 100
#define BUFSIZE 10
//#define DEBUG 0
int buf[BUFSIZE]={0};
int in=0;
int out=0;
sem_t full,empty;
#ifdef DEBUG
void print(void)
{
   int i;
   printf("buf is:");
    for(i=out;i<in;i++)
       printf("%d ",buf[i]);
   printf("\n");
}
#endif  
void* producer(void* arg)
{
   int i;
   for (i = 1; i <= MAX; ++i)
    {
       /*produce*/
       sem_wait(&full);
       buf[in++]=i;
       in%=BUFSIZE;
#ifdef DEBUG
       print();
#endif
       sem_post(&empty);
    }
   pthread_exit((void*)"thread1 exit\n");
}
void* comsumer(void* arg)
{
   int i;
   for (i = 1; i <= MAX; ++i)
    {
       /*comsumer*/
       sem_wait(&empty);
       out++;
       out%=BUFSIZE;
       sem_post(&full);
    }
   pthread_exit((void*)"thread2 exit\n");
}
int main(void)
{
   void *tret;
   sem_init(&full,0,10);
   sem_init(&empty,0,0);
   pthread_t tid_producer,tid_comsumer;
   pthread_create(&tid_producer,NULL,producer,NULL);
   pthread_create(&tid_comsumer,NULL,comsumer,NULL);
   pthread_join(tid_producer,&tret);
       printf("%s\n",(char*)tret);
   pthread_join(tid_comsumer,&tret);
       printf("%s\n",(char*)tret);
   sem_destroy(&full);
   sem_destroy(&empty);
   return 0;
}




  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值