linux_信号量(详解)

打印 上一主题 下一主题

主题 716|帖子 716|积分 2152

一.信号量

1.1信号量的概述

信号量广泛用于进程或线程间的同步和互斥,信号量本质上是一个非负整数计数器,它被用来控制对公共资源的访问
编程时可根据利用信号量值的结果判断是否对公共资源具有访问的权限,当信号量大于0时,则可以访问,否则将阻塞
信号量又称之为PV利用,P V原语是对信号量的利用,一次P利用使信号量使信号量sem-1一次V利用使信号量sem+1,对于P利用,如果信号量的sem值小于即是0,则P利用就会阻塞,如果信号量的值大于0,才可以实验p利用进行减1
信号量主要用于进程或线程间的同步和互斥这两种情况

  • 若用于互斥,几个进程(或线程)每每只设置一个信号量
  • 若用于同步利用,每每会设置多个信号量,而且安排不同的初始值,来实现它们之间的实验次序
    信号量用于互斥

信号量用于同步
二 信号量利用

2.1 信号量初始化

  1. 1. #include <semaphore.h>
  2. 2. int sem_init(sem_t *sem,int pshared,unsigned int value);
  3. 3. 功能:创建一个信号量并初始化它的值
  4. 4. 参数: sem:信号量地址  
  5.                 pshared:等于0,信号量在线程间共享;不等于0,信号量在进程共享。
  6.                 value:信号量的初始值。
  7. 5.返回值:成功返回0,失败返回-1;
复制代码
2.2 信号量的P利用

  1. 1. #include<semaphore.h>
  2. 2. int sem_wait(sem_t *sem);
  3. 3. 功能:将信号量的值减1,若信号量的值小于等于0,此函数会引起调用者阻塞
  4. 4. 参数:sem:信号量地址
  5. 5. 返回值:成功返回0,失败返回-1
复制代码
  1. #include<semaphore.h>
  2. 2. int sem_trywait(sem_t *sem);
  3. 3. 功能:将信号量的值减1,若信号量的值小于等于0,则对信号量的操作失败,函数立即返回
  4. 4. 参数:sem:信号量地址
  5. 5. 返回值:成功返回0,失败返回-1
复制代码
2.3 信号量的V利用

  1. 1. #include <semaphore.h>
  2. 2. int sem_post(sem_t *sem)       
  3. 3. 功能:执行v操作,执行一次,信号量的值加1
  4. 4. 参数:sem:信号量地址
  5. 5. 返回值:成功返回0,失败返回-1
复制代码
2.4 获取信号量的计数值

  1. 1. #include <semaphore.h>
  2. 2. int sem_getvalue(sem_t *sem,int *sval);       
  3. 3. 功能:获取sem标识的信号量的值,保存在sval中
  4. 4. 参数:sem:信号量地址 sval:保存信号量值的地址
  5. 5. 返回值:成功返回0,失败返回-1
复制代码
2.5 信号量的销毁

  1. 1. #include <semaphore.h>
  2. 2. int sem_destroy(sem_t *sem);       
  3. 3. 功能:删除sem标识的信号量,
  4. 4. 参数:sem:信号量地址
  5. 5. 返回值:成功返回0,失败返回-1
复制代码
三 信号量的使用

3.1 信号量实现互斥功能


  1. #include <stdio.h>
  2. #include <pthread.h>
  3. #include <semaphore.h>
  4. #include <unistd.h>
  5. #include <stdlib.h>
  6. // 通过信号量实现互斥操作
  7. // 第一步:创建一个信号量
  8. sem_t sem;
  9. void printer(char *str)
  10. {
  11. //      第三步:执行p操作
  12. //      由于使用信号量实现互斥,信号量初始值设置为1,则两个线程执行p操作
  13. //      先执行p操作的线程继续执行,后执行p操作的先阻塞等待
  14.         sem_wait(&sem);
  15.         while(*str){
  16.                 putchar(*str);
  17.                 fflush(stdout);
  18.                 str++;
  19.                 sleep(1);
  20.         }
  21. //      第四步:执行v操作
  22.         sem_post(&sem);
  23. }
  24. void *thr_fun1(void *arg)
  25. {
  26.         char *str1 = "change";
  27.         printer(str1);
  28. }
  29. void *thr_fun2(void *arg)
  30. {
  31.         char *str2 = "word";
  32.         printer(str2);
  33. }
  34. int main()
  35. {
  36.         pthread_t th1,th2;
  37. //      第二步:初始化信号量
  38.         sem_init(&sem,0,1);
  39.         if(pthread_create(&th1,NULL,thr_fun1,NULL) != 0)
  40.         {
  41.                 perror("fail to pthread_create");
  42.                 exit(1);
  43.         }
  44.         if(pthread_create(&th2,NULL,thr_fun2,NULL)  != 0)
  45.         {
  46.                 perror("fail to pthread_create");
  47.                 exit(1);
  48.         }
  49.         pthread_join(th1,NULL);
  50.         pthread_join(th2,NULL);
  51.         printf("\n");
  52. //      第五步
  53.         sem_destroy(&sem);
  54.         return 0;
  55. }
复制代码
实验结果

3.2 信号量实现同步功能


  1. #include <stdio.h>
  2. #include <pthread.h>
  3. #include <semaphore.h>
  4. #include <unistd.h>
  5. #include <stdlib.h>
  6. // 通过信号量实现同步操作
  7. // 第一步:创建两个信号量
  8. sem_t sem_p,sem_g;
  9. char ch = 'a';
  10. void *thr_g(void *arg)
  11. {
  12.         while(1)
  13.         {
  14. //              第四步:执行p功能
  15.                 sem_wait(&sem_g);
  16.                 ch++;
  17.                 sleep(1);
  18. //              第六步:执行v操作
  19.                 sem_post(&sem_p);
  20.         }
  21.         pthread_exit(0);
  22. }
  23. void *thr_p(void *arg) // 打印ch的值
  24. {
  25.         while(1){
  26. //              第三步执行p操作
  27.                 sem_wait(&sem_p);
  28.                 printf("%c",ch);
  29.                 fflush(stdout);
  30. //              第五步执行V操作
  31.                 sem_post(&sem_g);
  32.         }
  33.         pthread_exit(0);
  34. }
  35. int main()
  36. {
  37.         pthread_t th1,th2;
  38. //      第二步初始化信号量
  39.         sem_init(&sem_p,0,1);
  40.         sem_init(&sem_g,0,0);
  41.         if(pthread_create(&th1,NULL,thr_p,NULL) != 0)
  42.         {
  43.                 perror("fail to pthread_create");
  44.                 exit(1);
  45.         }
  46.         if(pthread_create(&th2,NULL,thr_g,NULL) != 0)
  47.         {
  48.                 perror("fail to pthread_create");
  49.                 exit(1);
  50.         }
  51.         pthread_join(th1,NULL);
  52.         pthread_join(th2,NULL);
  53.         printf("\n");
  54. //      第五步,销毁信号量
  55.         sem_destroy(&sem_p);
  56.         sem_destroy(&sem_g);
  57.         return 0;
  58. }
  59.   
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

东湖之滨

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表