分享
嵌入式Linux09.ppt
下载文档

ID:3453286

大小:1.99MB

页数:64页

格式:PPT

时间:2024-05-08

收藏 分享赚钱
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,汇文网负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。
网站客服:3074922707
嵌入式 Linux09
第9章 嵌入式Linux多线程开发,本章教学目的及要求了解Linux的多线程概念掌握Linux多线程相关的API理解Linux多线程的通信机制及常用方法,线程的概念,进程是系统中程序执行和资源分配的基本单位。每个进程都拥有自己的数据段、代码段和堆栈段,这就造成了进程在进行切换等操作时都需要有比较费时的上下文切换等动作。为了进一步减少处理机的空转时间支持多处理器和减少上下文切换开销,进程在演化中出现了另一个概念线程,线程的概念,进程是系统中程序执行和资源分配的基本单位。每个进程都拥有自己的数据段、代码段和堆栈段,这就造成了进程在进行切换等操作时都需要有比较费时的上下文切换等动作。为了进一步减少处理机的空转时间支持多处理器和减少上下文切换开销,进程在演化中出现了另一个概念线程,线程的概念,进程是系统中程序执行和资源分配的基本单位。每个进程都拥有自己的数据段、代码段和堆栈段,这就造成了进程在进行切换等操作时都需要有比较费时的上下文切换等动作。为了进一步减少处理机的空转时间支持多处理器和减少上下文切换开销,进程在演化中出现了另一个概念线程线程是一个进程内的基本调度单位,也可以称为轻量级进程。线程是在共享内存空间中并发的多道执行路径,它们共享一个进程的资源,如文件描述和信号处理。因此,大大减少了上下文切换的开销。,线程的概念,进程是系统中程序执行和资源分配的基本单位。每个进程都拥有自己的数据段、代码段和堆栈段,这就造成了进程在进行切换等操作时都需要有比较费时的上下文切换等动作。为了进一步减少处理机的空转时间支持多处理器和减少上下文切换开销,进程在演化中出现了另一个概念线程线程是一个进程内的基本调度单位,也可以称为轻量级进程。线程是在共享内存空间中并发的多道执行路径,它们共享一个进程的资源,如文件描述和信号处理。因此,大大减少了上下文切换的开销。,同进程一样,线程也将相关的变量值放在线程控制表内。一个进程可以有多个线程,也就是有多个线程控制表及堆栈寄存器,但却共享一个用户地址空间。要注意的是,由于线程共享了进程的资源和地,址空间,因此,任何线程对系统资源的操作都会给其他线程带来影响,因此,多线程中的同步就是非常重要的问题了,9.1Linux多线程相关API,Linux有多线程开发的 Pthread 库支持。涉及多线程开发的最基本概念:线程、互斥锁、条件。线程操作又分线程的创建、退出、等待。互斥锁则包括 4 种操作:创建、销毁、加锁和解锁。条件操作有 5 种操作:创建、销毁、触发、广播和等待。其他的一些线程扩展概念,如信号灯等,都可以通过上面的三个基本元素的基本操作封装出来。,9.1Linux多线程相关API,线程使用线程主要包括以下几个步骤:创建线程 调用相关线程函数 线程退出 线程资源回收,9.1.1线程的创建,Pthread不是linux系统默认的库,连接时需要使用库libthread.a,执行顺序,9.1.2线程终止,此函数用来等待一个线程的结束。这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。,9.1.2 线程终止,线程结束的两种途径:当函数结束了,调用它的线程也就结束了;另一种方式是通过函数pthread_exit 来实现。,阅读程序写出结果,9.1.3线程的标识,每个进程有一个进程ID,每个线程也有一个线程ID,进程ID在整个系统中是唯一的,但线程不同,线程ID只在它所属的进程环境中有效。线程ID用pthread_t数据类型来表示,实现的时候可以用一个结构来代表pthread_t数据类型,所以可以移植的操作系统不能把它作为整数处理。1pthread_self()函数函数用于获取自身线程的id。其函数原型为:#include pthread_t pthread_self(void);返回值:调用线程的线程id。,2pthread_equal函数pthread_equal函数用于测试两个线程号ID是否相同。其函数原型为:#include int pthread_equal(pthread_t tid1,pthread_t tid2);返回值:测试两个线程号ID是否相同。若相等返回非0值,否则返回0。函数说明:函数中的参数tid1为线程1的ID,tid2 为线程2的ID。,9.1Linux多线程相关API,Linux有多线程开发的 Pthread 库支持。涉及多线程开发的最基本概念:线程、互斥锁、条件。线程操作又分线程的创建、退出、等待。互斥锁则包括 4 种操作:创建、销毁、加锁和解锁。条件操作有 5 种操作:创建、销毁、触发、广播和等待。其他的一些线程扩展概念,如信号灯等,都可以通过上面的三个基本元素的基本操作封装出来。,9.2 线程访问控制,解决的问题:由于线程共享进程的资源和地址空间,因此在对这些资源进行操作时,必须考虑到线程资源访问的惟一性问题。主要介绍POSIX(可移植性操作系统接口)中线程同步的方法,主要有互斥锁和信号量的方式。1.mutex互斥量线程控制2.信号量线程控制,(1)说明mutex 是通过加锁来控制对共享资源的存取的一种简单方法。这个互斥量只有两种状态,也就是上锁和解锁,可以把互斥锁看作某种意义上的全局变量。,1mutex 互斥量线程控制,(1)说明mutex 是通过加锁来控制对共享资源的存取的一种简单方法。这个互斥量只有两种状态,也就是上锁和解锁,可以把互斥锁看作某种意义上的全局变量。在同一时刻只能有一个线程掌握某个互斥量上的锁,拥有上锁状态的线程能够对共享资源进行操作。若其他线程希望上锁一个已经上锁了的互斥量,则该线程就会挂起,直到上锁的线程释放掉互斥量上的锁为止。可以说,这把互斥锁使得各个线程按序操作共享资源。,1mutex 互斥量线程控制,(1)说明mutex 是通过加锁来控制对共享资源的存取的一种简单方法。这个互斥量只有两种状态,也就是上锁和解锁,可以把互斥锁看作某种意义上的全局变量。在同一时刻只能有一个线程掌握某个互斥量上的锁,拥有上锁状态的线程能够对共享资源进行操作。若其他线程希望上锁一个已经上锁了的互斥量,则该线程就会挂起,直到上锁的线程释放掉互斥量上的锁为止。可以说,这把互斥锁使得各个线程按序操作共享资源。,1mutex 互斥量线程控制,互斥锁的操作主要包括以下几个步骤,互斥锁初始化:pthread_mutex_init互斥锁上锁:pthread_mutex_lock互斥锁判断上锁:pthread_mutex_trylock互斥锁解锁:pthread_mutex_unlock消除互斥锁:pthread_mutex_destroy,互斥锁分类及区别,互斥锁可以分为快速互斥锁、递归互斥锁和检错互斥锁。这三种锁的区别主要在于其他未占有互斥锁的线程在希望得到互斥锁时,是否需要阻塞等待快速锁是指调用线程会阻塞直至拥有互斥锁的线程解锁为止。递归互斥锁能够成功地返回并且增加调用线程在互斥上加锁的次数。而检错互斥锁则为快速互斥锁的非阻塞版本,它会立即返回并返回一个错误信息。,(2)函数格式,互斥锁用pthread_mutex_t数据类型来表示,在使用互斥锁之前,必须首先对它进行初始化,通过调用pthread_mutex_init函数可以进行初始化静态和动态分配的互斥锁pthread_mutex_init函数用于初始化互斥锁。,使用默认值初始化时为NULL,对共享资源的访问,要对互斥量进行加锁,如果互斥量已经上了锁,调用线程会阻塞,直到互斥量被解锁。在完成了对共享资源的访问后,要对互斥量进行解锁。,int pthread_mutex_trylock(pthread_mutex_t*mutex);函数参数:参数mutex是互斥量返回值:成功则返回0,出错则返回错误编号函数说明:trylock函数,这个函数是非阻塞调用模式,也就是说,如果互斥量没被锁住,trylock函数将把互斥量加锁,并获得对共享资源的访问权限;如果互斥量被锁住了,trylock函数将不会阻塞等待而直接返回EBUSY,表示共享资源处于忙状态。,互斥量解锁函数,#include int pthread_mutex_unlock(pthread_mutex_t*mutex);函数参数:参数mutex是互斥量返回值:成功则返回0,出错则返回错误编号对互斥量解锁,需要调用pthread_mutex_unlock.,(3)使用实例,main线程与thread_function交替运行,都可以对run_now进行操作。,代表共享资源,访问run_now的function线程函数,创建一个线程,主线程执行的操作,主线程执行的操作,等待子线程结束以释放资源,main线程和function线程交替运行,两者都可以实现对run_now的操作。如何实现对它的锁定?,为互斥量加锁,代表共享资源,访问run_now的function线程函数,定义互斥量,main都干了什么?,初始化互斥量,创建新线程,对互斥量上锁,上锁成功显示main lock,main都干了什么?,执行循环操作,给互斥变量解锁,显示解锁成功,收回互斥变量资源,等待线程结束,释放资源,“main都干了什么?”的简化版,初始化互斥量,创建新线程,对互斥量上锁,上锁成功显示main lock,执行循环操作,给互斥变量解锁,显示解锁成功,收回互斥变量资源,等待线程结束,释放资源,简化后的main运行结果,练习,2信号量线程控制,(1)信号量说明信号量也就是操作系统中所用到的PV 原语,它广泛用于进程或线程间的同步与互斥。信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问。,PV原语,PV原语是对整数计数器信号量sem的操作。一次P操作使sem减一,而一次V操作sem加一。进程(或线程)根据信号量的值来判断是否对公共资源具有访问权限。当信号量sem 的值大于等于零时,该进程(或线程)具有公共资源的访问权限;相反,当信号量sem的值小于零时,该进程(或线程)就将阻塞直到信号量sem的值大于等于0 为止。,PV 原语主要用于进程或线程间的同步和互斥这两种典型情况。若用于互斥,几个进程(或线程)往往只设置一个信号量sem,它们的操作流程如图。,当信号量用于同步操作时,往往会设置多个信号量,并安排不同的初始值来实现它们之间的顺序执行,它们的操作流程如图。,(2)函数说明,Linux 实现了POSIX 的无名信号量(基于内存的信号量),主要用于线程间的互斥、同步。这里主要介绍几个常见函数。sem_init用于创建一个信号量,并能初始化它的值。sem_wait和sem_trywait函数用于等待共享资源,相当于P操作,它们都能将信号量的值减一,两者的区别在于若信号量小于零时,sem_wait将会阻塞进程,而sem_trywait则会立即返回。sem_post相当于V操作,它将信号量的值加一同时发出信号唤醒等待的进程。sem_getvalue用于得到信号量的值。sem_destroy用于删除信号量。,(3)函数格式,(3)函数格式,(4)使用实例,使用信号量实现对lock_var 的操作,在这里使用的是互斥操作,也就是只使用一个信号量来实现,条件变量,条件变量是利用线程间共享的全局变量进行同步的一种机制。主要包括两个动作:一个线程等待“条件变量的条件成立”而挂起;另一个线程使“条件成立”(给出条件成立信号)。为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。,条件变量的创建与注销,条件变量和互斥锁一样,都有静态动态两种创建方式。静态方式使用PTHREAD_COND_INITIALIZER常量pthread_cond_t cond=PTHREAD_COND_INITIALIZER动态方式调用pthread_cond_init()函数,API定义:int pthread_cond_init(pthread_cond_t*cond,pthread_condattr_t*cond_attr)尽管POSIX标准中为条件变量定义了属性,但在LinuxThreads中没有实现,因此cond_attr值通常为NULL,且被忽略。,条件变量的创建与注销,注销一个条件变量需要调用pthread_cond_destroy()只有在没有线程在该条件变量上等待的时候才能注销这个条件变量,否则返回EBUSY。因为Linux实现的条件变量没有分配什么资源,所以注销动作只包括检查是否有等待线程。API定义如下:int pthread_cond_destroy(pthread_cond_t*cond),条件变量的等待与触发,等待条件有两种方式:无条件等待pthread_cond_wait()计时等待pthread_cond_timedwait(),其中计时等待方式如果在给定时刻前条件没有满足,则返回ETIMEOUT,结束等待。无论哪种等待方式,都必须和一个互斥锁配合,以防止多个线程同时请求等待条件的竞争条件(Race Condition)。mutex互斥锁在调用pthread_cond_wait()前必须由本线程加锁,而在更新条件等待队列以前,mutex保持锁定状态,并在线程挂起进入等待前解锁。注:想要实现线程间的同步,需要使用互斥锁和条件变量相互配合。,互斥量、信号量、条件变量,Mutex互斥量,用于操作某个临界资源时对该资源上锁,以实现互斥地对独占资源的使用。Semophore信号量,信号量内有一计数器,可以用于对多个同类资源的分配。当资源用完时,申请资源的线程会在信号量上睡眠,有线程释放资源时,再将该线程唤醒继续运行。Condition条件变量,条件变量用于等待信号。当一个线程需要等待某个信号时,就可到条件变量上等待,当信号具备时,系统会唤醒该线程继续运行。,本章小结,本章介绍了Linux多线程开发的基本知识,以及Linux多线程相关API函数的使用等内容。通过本章的学习,要了解Linux多线程开发的基本方法,掌握Linux多线程程序的编程方法。,9作业P321习题一3、4,/*example.c*/#include#include void thread(void)int i;for(i=0;i3;i+)printf(This is a pthread.n);int main(void)pthread_t id;int i,ret;ret=pthread_create(,考试题型,1.选择题2.判断题3.填空题4.程序分析题(包括填写空余代码)5.找出程序中的错误6.会编写简单的Shell程序,

此文档下载收益归作者所有

下载文档
收起
展开