linux应用编程之进程间同步
一、描述
在操作系统中,异步并发执行环境下的一组进程,因为相互制约关系,进而互相发送消息、互相合作、互相等待,使得各进程按一定的顺序和速度执行,称为进程间的同步。具有同步关系的一组并发进程,称为合作进程,合作进程间互相发送的信号,称为消息或事件。
这种需要进程间同步的情况,是可以想见的,例如几个进程访问“临界资源”。而为了解决进程间的同步问题,引入信号量的概念。
二、异步执行
所谓异步执行命令,就是说一个线程用于接收解析命令,另外一个线程用于实际执行命令。实际工程中,经常会遇到有许多种命令要在一个线程中得到解析并执行,有些命令耗时短,可以在这个线程中完成;但是,有些命令耗时长,如果也放在这个线程中,则影响该线程接收(其他命令)。所以,此时可以考虑用异步执行的方案,将耗时短的命令,就放在接收解析线程中;而将耗时长的命令,则用异步执行的方案,将接收与实际执行分离,以避免接收线程受到严重阻塞。
example:
本例程中,用主线程创建了两个子线程pthread1和pthread2,其中线程pthread1用于产生命令(模仿接受解析过程),而线程pthread2用于实际执行命令。
代码如下:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<pthread.h> 4 #include <semaphore.h> 5 6 /* 将信号量定义为全局变量,方便多个线程共享 */ 7 sem_t sem; 8 9 /* 线程1和线程2的公用命令 */ 10 int gCmd = 0; 11 12 /* 同步线程1和线程2的全局变量 */ 13 static int gIsExecFlag = 0; 14 15 /* 定义线程pthread1 */ 16 static void * pthread1(void *arg) 17 { 18 /* 线程pthread1开始运行 */ 19 printf("pthread1 start!\n"); 20 21 while(1) 22 { 23 /* 等待没有命令正在执行 */ 24 while(gIsExecFlag); 25 26 /* 更新命令 */ 27 gCmd++; 28 if(gCmd == 10) 29 { 30 /* 释放信号量 */ 31 sem_post(&sem); 32 33 /* 发送命令结束 */ 34 return NULL; 35 } 36 37 /* 释放信号量 */ 38 sem_post(&sem); 39 40 /* 等待线程2执行命令 */ 41 sleep(1); 42 } 43 } 44 45 /* 定义线程pthread2 */ 46 static void * pthread2(void *arg) 47 { 48 int tmp; 49 50 /* 线程pthread2开始运行 */ 51 printf("pthread2 start!\n"); 52 53 while(1) 54 { 55 if (sem_wait(&sem) != 0) 56 { 57 printf("Error!\n"); 58 } 59 60 /* 正在执行的标志置1 */ 61 gIsExecFlag = 1; 62 63 /* 线程2接受来自线程1的命令,并打印 */ 64 tmp = gCmd; 65 printf("now execute the cmd,and the code of cmd is %d.\n", tmp); 66 67 /* 执行命令需要时间:3s,模仿实际命令执行 */ 68 sleep(3); 69 70 /* 正在执行的标志清0 */ 71 gIsExecFlag = 0; 72 73 if(gCmd == 10){ 74 /* 命令执行结束 */ 75 return NULL; 76 } 77 } 78 } 79 80 /* main函数 */ 81 int main(int agrc,char* argv[]) 82 { 83 pthread_t tidp1,tidp2; 84 85 /* 初始化信号量sem,注意初始值为0 */ 86 sem_init(&sem, 0, 0); 87 88 /* 创建线程pthread1 */ 89 if ((pthread_create(&tidp1, NULL, pthread1, NULL)) == -1) 90 { 91 printf("create error!\n"); 92 return 1; 93 } 94 95 /* 同步,让线程1先执行 */ 96 usleep(10); 97 98 /* 创建线程pthread2 */ 99 if ((pthread_create(&tidp2, NULL, pthread2, NULL)) == -1) 100 { 101 printf("create error!\n"); 102 return 1; 103 } 104 105 /* 等待线程pthread1释放 */ 106 if (pthread_join(tidp1, NULL)) 107 { 108 printf("thread is not exit...\n"); 109 return -2; 110 } 111 112 /* 等待线程pthread2释放 */ 113 if (pthread_join(tidp2, NULL)) 114 { 115 printf("thread is not exit...\n"); 116 return -2; 117 } 118 119 return 0; 120 }
代码重点解析:
进程pthread1和进程pthread2之间单纯用信号量sem同步,无法解决发送线程pthread1,在线程pthread2正在执行命令时,又写入了新的命令的问题,造成命令执行错乱。为了解决这个问题,引入全局变量gIsExecFlag用于同步。经过信号量sem和全局变量gIsExecFlag的完美配合,就可以实现命令发送与执行过程的有序配合。
测试效果
编译命令:
#arm-linux-gcc -o pthread pthread.c -lpthread
执行结果:
后续分析
由上图可知,两个线程的整体执行周期,并非是线程pthread1和线程pthread2周期的和,而是取两者中的最大者。实际上,这也很容易想见,两个线程的通信速度,取决于两个线程中速度最慢者,也对应这个结论。
经过测试,不论发送线程和执行线程的速度孰大孰小,总体的执行结果是一样的,都能保证命令执行流程的正确。所以,就可以证明上述代码的可行性。但是,需要注意的是,线程之间的同步时间还是有限制的,线程pthread1的睡眠时间应≥10ms,否则将会出现执行流程的错误。
参考资料:Linux线程的信号量同步
linux应用编程之进程间同步相关推荐
- Linux系统编程06 --进程间关系
文章目录 六.进程间关系 终端 **tty** 网络终端 进程组 会话 setsid()创建新会话函数 getsid()获取会话sid函数 守护进程 守护进程创建步骤 六.进程间关系 终端 在UN ...
- Linux系统编程(四)--进程间关系
文章目录 1 进程扇与进程链 2 进程组 2.1 概念 2.1 进程组的创建与设置 3 会话 3.1 概念 3.2 创建会话 4 控制终端.前台进程组与后台进程组 5 后台进程组与控制终端 6 孤儿进 ...
- linux 进程间读写锁,Linux系统编程—进程间同步
我们知道,线程间同步有多种方式,比如:信号量.互斥量.读写锁,等等.那进程间如何实现同步呢?本文介绍两种方式:互斥量和文件锁. ##互斥量mutex 我们已经知道了互斥量可以用于在线程间同步,但实际上 ...
- 利用管道实现进程间同步
进程间同步是指进程的运行有先后顺序,如A进程等待B进程执行完某个动作A进程才能继续往下运行.进程间通信的方法都可以用来同步,只是操作是否方便的一个问题.复习了UNIX高级编程,觉得POSIX的信号量是 ...
- android p获取通话记录_Android 底层的进程间同步机制
作者:Android面试官 进程间通信的经典实现 进程间通信(Inter-process communication,IPC)指运行在不同进程中的若干线程间的数据交换,可发生在一台机器上,也可通过网络 ...
- (28)System Verilog进程间同步(事件event)
(28)System Verilog进程间同步(事件event) 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog进程间同步(事件eve ...
- (30)System Verilog进程间同步(邮箱mailbox)
(30)System Verilog进程间同步(邮箱mailbox) 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog进程间同步(邮箱m ...
- (29)System Verilog进程间同步(旗语semaphore)
(29)System Verilog进程间同步(旗语semaphore) 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog进程间同步(旗 ...
- vbs结束进程代码_物联网学习教程—Linux系统编程之进程控制
Linux系统编程之进程控制 一.结束进程 首先,我们回顾一下 C 语言中 continue, break, return 的作用: continue: 结束本次循环 break: 跳出整个循环,或跳 ...
最新文章
- C语言实现傅里叶变换函数dft,idft,fft,ifft
- 2.1.1 物理层的基本概念
- 配置Exchange 2007边缘同步
- vue 关闭弹如何销毁子组件_vue中的eventBus会产生内存泄漏吗
- 多目标跟踪(MOT)论文随笔-SIMPLE ONLINE AND REALTIME TRACKING (SORT)
- LA 3458——Bridge
- linux tee 重定向_快乐的linux命令行-重定向
- 电子邮件乱码的解决方法
- c语言程序设计卡特兰数问题,求解圆上2N个点的连线问题(卡特兰数)
- 台式计算机接口示意图,台式机硬盘接口_台式机硬盘接口图解
- 乔本生涯, 为什么要这样做
- 想成为年薪30W+的运营,你必须具备这4个“运营思维”
- 吴恩达Course1《神经网络与深度学习》week2:神经网络基础 测验及作业
- 生产注意事项(分片集群)
- (OpenCV+Python)--目标跟踪,卡尔曼滤波+鼠标轨迹跟踪
- 【系统集成项目管理工程师】项目立项
- android 防刷机
- Rosalind第68题:Counting Optimal Alignments
- i3 1215U 和 i5 1235U选哪个好
- FirstBlood