信号量sem_init

来源:互联网 发布:yum怎么读 编辑:程序博客网 时间:2024/05/10 20:55

信号量的数据类型为结构sem_t,它本质上是一个长整型的数。函数sem_init()用来初始化一个信号量。它的原型为:  

extern int sem_init __P((sem_t *__sem, int __pshared, unsigned int __value));  

sem为指向信号量结构的一个指针;pshared不为0时此信号量在进程间共享,否则只能为当前进程的所有线程共享;value给出了信号量的初始值。  

函数sem_post( sem_t *sem)用来增加信号量的值。当有线程阻塞在这个信号量上时,调用这个函数会使其中的一个线程不在阻塞,选择机制同样是由线程的调度策略决定的。  

函数sem_wait( sem_t *sem)被用来阻塞当前线程直到信号量sem的值大于0,解除阻塞后将sem的值减一,表明公共资源经使用后减少。函数sem_trywait (sem_t *sem )是函数sem_wait()的非阻塞版本,它直接将信号量sem的值减一。  

函数sem_destroy(sem_t*sem)用来释放信号量sem。 

信号量用sem_init函数创建的,下面是它的说明:
  #include<semaphore.h>
       int sem_init (sem_t *sem, int pshared, unsigned int value);

       这个函数的作用是对由sem指定的信号量进行初始化,设置好它的共享选项,并指定一个整数类型的初始值。pshared参数控制着信号量的类型。如果pshared的值是0,就表示它是当前里程的局部信号量;否则,其它进程就能够共享这个信号量。我们现在只对不让进程共享的信号量感兴趣。 (这个参数受版本影响), pshared传递一个非零将会使函数调用失败。

  这两个函数控制着信号量的值,它们的定义如下所示:
  
  #include <semaphore.h>
       int sem_wait(sem_t * sem);
       int sem_post(sem_t * sem);
 
       这两个函数都要用一个由sem_init调用初始化的信号量对象的指针做参数。
       sem_post函数的作用是给信号量的值加上一个“1”,它是一个“原子操作”---即同时对同一个信号量做加“1”操作的两个线程是不会冲突的;而同时对同一个文件进行读、加和写操作的两个程序就有可能会引起冲突。信号量的值永远会正确地加一个“2”--因为有两个线程试图改变它。
       sem_wait函数也是一个原子操作,它的作用是从信号量的值减去一个“1”,但它永远会先等待该信号量为一个非零值才开始做减法。也就是说,如果你对一个值为2的信号量调用sem_wait(),线程将会继续执行,介信号量的值将减到1。如果对一个值为0的信号量调用sem_wait(),这个函数就会地等待直到有其它线程增加了这个值使它不再是0为止。如果有两个线程都在sem_wait()中等待同一个信号量变成非零值,那么当它被第三个线程增加一个“1”时,等待线程中只有一个能够对信号量做减法并继续执行,另一个还将处于等待状态。
        信号量这种“只用一个函数就能原子化地测试和设置”的能力下正是它的价值所在。还有另外一个信号量函数sem_trywait,它是sem_wait的非阻塞搭档。

        最后一个信号量函数是sem_destroy。这个函数的作用是在我们用完信号量对它进行清理。下面的定义:
         #include<semaphore.h>
         int sem_destroy (sem_t *sem);
         这个函数也使用一个信号量指针做参数,归还自己战胜的一切资源。在清理信号量的时候如果还有线程在等待它,用户就会收到一个错误。
        与其它的函数一样,这些函数在成功时都返回“0”。

 

#include<stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>

sem_t bin_sem;
void *thread_function1(void *arg)
{
 printf("thread_function1--------------sem_wait\n");
 sem_wait(&bin_sem);
 printf("sem_wait\n");
 while (1)
 {
 }
}

void *thread_function2(void *arg)
{
 printf("thread_function2--------------sem_post\n");
 sem_post(&bin_sem);
 printf("sem_post\n");
 while (1)
 {
 }
}


 
int main()
{
 int res;
 pthread_t a_thread;
 void *thread_result;
 
 res = sem_init(&bin_sem, 0,0);
 if (res != 0)
 {
  perror("Semaphoreinitialization failed");
 }
  printf("sem_init\n");
 res = pthread_create(&a_thread,NULL, thread_function1, NULL);
 if (res != 0)
 {
  perror("Thread creationfailure");
 }
 printf("thread_function1\n");
 sleep (5);
 printf("sleep\n");
 res = pthread_create(&a_thread,NULL, thread_function2, NULL);
 if (res != 0)
 {
  perror("Thread creationfailure");
 }
 while (1)
 {
 }
}


sem_init
thread_function1
thread_function1--------------sem_wait
sleep
thread_function2--------------sem_post
sem_wait
sem_post
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 火柴没有擦的了怎么办 乙醚倒进下水道了怎么办 乙醚和水不分层怎么办 乙醚闻多了头晕怎么办 爱乐维吃了便秘怎么办 刮完滑石粉墙面很软怎么办 被硫酸泼到皮肤怎么办 头磕了一下头晕怎么办 家里有事与工作不能请怎么办 撞了头头晕想吐怎么办 猫不小心摔一下怎么办 一氧化二氮中毒怎么办 电脑开机变慢了怎么办 怎么办抚顺韦德健身卡 预售健身卡合法吗怎么办 被浓硫酸泼到怎么办 婴儿误喝了生水怎么办 宝宝喝了生水拉肚子怎么办 因妈妈喝生水宝宝拉肚子怎么办 喝了几口生水怎么办 不小心吃到蟑螂怎么办 吃了有蛆的樱桃怎么办 不小心误食了蛆怎么办 吃了有蟑螂的汤怎么办 调节天平时指针向右怎么办 香薰蜡烛融化了怎么办 香薰蜡烛挂壁怎么办y 粗蜡烛只烧中间怎么办 紫薯馒头变绿怎么办 小孩手开水烫了怎么办 被油烫伤了怎么办才不留疤 烫伤水泡蹭破了怎么办 烧伤的水泡破了怎么办 烧伤后水泡破了怎么办 烫伤泡破了红肿怎么办 烧伤第二天水泡破了怎么办? 烧伤后换药特别疼怎么办 盐酸溅到皮肤上怎么办 磷性磷酸酶高440怎么办 浓硫酸沾到皮肤上怎么办 浓硫酸溅到皮肤上怎么办