Linux进程间通信——使用信号量
这篇文章将讲述别一种进程间通信的机制——信号量。注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物。有关信号的更多内容,可以阅读我的另一篇文章:Linux进程间通信——使用信号。下面就进入信号量的讲解。
1 int semget(key_t key, int num_sems, int sem_flags);
1 int semop(int sem_id, struct sembuf *sem_opa, size_t num_sem_ops);
sem_id是由semget返回的信号量标识符,sembuf结构的定义如下:
1 struct sembuf{ 2 short sem_num;//除非使用一组信号量,否则它为0 3 short sem_op;//信号量在一次操作中需要改变的数据,通常是两个数,一个是-1,即P(等待)操作, 4 //一个是+1,即V(发送信号)操作。 5 short sem_flg;//通常为SEM_UNDO,使操作系统跟踪信号, 6 //并在进程没有释放该信号量而终止时,操作系统释放信号量 7 };
1 int semctl(int sem_id, int sem_num, int command, ...);
如果有第四个参数,它通常是一个union semum结构,定义如下:
1 union semun{ 2 int val; 3 struct semid_ds *buf; 4 unsigned short *arry; 5 };
1 #include <unistd.h> 2 #include <sys/types.h> 3 #include <sys/stat.h> 4 #include <fcntl.h> 5 #include <stdlib.h> 6 #include <stdio.h> 7 #include <string.h> 8 #include <sys/sem.h> 9 10 union semun 11 { 12 int val; 13 struct semid_ds *buf; 14 unsigned short *arry; 15 }; 16 17 static int sem_id = 0; 18 19 static int set_semvalue(); 20 static void del_semvalue(); 21 static int semaphore_p(); 22 static int semaphore_v(); 23 24 int main(int argc, char *argv[]) 25 { 26 char message = 'X'; 27 int i = 0; 28 29 //创建信号量 30 sem_id = semget((key_t)1234, 1, 0666 | IPC_CREAT); 31 32 if(argc > 1) 33 { 34 //程序第一次被调用,初始化信号量 35 if(!set_semvalue()) 36 { 37 fprintf(stderr, "Failed to initialize semaphore\n"); 38 exit(EXIT_FAILURE); 39 } 40 //设置要输出到屏幕中的信息,即其参数的第一个字符 41 message = argv[1][0]; 42 sleep(2); 43 } 44 for(i = 0; i < 10; ++i) 45 { 46 //进入临界区 47 if(!semaphore_p()) 48 exit(EXIT_FAILURE); 49 //向屏幕中输出数据 50 printf("%c", message); 51 //清理缓冲区,然后休眠随机时间 52 fflush(stdout); 53 sleep(rand() % 3); 54 //离开临界区前再一次向屏幕输出数据 55 printf("%c", message); 56 fflush(stdout); 57 //离开临界区,休眠随机时间后继续循环 58 if(!semaphore_v()) 59 exit(EXIT_FAILURE); 60 sleep(rand() % 2); 61 } 62 63 sleep(10); 64 printf("\n%d - finished\n", getpid()); 65 66 if(argc > 1) 67 { 68 //如果程序是第一次被调用,则在退出前删除信号量 69 sleep(3); 70 del_semvalue(); 71 } 72 exit(EXIT_SUCCESS); 73 } 74 75 static int set_semvalue() 76 { 77 //用于初始化信号量,在使用信号量前必须这样做 78 union semun sem_union; 79 80 sem_union.val = 1; 81 if(semctl(sem_id, 0, SETVAL, sem_union) == -1) 82 return 0; 83 return 1; 84 } 85 86 static void del_semvalue() 87 { 88 //删除信号量 89 union semun sem_union; 90 91 if(semctl(sem_id, 0, IPC_RMID, sem_union) == -1) 92 fprintf(stderr, "Failed to delete semaphore\n"); 93 } 94 95 static int semaphore_p() 96 { 97 //对信号量做减1操作,即等待P(sv) 98 struct sembuf sem_b; 99 sem_b.sem_num = 0; 100 sem_b.sem_op = -1;//P() 101 sem_b.sem_flg = SEM_UNDO; 102 if(semop(sem_id, &sem_b, 1) == -1) 103 { 104 fprintf(stderr, "semaphore_p failed\n"); 105 return 0; 106 } 107 return 1; 108 } 109 110 static int semaphore_v() 111 { 112 //这是一个释放操作,它使信号量变为可用,即发送信号V(sv) 113 struct sembuf sem_b; 114 sem_b.sem_num = 0; 115 sem_b.sem_op = 1;//V() 116 sem_b.sem_flg = SEM_UNDO; 117 if(semop(sem_id, &sem_b, 1) == -1) 118 { 119 fprintf(stderr, "semaphore_v failed\n"); 120 return 0; 121 } 122 return 1; 123 }
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(int argc, char *argv[]) 5 { 6 char message = 'X'; 7 int i = 0; 8 if(argc > 1) 9 message = argv[1][0]; 10 for(i = 0; i < 10; ++i) 11 { 12 printf("%c", message); 13 fflush(stdout); 14 sleep(rand() % 3); 15 printf("%c", message); 16 fflush(stdout); 17 sleep(rand() % 2); 18 } 19 sleep(10); 20 printf("\n%d - finished\n", getpid()); 21 exit(EXIT_SUCCESS); 22 }
转载于:https://www.cnblogs.com/Marineking/p/3747780.html
Linux进程间通信——使用信号量相关推荐
- Linux进程间通信(信号量)
★什么是信号量 为了防止出现多个程序同时访问一个共享数据资源而引发的问题,需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区.信号量就可以提供这样一种访问机制. ...
- Linux 进程间通信之 - 信号量
前言 很久不用,基本概念虽然还记得,估计不会用了,写个demo练练手. 概念 信号量(信号灯)本质上是一个计数器,用于协调多个进程(包括但不限于父子进程)对共享数据对象的读/写.它不以传送数据为目的, ...
- Linux进程间通信——使用共享内存
下面将讲解进程间通信的另一种方式,使用共享内存. 一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式 ...
- Linux多线程——使用信号量同步线程
http://blog.csdn.net/ljianhui/article/details/10813469/ 信号量.同步这些名词在进程间通信时就已经说过,在这里它们的意思是相同的,只不过是同步的对 ...
- linux进程间通信:system V 信号量 生产者和消费者模型编程案例
生产者和消费者模型: 有若干个缓冲区,生产者不断向里填数据,消费者不断从中取数据 两者不冲突的前提: 缓冲区有若干个,且是固定大小,生产者和消费者各有若干个 生产者向缓冲区中填数据前需要判断缓冲区是否 ...
- Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存
Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存 参考:<linux编程从入门到精通>,<Linux C程序设计大全>,<unix环境高级编程> ...
- Linux进程间通信(管道、消息队列、共享内存、信号、信号量)
目录 Linux进程间通信概述 1.管道 无名管道(pipe) 有名管道(fifo) 2.消息队列(msg) 消息队列的通信原理 消息队列相关api 消息队列收发数据 键值生成 消息队列移除 3.共享 ...
- 【 Linux 】进程间通信之信号量
进程间通信方式---信号量 1.概念 为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域.临 ...
- linux进程间通信:POSIX 共享内存
文章目录 思维导图 通信原理 优势 POSIX 共享内存 编程接口 编程案例 思维导图 之前学习过sysemV 的共享内存的实现及使用原理,参考linux进程间通信:system V 共享内存 POS ...
- Linux进程间通信(二):信号集函数 sigemptyset()、sigprocmask()、sigpending()、sigsuspend()...
我们已经知道,我们可以通过信号来终止进程,也可以通过信号来在进程间进行通信,程序也可以通过指定信号的关联处理函数来改变信号的默认处理方式,也可以屏蔽某些信号,使其不能传递给进程.那么我们应该如何设定我 ...
最新文章
- rust编程之道 pdf_深挖一篇嵌入式内核论文之后,我发现 Rust 正在悄悄改变世界...
- Python3访问纯真IP数据库的代码
- 《王者荣耀》游戏技术总监:技术架构与同步方案上做出改变?
- Linux apt命令
- 编写一个Rubygem, 如何在gem 被Install之前运行一段程序?
- vue中使用setTimeout
- priority_queue C++
- BS7799与ISO17799的发展历程
- 微博 用户画像_新浪微博数据采集方法以及数据分析(用户画像) - 八爪鱼采集器...
- ESP32烧录Arduino生成的bin文件
- sql server (sqlexpress) 服务因 3417 (0xd59) 服务性错误而停止(转自太原市李江软件开发工作室)...
- 阿里技术专家楚衡:架构制图的工具与方法论
- android音量键调节听筒音量的大小
- 基于GPT2_Chinese文本自动生成
- Pillow - putpixel操作 实现随机色的图片
- 量子计算(十四):超导量子芯片
- Mysql 性能优化教程
- 背景图自适应屏幕大小
- cycleInterpolator 循环加速器
- 2022-2028全球汽车自适应可变悬架系统行业调研及趋势分析报告