© 2005 博创科技 北 京 博 创 兴 业 科 技 有 限 公 司 BEIJNG UNIVERSAL PIONEERING TECHNOLOGY Co., LTD 博创科技 嵌入互动 第四讲 Linux 多线程编程 北京博创兴业科技有限公司.

Slides:



Advertisements
Similar presentations
实验二 Linux 线程及信号灯 一、目的 了解并掌握 Linux 线程及信号灯。 二、要求 1 、了解 Linux 线程与信号灯使用: ( 1 ) Linux 线程 ( 2 ) Linux 信号灯 ( 3 )线程互斥 ( 4 )线程同步.
Advertisements

1 基于嵌入式 Linux 开发基础 丁男. 2 概要 基于 linux 系统开发简介 基于 linux 系统开发简介 多线程技术 多线程技术 对文件操作 对文件操作 对设备操作 对设备操作.
阻塞操作. 在 linux 里,一个等待队列由一个 wait_queue_head_t 类型的结构来描述 等待队列的初始化: static wait_queue_head_t testqueue; init_waitqueue_head(&testqueue);
多线程编程  Linux 下线程 概述  linux 线程 实现. 1 、 Linux 下线程 概述 进程是系统中程序执行和资源分配的基 本单位。每个进程有自己的数据段、代码 段和堆栈段。 线程通常叫做轻型的进程。线程是在共 享内存空间中并发执行的多道执行路径, 他们共享一个进程的资源。 因为线程和进程比起来很小,所以相对.
Oracle数据库 Oracle 子程序.
C++中的声音处理 在传统Turbo C环境中,如果想用C语言控制电脑发声,可以用Sound函数。在VC6.6环境中如果想控制电脑发声则采用Beep函数。原型为: Beep(频率,持续时间) , 单位毫秒 暂停程序执行使用Sleep函数 Sleep(持续时间), 单位毫秒 引用这两个函数时,必须包含头文件
第三讲 多线程程序设计 课程网站:CourseGrading buaa.edu.cn 主讲教师: 赵长海
Using C++ The Weird Way Something about c++11 & OOP tricks
陈香兰 助教:陈博、李春华 Spring 2009 嵌入式操作系统 陈香兰 助教:陈博、李春华 Spring 2009.
Kvm异步缺页中断 浙江大学计算机体系结构实验室 徐浩.
OpenMP简介和开发教程 广州创龙电子科技有限公司
进程及进程管理 第4章 进程及进程管理.
实践演练 广州创龙电子科技有限公司 01 广州创龙电子科技有限公司
走进编程 程序的顺序结构(二).
辅导课程六.
2017 Operating Systems 作業系統實習 助教:陳主恩、林欣穎 實驗室:720A Lab8 1.
2017 Operating Systems 作業系統實習 助教:陳主恩、林欣穎 實驗室:720A Lab10 1.
网络常用常用命令 课件制作人:谢希仁.
临界区软件互斥软件实现算法.
DM81X 视频采集处理 ——简单采集显示例程讲解 广州创龙电子科技有限公司
SPI驱动 广州创龙电子科技有限公司 Guangzhou Tronlong Electronic Technology Co., Ltd.
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
文件读写实践 广州创龙电子科技有限公司 01 广州创龙电子科技有限公司
按键驱动 广州创龙电子科技有限公司 Guangzhou Tronlong Electronic Technology Co., Ltd.
Online job scheduling in Distributed Machine Learning Clusters
本节内容 模拟线程切换 视频提供:昆山滴水信息技术有限公司 官网地址: 论坛地址: QQ交流 :
《手把手教你学STM32》 主讲人 :正点原子团队 硬件平台:正点原子STM32开发板 版权所有:广州市星翼电子科技有限公司 淘宝店铺:
如何生成设备节点 广州创龙电子科技有限公司
临界区软件互斥软件实现算法 主讲教师:夏莹杰
用event class 从input的root文件中,由DmpDataBuffer::ReadObject读取数据的问题
实验二、线程同步与通信 一、实验目的 1、掌握Linux下线程的概念; 2、了解Linux线程同步与通信的主要机制;
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
EBNF与操作语义 请用扩展的 BNF 描述 javascript语言里语句的结构;并用操作语义的方法描述对应的语义规则
简单介绍 用C++实现简单的模板数据结构 ArrayList(数组, 类似std::vector)
$9 泛型基础.
VB与Access数据库的连接.
姚金宇 MIT SCHEME 使用说明 姚金宇
3.5 线程 问题的提出 进程的引入使操作系统得以完成对并发执行的多道程序动态特征的描述和资源共享的管理,因而进程既是调度的基本单位又是资源分配的基本单位。进程所具有的这两个特点构成了程序并发执行的基础,但同时又导致进程切换过程中由于进程映像过大而带来的时空开销。因此,如果系统中创建的进程过多,或进程切换的频率过高,则会使系统效率下降,限制了并发度的进一步提高。
工业机器人知识要点解析 (ABB机器人) 主讲人:王老师
Select模型 本节内容 视频提供:昆山爱达人信息技术有限公司 视频录制:yang 官网地址:
本节内容 Win32 API中的宽字符 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
信号量(Semaphore).
<编程达人入门课程> 本节内容 为什么要使用变量? 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ:
第九节 赋值运算符和赋值表达式.
§6.7 子空间的直和 一、直和的定义 二、直和的判定 三、多个子空间的直和.
第二章 类型、对象、运算符和表达式.
《手把手教你学STM32-STemWin》 主讲人 :正点原子团队 硬件平台:正点原子STM32开发板 版权所有:广州市星翼电子科技有限公司
Pthread.
Chapter 18 使用GRASP的对象设计示例.
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
2017 Operating Systems 作業系統實習 助教:陳主恩、林欣穎 實驗室:720A Lab7.
第7章 模板 陈哲 副教授 南京航空航天大学 计算机科学与技术学院.
临界区问题的硬件指令解决方案 (Synchronization Hardware)
第二节 函数的极限 一、函数极限的定义 二、函数极限的性质 三、小结 思考题.
本节内容 Windows线程切换_时钟中断切换 视频提供:昆山滴水信息技术有限公司 官网地址: 论坛地址: QQ交流 :
工业机器人知识要点解析 (ABB机器人) 主讲人:王老师
WSAAsyncSelect 模型 本节内容 视频提供:昆山爱达人信息技术有限公司 视频录制:yang
_07多连接之select模型 本节课讲师——void* 视频提供:昆山爱达人信息技术有限公司 官网地址:
阻塞式模型 本节内容 视频提供:昆山爱达人信息技术有限公司 视频录制:yang 官网地址:
基于列存储的RDF数据管理 朱敏
C++语言程序设计 C++语言程序设计 第一章 C++语言概述 第十一组 C++语言程序设计.
本节内容 动态链接库 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
2019 Operating Systems 作業系統實習 助教:林欣穎 實驗室:720A Lab10 1.
本节内容 进程 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
2019 Operating Systems 作業系統實習 助教:林欣穎 實驗室:720A Lab11 1.
本节内容 SEMAPHORE 视频提供:昆山滴水信息技术有限公司 官网地址: 论坛地址: QQ交流 :
第二次课后作业答案 函数式编程和逻辑式编程
本节内容 this指针 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
2019 Operating Systems 作業系統實習 助教:林欣穎 實驗室:720A Lab7.
Presentation transcript:

© 2005 博创科技 北 京 博 创 兴 业 科 技 有 限 公 司 BEIJNG UNIVERSAL PIONEERING TECHNOLOGY Co., LTD 博创科技 嵌入互动 第四讲 Linux 多线程编程 北京博创兴业科技有限公司

博创科技 嵌入互动 © 2005 博创科技 Linux 多线程编程 主讲人:王君

博创科技 嵌入互动 © 2006 博创科技 进程与线程  使用多线程的理由之一是和进程相比,它是一种非常 " 节俭 " 的 多任务操作方式。  在 Linux 系统下,启动一个新的进程必须分配给它独立的地址 空间,建立众多的数据表来维护它的代码段、堆栈段和数据 段,这是一种 " 昂贵 " 的多任务工作方式。  而运行于一个进程中的多个线程,它们彼此之间使用相同的 地址空间,共享大部分数据,启动一个线程所花费的空间远 远小于启动一个进程所花费的空间,而且,线程间彼此切换 所需的时间也远远小于进程间切换所需要的时间。

博创科技 嵌入互动 © 2006 博创科技 进程与线程(二)  使用多线程的理由之二是线程间方便的通信机制。  不同的进程具有独立的数据空间,要进行数据的传 递只能通过通信的方式进行  同一进程下的线程之间共享数据空间,所以一个线 程的数据可以直接为其它线程所用

博创科技 嵌入互动 © 2006 博创科技 多线程程序的优点  提高应用程序响应。当一个操作耗时很长时,整个 系统都会等待这个操作,多线程技术会将耗时长的 操作( time consuming )置于一个新的线程。  使多 CPU 系统更加有效。操作系统会保证当线程数 不大于 CPU 数目时,不同的线程运行于不同的 CPU 上。  改善程序结构。一个既长又复杂的进程可以考虑分 为多个线程,成为几个独立或半独立的运行部分。

博创科技 嵌入互动 © 2006 博创科技 多线程编程起步  编写 Linux 下的多线程程序,需要使用头文件 pthread.h ,连接时需要使用库 libpthread.a  多线程程序实例  /* example.c*/ #include #include void thread(void) { int i; for(i=0;i<3;i++) printf("This is a pthread.\n"); }

博创科技 嵌入互动 © 2006 博创科技  int main(void) { pthread_t id; int i,ret; ret=pthread_create(&id,NULL,(void *) thread,NULL); if(ret!=0){ printf ("Create pthread error!\n"); exit (1); } for(i=0;i<3;i++) printf("This is the main process.\n"); pthread_join(id,NULL); return (0); }

博创科技 嵌入互动 © 2006 博创科技  执行: gcc example.c -lpthread -o example  -l 参数用于指定编译时要用到的库  运行生成的 example  每次运行的结果可能不同,这是因为两个线程在争 夺 CPU 资源

博创科技 嵌入互动 © 2006 博创科技 线程标识符 pthread_t  pthread_t 在头文件 /usr/include/bits/pthreadtypes.h 中定义: typedef unsigned long int pthread_t;  用来标识一个线程

博创科技 嵌入互动 © 2006 博创科技 主要 API 函数介绍  LIBC 中的 pthread 库提供了大量的 API 函数  $ cd /usr/lib

博创科技 嵌入互动 © 2006 博创科技 线程创建函数  函数原型: int pthread_create (pthread_t * thread_id , __const pthread_attr_t * __attr, void *(*__start_routine) (void *),void *__restrict __arg)  第一个参数为指向线程标识符的指针  第二个参数用来设置线程属性  第三个参数是线程运行函数的起始地址  最后一个参数是运行函数的参数  函数 thread 不需要参数,所以最后一个参数设为空指针。 第二个参数也设为空指针,这样将生成默认属性的线程。

博创科技 嵌入互动 © 2006 博创科技  当创建线程成功时,函数返回 0 ,若不为 0 则说明创 建线程失败,常见的错误返回代码为 EAGAIN 和 EINVAL 。前者表示系统限制创建新的线程,例如线 程数目过多了;后者表示第二个参数代表的线程属 性值非法。  创建线程成功后,新创建的线程则运行参数三和参 数四确定的函数,原来的线程则继续运行下一行代 码。

博创科技 嵌入互动 © 2006 博创科技 pthread_join 函数  用来等待一个线程的结束。  函数原型: int pthread_join (pthread_t __th, void **__thread_return)  第一个参数为被等待的线程标识符 。  第二个参数为一个用户定义的指针,用来存储被等 待线程返回值。  这个函数是一个线程阻塞的函数,调用它的函数将 一直等待到被等待的线程结束为止,当函数返回时, 被等待线程的资源被收回。

博创科技 嵌入互动 © 2006 博创科技 pthread_exit 函数  一个线程的结束有两种途径,一种是象我们上面的 例子,函数结束了,调用它的线程也就结束了;另 一种方式是通过函数 pthread_exit 实现 。  函数原型: void pthread_exit (void *__retval )  唯一的参数是函数的返回代码 。如果 pthread_join 中 的第二个参数 thread_return 不是 NULL ,这个值将被 传递给 thread_return 。  需要注意的是:一个线程不能被多个线程等待,否 则第一个接收到信号的线程成功返回,其余调用 pthread_join 的线程则返回错误代码 ESRCH 。

博创科技 嵌入互动 © 2006 博创科技 线程的属性  使用 pthread_create 函数创建线程时,线程参数一般 都为默认值,即将第二个参数设为 NULL ,对大多数 程序来说,使用默认属性就够了  属性结构为 pthread_attr_t ,它在头文件 /usr/include/pthread.h 中定义,属性值不能直接设置, 须使用相关函数进行操作,初始化的函数为 pthread_attr_init ,这个函数必须在 pthread_create 函 数之前调用。

博创科技 嵌入互动 © 2006 博创科技 线程的优先级  线程的优先级是线程的常用属性,  它存放在结构 sched_param 中。用函数 pthread_attr_getschedparam 和函数 pthread_attr_setschedparam 进行存放,一般是先取 优先级,对取得的值修改后再存放回去。  下面是一个简单的例子:

博创科技 嵌入互动 © 2006 博创科技  #include #include pthread_attr_t attr; pthread_t tid; sched_param param; int newprio=20; pthread_attr_init(&attr); pthread_attr_getschedparam(&attr, &param); param.sched_priority=newprio; pthread_attr_setschedparam(&attr, &param); pthread_create(&tid, &attr, (void *)myfunction, myarg);

博创科技 嵌入互动 © 2006 博创科技 互斥锁  互斥锁用来保证一段时间内只有一个线程在执行一 段代码  看下面一段代码。这是一个读 / 写程序,它们公用一 个缓冲区,并且假定一个缓冲区只能保存一条信息。 即缓冲区只有两个状态:有信息或没有信息。

博创科技 嵌入互动 © 2006 博创科技  void reader_function ( void ); void writer_function ( void ); char buffer; int buffer_has_item=0; pthread_mutex_t mutex; struct timespec delay;

博创科技 嵌入互动 © 2006 博创科技  void main ( void ){ pthread_t reader; /* 定义延迟时间 */ delay.tv_sec = 2; delay.tv_nec = 0; /* 用默认属性初始化一个互斥锁对象 */ pthread_mutex_init (&mutex,NULL); pthread_create(&reader, pthread_attr_default, (void *)&reader_function), NULL); writer_function( ); }

博创科技 嵌入互动 © 2006 博创科技  void writer_function (void){ while(1){ /* 锁定互斥锁 */ pthread_mutex_lock (&mutex); if (buffer_has_item==0){ buffer=make_new_item( ); buffer_has_item=1; } /* 打开互斥锁 */ pthread_mutex_unlock(&mutex); pthread_delay_np(&delay); } }

博创科技 嵌入互动 © 2006 博创科技  void reader_function(void){ while(1){ pthread_mutex_lock(&mutex); if(buffer_has_item==1){ consume_item(buffer); buffer_has_item=0; } pthread_mutex_unlock(&mutex); pthread_delay_np(&delay); } }

博创科技 嵌入互动 © 2006 博创科技  声明互斥锁变量 pthread_mutex_t mutex  函数 pthread_mutex_init 用来生成一个互斥锁。 NULL 参数表明使用默认属性。

博创科技 嵌入互动 © 2006 博创科技  pthread_mutex_lock 声明开始用互斥锁上锁,此后的 代码直至调用 pthread_mutex_unlock 为止,均被上 锁,即同一时间只能被一个线程调用执行。当一个 线程执行到 pthread_mutex_lock 处时,如果该锁此时 被另一个线程使用,那此线程被阻塞,即程序将等 待到另一个线程释放此互斥锁。在上面的例子中, 我们使用了 pthread_delay_np 函数,让线程睡眠一段 时间,就是为了防止一个线程始终占据此函数。 。

博创科技 嵌入互动 © 2006 博创科技 条件变量  使用互斥锁可实现线程间数据的共享和通信,互斥 锁一个明显的缺点是它只有两种状态:锁定和非锁 定。而条件变量通过允许线程阻塞和等待另一个线 程发送信号的方法弥补了互斥锁的不足,它常和互 斥锁一起使用。使用时,条件变量被用来阻塞一个 线程,当条件不满足时,线程往往解开相应的互斥 锁并等待条件发生变化。一旦其它的某个线程改变 了条件变量,相应的条件变量唤醒一个或多个正被 此条件变量阻塞的线程。这些线程将重新锁定互斥 锁并重新测试条件是否满足。

博创科技 嵌入互动 © 2006 博创科技 pthread_cond_init 函数  条件变量的结构为 pthread_cond_t ,函数 pthread_cond_init ()被用来初始化一个条件变量。 它的原型为:  int pthread_cond_init (pthread_cond_t * cond, __const pthread_condattr_t * cond_attr)  其中 cond 是一个指向结构 pthread_cond_t 的指针  cond_attr 是一个指向结构 pthread_condattr_t 的指针。 结构 pthread_condattr_t 是条件变量的属性结构

博创科技 嵌入互动 © 2006 博创科技  注意:条件变量只有在未被使用时才能重新初始化 或被释放。  释放一个条件变量的函数为 pthread_cond_ destroy ( pthread_cond_t cond )。

博创科技 嵌入互动 © 2006 博创科技 pthread_cond_wait 函数  使线程阻塞在一个条件变量上。  函数原型: extern int pthread_cond_wait (pthread_cond_t *__restrict__cond, pthread_mutex_t *__restrict __mutex)  线程解开 mutex 指向的锁并被条件变量 cond 阻塞。线程可以 被函数 pthread_cond_signal 和函数 pthread_cond_broadcast 唤醒  但是要注意的是,条件变量只是起阻塞和唤醒线程的作用, 具体的判断条件还需用户给出,例如一个变量是否为 0 等等, 线程被唤醒后,它将重新检查判断条件是否满足,如果还不 满足,一般说来线程应该仍阻塞在这里,等待被下一次唤醒。 这个过程一般用 while 语句实现。

博创科技 嵌入互动 © 2006 博创科技 pthread_cond_timedwait 函数  也可以用来阻塞线程  函数原型: extern int pthread_cond_timedwait (pthread_cond_t *__cond, pthread_mutex_t *__mutex, __const struct timespec *__abstime)  它比函数 pthread_cond_wait ()多了一个时间参数, 经历 abstime 段时间后,即使条件变量不满足,阻塞 也被解除。

博创科技 嵌入互动 © 2006 博创科技 pthread_cond_signal 函数  用来释放被阻塞在条件变量 cond 上的一个线程。  函数原型: extern int pthread_cond_signal (pthread_cond_t *__cond)  多个线程阻塞在此条件变量上时,哪一个线程被唤 醒是由线程的调度策略所决定的。

博创科技 嵌入互动 © 2006 博创科技 使用函数 pthread_cond_wait ()和函数 pthread_cond_signal ()的一个简单的例子  pthread_mutex_t count_lock; pthread_cond_t count_nonzero; unsigned count; decrement_count () { pthread_mutex_lock (&count_lock); while(count==0) pthread_cond_wait( &count_nonzero, &count_lock); count=count -1; pthread_mutex_unlock (&count_lock); }

博创科技 嵌入互动 © 2006 博创科技  increment_count(){ pthread_mutex_lock(&count_lock); if(count==0) pthread_cond_signal(&count_nonzero); count=count+1; pthread_mutex_unlock(&count_lock); }  count 值为 0 时, decrement 函数 pthread_cond_wait 处被阻塞,并打开互斥锁 count_lock 。此时,当调用 到函数 increment_count 时, pthread_cond_signal () 函数改变条件变量,告知 decrement_count ()停止 阻塞。

博创科技 嵌入互动 © 2006 博创科技  下面我们分析一下著名的生产者-消费者问题模型 的实现,主程序中分别启动生产者线程和消费者线 程。生产者线程不断顺序地将 0 到 1000 的数字写入共 享的循环缓冲区,同时消费者线程不断地从共享的 循环缓冲区读取数据。

博创科技 嵌入互动 © 2006 博创科技  产者写入缓冲区和消费者从缓冲区读数的具体流程:  生产者首先要获得互斥锁,并且判断写指针 +1 后是否等 于读指针,如果相等则进入等待状态,等候条件变 notfull ; 如果不等则向缓冲区中写一个整数,并且设置条件变量为 notempty ,最后释放互斥锁。消费者线程与生产者线程 类似 。

博创科技 嵌入互动 © 2006 博创科技