1 / 13
文档名称:

Linux下多线程并发控制的机制分析.doc

格式:doc   页数:13
下载后只包含 1 个 DOC 格式的文档,没有任何的图纸或源代码,查看文件列表

如果您已付费下载过本站文档,您可以点这里二次下载

分享

预览

Linux下多线程并发控制的机制分析.doc

上传人:799474576 2013/8/6 文件大小:0 KB

下载得到文件列表

Linux下多线程并发控制的机制分析.doc

文档介绍

文档介绍:Linux下多线程并发控制的机制分析
Linux下并发控制原因及方法
、并发控制
如果在对linux字符设备驱动实例进行分析时,我们可能会有一个疑问,当我们调用copy_to_user和copy_from_user函数完成从用户态、内核态的读写操作的时候,如果这两个操作并发执行的话会出现一个什么样的情况?那肯定是会出现问题的,这个很容易理解,那么我们怎么去解决这一类似的问题呢?这就是我现在要探讨的linux并发控制机制。
我们在设备驱动的编写过程中要解决的一个问题就是并发的控制,也就是进程对共享资源的并发访问,而在linux中,提供了多个解决并发控制的方式,比如:中断屏蔽、原子操作、互斥锁等,下面将逐一介绍。
、中断屏蔽
中断屏蔽的概念实际上就是平常所说的开中断、关中断。在单cpu中使用中断屏蔽来避免竟态是很方便的一种方法,每次在进入临界区之前屏蔽所有的中断,访问完成后再打开中断。这项功能可以保障在执行的内核执行路径不被中断处理程序所抢占。它将使得中断与进程之间的并发不在发生,而且由于linux内核的进程调度都依赖于中断来实现,所以这样也就可以避免进程之间的并发。
中断对于内核的运行是非常重要的,在中断屏蔽期间,所有的中断都无法得到处理,因此长时间的屏蔽中断是很危险的,可能会造成数据丢失、系统崩溃等严重的后果。这就要求临界区的执行应该尽可能的快。
、原子操作
原子操作,指的是在执行的过程中不会被中断的操作。linux内核提供了一系列的函数来完成原子操作,内核代码可以安全的调用他们而不被打断。
、自旋锁
自旋锁是一种典型的互斥访问临界资源的手段。为何叫自旋锁,还得从他的工作机制说起。为了获得一个自旋锁,在cpu上运行的代码需要先执行一个原子操作,该操作测试并设置某个内存变量,而且在操作完成之前无法被打断,即别的执行单元是不能访问这个内存变量的。当测试结果表明锁已空闲,那么程序就获得者个自旋锁并继续执行它,如果测试表明锁被占用,那么程序则一直重复测试操作直到锁空闲为止,这就是自旋的概念。理解一个自旋锁也不是很困难,我们可以把它当成一个变量来看待,就像原子变量。比如两个执行单元A、B,如果A先进入,那么它将持有锁,当B也想进入的时候,但是测试出锁已经被占有,那么它将一直等待锁被释放后再进入。
二、程序功能设计
为了研究Linux下的多线程机制,设计生产者和消费者研究程序,程序结构如下图所示:
程序结构图
主线程负责创建生产者线程和消费者线程。主线程同时还负责观察产品仓库的情况,它每5秒查看一次仓库的大小和剩余产品。
生产者线程在启动以后,负责生产产品,并且往产品仓库里面放。
消费者线程在启动以后,负责消费产品,从产品里面取出产品。
当生产者线程把产品仓库放满以后,就不再生产产品,而是等待消费者取走产品后再生产。消费者把仓库取空之后,就不再从仓库中取产品,而是等待生产者生产产品后再取。
三、程序实现
环境:操作系统:RHEL5,语言:C++。在Linux中,使用Pthread库来操作线程。POSIX thread是一个标准线程定义,该标准定义一系列的多线程标准。pthreads线程库实现了POSIX线程标准,定义了一套C\C++语言下的线程库。
首先需要定义生产者线程、消费者线程、产品仓库等,在本例中,使用pthread线程库,所以生产者线程和消费者线程都定义为pthread_t类型;产品仓库则使用一个先进先出的队列来实现,这个队列类型直接使用了stl库中的list 结构。
//定义生产者和消费者线程
pthread_t producer,consumer;
//定义产品仓库,用List结构来保存。
list<int> storeList;
在主线程中使用pthread_create方法来创建了生产者线程和消费者线程,创建线程主要需要传入pthread_t类型的线程对象,以及线程的工作方法。如果线程创建函数返回的值不为0,则表示线程创建失败,可能由于没有足够的系统资源。
//创建生产者线程,并使其工作。
ret = pthread_create(&producer,NULL, producer_work,NULL);
//创建消费者线程,并使其工作。
ret1 = pthread_create(&consumer,NULL, consumer_work,NULL);
//如果线程创建函数返回的值不为0,则表示线程创建失败,可能由于没有足够的系统资源。
if(ret != 0 || ret1 != 0)
{
cout << "创建线程错误! \n";
exit(1);
}
在生产者线程的工作代码(produce