进程同步与互斥:POSIX有名信号量

在 POSIX 标准中,信号量分两种,一种是无名信号量,一种是有名信号量。无名信号量一般用于线程间同步或互斥,而有名信号量一般用于进程间同步或互斥。它们的区别和管道及命名管道的区别类似,无名信号量则直接保存在内存中,而有名信号量要求创建一个文件。前面我们学习了无名信号量的使用(详情请看《无名信号量》),这里我们学习有名信号量的使用。

1)创建一个有名信号量

所需头文件:

#include <fcntl.h>

#include <sys/stat.h>

#include <semaphore.h>

当有名信号量存在时使用:

sem_t *sem_open(const char *name, int oflag);

当有名信号量不存在时使用:

sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);

功能:

创建一个有名信号量。

参数:

name:信号量文件名。注意,不能指定路径名。因为有名信号量,默认放在/dev/shm 里,如下图:

flags:sem_open() 函数的行为标志。

mode:文件权限(可读、可写、可执行)的设置。

value:信号量初始值。

返回值:

成功:信号量的地址

失败:SEM_FAILED

2)关闭有名信号量

所需头文件:

#include <semaphore.h>

int sem_close(sem_t *sem);

功能:

关闭有名信号量。

参数:

sem:指向信号量的指针。

返回值:

成功:0

失败:-1

3)删除有名信号量文件

所需头文件:

#include <semaphore.h>

int sem_unlink(const char *name);

功能:

删除有名信号量的文件。

参数:

name:有名信号量文件名。

返回值:

成功:0

失败:-1

4)信号量 PV 操作

用法和《POSIX 无名信号量》一样,详情请点此链接。

有名信号量实现进程间互斥功能:

[cpp] view
plain
copy

  1. #include<stdio.h>
  2. #include<semaphore.h>
  3. #include<fcntl.h>
  4. #include<unistd.h>
  5. #include<sys/stat.h>
  6. #include<sys/types.h>
  7. void printer(sem_t *sem, char *str)
  8. {
  9. sem_wait(sem);  //信号量减一
  10. while(*str!=‘\0‘)
  11. {
  12. putchar(*str);
  13. fflush(stdout);
  14. str++;
  15. sleep(1);
  16. }
  17. printf("\n");
  18. sem_post(sem);  //信号量加一
  19. }
  20. int main(int argc, char *argv[])
  21. {
  22. pid_t pid;
  23. sem_t *sem = NULL;
  24. pid = fork(); //创建进程
  25. if(pid<0){ //出错
  26. perror("fork error");
  27. }else if(pid == 0){ //子进程
  28. //跟open()打开方式很相似,不同进程只要名字一样,那么打开的就是同一个有名信号量
  29. sem = sem_open("name_sem", O_CREAT|O_RDWR, 0666, 1); //信号量值为 1
  30. if(sem == SEM_FAILED){ //有名信号量创建失败
  31. perror("sem_open");
  32. return -1;
  33. }
  34. char *str1 = "hello";
  35. printer(sem, str1); //打印
  36. sem_close(sem); //关闭有名信号量
  37. _exit(1);
  38. }else if(pid > 0){ //父进程
  39. //跟open()打开方式很相似,不同进程只要名字一样,那么打开的就是同一个有名信号量
  40. sem = sem_open("name_sem", O_CREAT|O_RDWR, 0666, 1); //信号量值为 1
  41. if(sem == SEM_FAILED){//有名信号量创建失败
  42. perror("sem_open");
  43. return -1;
  44. }
  45. char *str2 = "world";
  46. printer(sem, str2); //打印
  47. sem_close(sem); //关闭有名信号量
  48. wait(pid, NULL); //等待子进程结束
  49. }
  50. sem_unlink("name_sem");//删除有名信号量
  51. return 0;
  52. }

运行结果如下:

有名信号量实现进程间同步功能(print2 先打印,再到 print1 打印):

print1.c 代码如下:

[cpp] view
plain
copy

  1. #include <fcntl.h>           /* For O_* constants */
  2. #include <sys/stat.h>        /* For mode constants */
  3. #include <semaphore.h>
  4. #include <stdio.h>
  5. void print(sem_t *print1, sem_t *print2)
  6. {
  7. int i = 0;
  8. while(1)
  9. {
  10. sem_wait(print1);
  11. i++;
  12. printf("int print1 i = %d\n", i);
  13. sem_post(print2);
  14. }
  15. }
  16. int main(int argc, char **argv)
  17. {
  18. sem_t *print1, *print2;
  19. print1 = sem_open("sem_print1", O_CREAT, 0777, 0);
  20. if(SEM_FAILED == print1)
  21. {
  22. perror("sem_open");
  23. }
  24. print2 = sem_open("sem_print2", O_CREAT, 0777, 1);
  25. if(SEM_FAILED == print2)
  26. {
  27. perror("sem_open");
  28. }
  29. print(print1, print2);
  30. return 0;
  31. }

print2.c 代码如下:

[cpp] view
plain
copy

  1. #include <fcntl.h>           /* For O_* constants */
  2. #include <sys/stat.h>        /* For mode constants */
  3. #include <semaphore.h>
  4. #include <stdio.h>
  5. void print(sem_t *print1, sem_t *print2)
  6. {
  7. int i = 0;
  8. while(1)
  9. {
  10. sem_wait(print2);
  11. i++;
  12. printf("in print2 i = %d\n", i);
  13. sleep(1);
  14. sem_post(print1);
  15. }
  16. }
  17. int main(int argc, char **argv)
  18. {
  19. sem_t *print1, *print2;
  20. print1 = sem_open("sem_print1", O_CREAT, 0777, 0);
  21. if(SEM_FAILED == print1)
  22. {
  23. perror("sem_open");
  24. }
  25. print2 = sem_open("sem_print2", O_CREAT, 0777, 1);
  26. if(SEM_FAILED == print2)
  27. {
  28. perror("sem_open");
  29. }
  30. print(print1, print2);
  31. return 0;
  32. }

删除有名信号量示例代码如下:

[cpp] view
plain
copy

  1. #include <semaphore.h>
  2. #include <stdio.h>
  3. void sem_del(char *name)
  4. {
  5. int ret;
  6. ret = sem_unlink(name);
  7. if(ret < 0)
  8. {
  9. perror("sem_unlink");
  10. }
  11. }
  12. int main(int argc, char **argv)
  13. {
  14. sem_del("sem_print1"); //删除信号量文件sem_print1
  15. sem_del("sem_print2"); //删除信号量文件sem_print2
  16. return 0;
  17. }

makefile 代码如下:

[plain] view
plain
copy

  1. all:
  2. gcc sem_del.c -o sem_del -lpthread
  3. gcc print1.c -o print1 -lpthread
  4. gcc print2.c -o print2 -lpthread
  5. clean:
  6. rm sem_del print1 print2

运行程序时,先把有名信号量删除(sem_del),再分别运行 print1 和 print2:

本教程示例代码下载请点此处。

转自:http://blog.csdn.net/tennysonsky/article/details/46500417

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-12 00:18:19

进程同步与互斥:POSIX有名信号量的相关文章

Linux系统编程——进程同步与互斥:POSIX有名信号量

在 POSIX 标准中,信号量分两种,一种是无名信号量,一种是有名信号量.无名信号量一般用于线程间同步或互斥,而有名信号量一般用于进程间同步或互斥.它们的区别和管道及命名管道的区别类似,无名信号量则直接保存在内存中,而有名信号量要求创建一个文件.前面我们学习了无名信号量的使用(详情请看<无名信号量>),这里我们学习有名信号量的使用. 1)创建一个有名信号量 所需头文件: #include <fcntl.h> #include <sys/stat.h> #include

进程同步与相互排斥:POSIX有名信号量

在 POSIX 标准中,信号量分两种,一种是无名信号量,一种是有名信号量. 无名信号量一般用于线程间同步或相互排斥,而有名信号量一般用于进程间同步或相互排斥. 它们的差别和管道及命名管道的差别类似.无名信号量则直接保存在内存中,而有名信号量要求创建一个文件.前面我们学习了无名信号量的使用(详情请看<无名信号量>).这里我们学习有名信号量的使用. 1)创建一个有名信号量 所需头文件: #include <fcntl.h> #include <sys/stat.h> #in

Python之路(第三十八篇) 并发编程:进程同步锁/互斥锁、信号量、事件、队列、生产者消费者模型

一.进程锁(同步锁/互斥锁) 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理. 例子 #并发运行,效率高,但竞争同一打印终端,带来了打印错乱 from multiprocessing import Process import os,time def work(): print('%s is running' %os.getpid()) time.sleep(2) print('

【Python下进程同步之互斥锁、信号量、事件机制】 -- 2019-08-16 17:58:28

原文: http://blog.gqylpy.com/gqy/229 " 一.锁机制:??multiprocess.Lock 上篇博客中,我们千方百计实现了程序的异步,让多个任务同时在几个进程中并发处理,但它们之间的运行没有顺序.尽管并发编程让我们能更加充分的利用io资源,但是也给我我们带来了新问题,多个进程使用同一份数据资源的时候,就会引发数据安全或顺序混乱问题. 例: # 多进程抢占输出资源 from multiprocessing import Process from os import

【Python下进程同步之互斥锁、信号量、事件机制】 &#173437;

原文: http://blog.gqylpy.com/gqy/229 " 一.锁机制:??multiprocess.Lock 上篇博客中,我们千方百计实现了程序的异步,让多个任务同时在几个进程中并发处理,但它们之间的运行没有顺序.尽管并发编程让我们能更加充分的利用io资源,但是也给我我们带来了新问题,多个进程使用同一份数据资源的时候,就会引发数据安全或顺序混乱问题. 例: # 多进程抢占输出资源 from multiprocessing import Process from os import

线程同步与互斥:POSIX无名信号量

信号量概述 信号量广泛用于进程或线程间的同步和互斥,信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问. 编程时可根据操作信号量值的结果判断是否对公共资源具有访问的权限,当信号量值大于 0 时,则可以访问,否则将阻塞.PV 原语是对信号量的操作,一次 P 操作使信号量减1,一次 V 操作使信号量加1. 信号量主要用于进程或线程间的同步和互斥这两种典型情况. 信号量用于互斥: 信号量用于同步: 在 POSIX 标准中,信号量分两种,一种是无名信号量,一种是有名信号量.无名信号量一般用

线程同步(互斥锁与信号量的作用与区别)

“信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作(大家都在semtake的时候,就阻塞在 哪里).而互斥锁是用在多线程多任务互斥的,一个线程占用了某一个资源,那么别的线程就无法访问,直到这个线程unlock,其他的线程才开始可以利用这 个资源.比如对全局变量的访问,有时要加锁,操作完了,在解锁.有的时候锁和信号量会同时使用的” 也就是说,信号量不一定是锁定某一个资源,而是流程上的概念,比如:有A,B两个线程,B线程要等A线程完成某一任务以后

Linux系统编程——线程同步与互斥:无名信号量

信号量概述 信号量广泛用于进程或线程间的同步和互斥,信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问. 编程时可根据操作信号量值的结果判断是否对公共资源具有访问的权限,当信号量值大于 0 时,则可以访问,否则将阻塞.PV 原语是对信号量的操作,一次 P 操作使信号量减1,一次 V 操作使信号量加1. 信号量主要用于进程或线程间的同步和互斥这两种典型情况. 信号量用于互斥: 信号量用于同步: 在 POSIX 标准中,信号量分两种,一种是无名信号量,一种是有名信号量.无名信号量一般用

临界区,互斥量,信号量,事件的区别(线程同步)

(转)临界区,互斥量,信号量,事件的区别(线程同步) (转)临界区,互斥量,信号量,事件的区别(线程同步) . 分类: C++ windows 核心编程 2012-04-10 14:55 3321人阅读 评论(0) 收藏 举报 semaphoremfcnulleventsthreadhttp服务器 四种进程或线程同步互斥的控制方法 1.临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问. 2.互斥量:为协调共同对一个共享资源的单独访问而设计的. 3.信号量:为控制一个