实验二、嵌入式Linux多线程编程实验
一、实验目的
1. 熟悉线程的定义、创建及应用方法,掌握编译源代码时引入线程库的方法。
2. 掌握如何利用信号量完成线程间的同步与互斥。
3. 熟悉Makefile工作原理,掌握编写Makefile的编写方法。
二、实验基本要求
1. 掌握熟悉线程的定义及操作方法。
2. 利用信号量的PV操作完成完成以下单个生产者和单个消费者模型的代码。
3. 编写在Ubuntu中编译执行的makefile文件,然后在Ubuntu中执行。
4. 编写在实验箱中编译执行的makefile文件,然后在实验箱中执行。注意Makefile编写规范缩进应使用制表键即Tab键。
三、实验原理
1.Linux线程的定义
线程(thread)是在共享内存空间中并发的多道执行路径,它们共享一个进程的资源,如文件描述和信号处理。在两个普通进程(非线程)间进行切换时,内核准备从一个进程的上下文切换到另一个进程的上下文要花费很大的开销。这里上下文切换的主要任务是保存老进程CPU状态并加载新进程的保存状态,用新进程的内存映像替换进程的内存映像。线程允许你的进程在几个正在运行的任务之间进行切换,而不必执行前面提到的完整的上下文。另外本文介绍的线程是针对POSIX线程,也就是pthread。也因为Linux对它的支持最好。相对进程而言,线程是一个更加接近于执行体的概念,它可以与同进程中的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。在串行程序基础上引入线程和进程是为了提高程序的并发度,从而提高程序运行效率和响应时间。也可以将线程和轻量级进程(LWP)视为等同的,但其实在不同的系统/实现中有不同的解释,LWP更恰当的解释为一个虚拟CPU或内核的线程。它可以帮助用户态线程实现一些特殊的功能。Pthread是一种标准化模型,它用来把一个程序分成一组能够同时执行的任务。
2. 什么场合会使用Pthread即线程
(1) 在返回前阻塞的I/O任务能够使用一个线程处理I/O,同时继续执行其他处理任务。
(2) 在有一个或多个任务受不确定性事件,比如网络通信的可获得性影响的场合,能够使用线程处理这些异步事件,同时继续执行正常的处理。
(3) 如果某些程序功能比其他的功能更重要,可以使用线程以保证所有功能都出现,但那些时间密集型的功能具有更高的优先级。
以上三点可以归纳为:在检查程序中潜在的并行性时,也就是说在要出能够同时执行任务时使用Pthread。上面已经介绍了,Linux进程模型提供了执行多个进程的能力,已经可以进行并行或并发编程,可是线程能够让你对多个任务的控制程度更好、使用资源更少,因为一个单一的资源,如全局变量,可以由多个线程共享。而且,在拥有多个处理器的系统上,多线程应用会比用多个进程实现的应用执行速度更快。
3. 信号量
信号量的值与相应资源的使用情况有关。当它的值大于0时,表示当前可用资源的数量;当它的值小于0时,其绝对值表示等待使用该资源的进程个数。注意,信号量的初值不能为负,且其值只能由P、V操作来改变。
4. 信号量的PV操作
P、V操作由P操作原语和V操作原语组成(原语是不可中断的过程),对信号量S进行操作,具体定义如下:
P(S):
① 将信号量S的值减1,即S=S-1;
② 如果S≥0,则该进程继续执行;否则该进程状态置为阻塞状态,进程PCB排入信号量PCB队列末尾,放弃CPU,等待V操作的执行。
V(S):
①    将信号量S的值加1,即S=S+1;
②    如果S≤0,释放信号量队列中第一个PCB所对应的进程,将进程状态由阻塞态改为就绪态。执行V操作的进程继续执行。
一般来说,信号量S>=0时,S表示可用资源的数量。执行一次P操作意味着请求分配一个单位资源,因此S的值减1;当S<0时,表示已经没有可用资源,请求者必须等待别的进程释放该类资源,它才能运行下去。而执行一个V操作意味着释放一个单位资源,因此S的值加1;若S<=0,表示有某些进程正在等待该资源,因此要唤醒一个阻塞状态的进程,使之成为就绪状态。
利用信号量PV操作实现线程互斥的模型:设初始化信号量S=1;且A和B共用同一临界区。
线程A              线程B                                               
P(S);            P(S);                       
临界区;            临界区;                           
  V(S);            V(S);
利用信号量PV操作实现线程同步的模型:设初始化信号量S=0;且A执行完才能执行B.
线程A              线程B                                               
执行A;            P(S)
V(S);          执行B; 
                   
  利用信号量PV操作实现线程交替同步的模型:设初始化同步信号量S1=1,同步信号量S2=0. 执行A,执行B,再执行A,执行B……,交替执行。
线程A              线程B                                               
P(S1);            P(S2);                       
执行A;              执行B;                           
  V(S2);            V(S1);
四、实验内容
1. 通过网络查资料学习线程的定义、线程的创建、线程退出、线程阻塞。
线程的概念:线程是进程内部的一条执行序列或执行路径,一个进程可以包含多条线程。线程是进行资源调度和分配的基本单位 。
(1)每个进程至少有一条执行路径,所以一个进程至少有一个线程。
(2)每个进程都有一个主线程。
线程创建:
在传统Unix进程模型中,每个进程只有一个控制线程。在POSIX线程(pthread)的情况下,程序开始运行时,它也是以单进程中的单个控制线程启动的。在创建多个控制线程以前,程序的行为与传统的进程并没有什么区别。新增的线程可以通过调用pthread_create函数创建。
#include <pthread.h>
int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
线程退出有多种方式,如return,pthread_exit,pthread_cancel等;线程分为可结合的(joinable)和 分离的(detached)两种,如果没有在创建线程时设置线程的属性为PTHREAD_CREATE_DETACHED,则线程默认是可结合的。
阻塞是指没有获得资源则挂起进程,直到获得资源为止。被挂起的进程进入休眠状态,被调度器的运行队列移走,直到等待条件被满足。阻塞不是低效率,如果设备驱动不阻塞, 用户想获取设备资源只能不断查询,消耗CPU资源,阻塞访问时,不能获取资源的进程将进入休眠,将CPU资源让给其他资源。
阻塞的进程会进入休眠状态,因此,必须确保有一个地方能唤醒休眠的进程。 唤醒进程的地方最大可能发生在中断里面,因为硬件资源获得的同时往往伴随着一个中断。
2. 通过网络查资料学习信号量的定义、信号量的初始化、信号量P操作、信号量V操作。
信号量的概念
        信号量广泛用于进程或线程间的同步和互斥, 信号量本质上是一个非负的整数计数器, 它被用来控制对公共资源的访问
        编程时可根据操作信号量值的结果判断是否对公共资源具有访问的权限, 当信号量值大于0 时, 则可以访问,否则将阻塞
      PV原语是对信号量的操作,一次P操作使信号量 sem 减1,一次V 操作使信号量 sem 加1
  信号量主要用于进程或线程间的同步和互斥这两种典型情况
      若用于互斥, 几个进程( 或线程) 往往只设置一个信号量
      若用于同步操作, 往往会设置多个信号量, 并且安排不同的初始值, 来实现它们之间的执行顺序
  信号量用于互斥
  信号量的初始化
#include <semaphore.h>
/*
*功能:
*  创建一个信号量并初始化它的值
*参数:
*  sem: 信号量的地址
*  pshared:
*    = 0,信号量在线程间共享
*    != 0,信号量在进程间共享
*  value:信号量的初始值
*return:
*  成功:0
一个线程可以包含多个进程 *  失败:-1
*/
int sem_init(sem_t *sem, int pshared, unsigned int value);
信号量 P 操作
#include <semaphore.h>
/*
*功能:
*  将信号量的值减 1,若信号量的值小于 0,此函数会引起调用者阻塞
*参数:
*  sem:信号量地址
*return:
*  成功: 0
*  失败: -1
*/
int sem_wait(sem_t *sem);
信号量的 V 操作
#include <semaphore.h>
/*
*功能:
*  将信号量的值加 1,发出信号唤醒等待线程
*参数:
*  sem:信号量地址
*return:
*  成功:
*  失败:
*/
int sem_post(sem_t *sem);
3. 掌握单个生产者与单个消费者之间共用N个缓冲区的同步问题。
    “单个生产者和单个消费者”问题描述如下:有N个缓冲区,生产者与消费者分别不停地把产品放入缓冲区和从缓冲区中拿走产品。生产者在缓冲区满时,它必须等待;消费者在缓冲区为空时,也必须等待。另外,因为缓冲区是临界资源,所以生产者和消费者之间必须交替同步执行。他们之间的关系如图所示。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。