基于arm的多线程应用程序设计大学论文.docx

上传人:b****6 文档编号:16806807 上传时间:2023-07-17 格式:DOCX 页数:18 大小:136.03KB
下载 相关 举报
基于arm的多线程应用程序设计大学论文.docx_第1页
第1页 / 共18页
基于arm的多线程应用程序设计大学论文.docx_第2页
第2页 / 共18页
基于arm的多线程应用程序设计大学论文.docx_第3页
第3页 / 共18页
基于arm的多线程应用程序设计大学论文.docx_第4页
第4页 / 共18页
基于arm的多线程应用程序设计大学论文.docx_第5页
第5页 / 共18页
基于arm的多线程应用程序设计大学论文.docx_第6页
第6页 / 共18页
基于arm的多线程应用程序设计大学论文.docx_第7页
第7页 / 共18页
基于arm的多线程应用程序设计大学论文.docx_第8页
第8页 / 共18页
基于arm的多线程应用程序设计大学论文.docx_第9页
第9页 / 共18页
基于arm的多线程应用程序设计大学论文.docx_第10页
第10页 / 共18页
基于arm的多线程应用程序设计大学论文.docx_第11页
第11页 / 共18页
基于arm的多线程应用程序设计大学论文.docx_第12页
第12页 / 共18页
基于arm的多线程应用程序设计大学论文.docx_第13页
第13页 / 共18页
基于arm的多线程应用程序设计大学论文.docx_第14页
第14页 / 共18页
基于arm的多线程应用程序设计大学论文.docx_第15页
第15页 / 共18页
基于arm的多线程应用程序设计大学论文.docx_第16页
第16页 / 共18页
基于arm的多线程应用程序设计大学论文.docx_第17页
第17页 / 共18页
基于arm的多线程应用程序设计大学论文.docx_第18页
第18页 / 共18页
亲,该文档总共18页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

基于arm的多线程应用程序设计大学论文.docx

《基于arm的多线程应用程序设计大学论文.docx》由会员分享,可在线阅读,更多相关《基于arm的多线程应用程序设计大学论文.docx(18页珍藏版)》请在冰点文库上搜索。

基于arm的多线程应用程序设计大学论文.docx

基于arm的多线程应用程序设计大学论文

开放性实验报告

 

题目:

基于ARM的多线程应用程序设计

院系名称:

电气工程学院

专业班级:

自动1302

学生姓名:

学号:

指导教师:

成绩:

指导老师签名:

日期:

2017.1.6

 

目录

1系统概况1

2完成步骤1

2.1思路分析1

2.2结构流程图2

2.3重要函数3

2.3.1源程序3

2.3.2函数分析9

3实验数据12

3.1下载和调试截图12

4结果分析和总结12

设计心得15

参考文献16

1系统概况

生产者-消费者问题是一个经典的线程同步问题,该问题最早由Dijkstra提出,用以演示他提出的信号量机制。

在同一个线程地址空间内执行的两个线程。

生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。

消费者线程从缓冲区中获得物品,然后释放缓冲区。

当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。

当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。

多个生产/消费者在有界缓冲上操作。

它利用N个字节的共享内存作为有界循环缓冲区,利用写一字符模拟放一个产品,利用读一字符模拟消费一个产品。

当缓冲区空时消费者应阻塞睡眠,而当缓冲区满时生产者应当阻塞睡眠。

一旦缓冲区中有空单元,生产者线程就向空单元中入写字符,并报告写的内容和位置。

一旦缓冲区中有未读过的字符,消费者线程就从该单元中读出字符,并报告读取位置。

生产者不能向同一单元中连续写两次以上相同的字符,消费者也不能从同一单元中连续读两次以上相同的字符。

2完成步骤

2.1思路分析

本试验是练习生产者-消费者问题,成性能分析,使理解掌握线程的同步、通信以及互斥和多线程的安全问题。

一般情况下,解决互斥方法常用信号量和互斥锁,即semaphore和mutex,而解决这个问题,多采用一个类似资源槽的结构,每个槽位标示了指向资源的指针以及该槽位的状态,生产者和消费者互斥查询资源槽,判断是否有产品或者有空位可以生产,然后进行相应的操作。

同时,为了告诉生产者或者消费者资源槽的情况,还要有一个消息传送机制,无论是管道还是线程通信。

为了保证互斥要求,需要定义一个数据结构,这个数据结构包含两个指针,一个读一个写,同时有一个资源数目量,告诉生产者和消费者是否可以生产或者消费。

由于该数据结构很小,因而可以对此结构互斥访问。

同时,对于每组数据,都有一个标志位,表示此组数据是否被占用,生产者和消费者均可以先占用此位置然后完成相应的操作。

当消费者互斥访问此结构时,首先判断是否有数据可以取,如果没有,直接等待,若有数据可取,先更改标志位占用此数据,并将资源数目-1。

然后交出互斥,把数据拷贝到自己缓冲区内,清空数据。

当生产者访问时,首先判断有没有空位可以生产,如果没有,直接等待,若有数据可以生产,先判断该位是否被占用,如果没被占用,则占用此位置进行生产。

生产完成后,将占用位改为未占用,同时将资源数目+1。

2.2结构流程图

试验为生产者-消费者问题模型的实现,主程序中分别启动生产者线程和消费者线程。

生产者线程不断顺序地将0到9的数字写入共享的循环缓冲区,同时消费者线程不断地从共享的循环缓冲区读取数据。

试验流程图如下:

图2-1结构流程图

2.3重要函数

2.3.1源程序

试验代码:

/************main.c************/  

#include "producer.h"  

#include "customer.h"  

#include "data.h"  

#include   

#include   

/******************************************************************* 

**实现生产者线程生产数据放入一个单向链表中,消费者线程负责消费数据**

********************************************************************/  

int main(){  

   pthread_t thread_pro;  

   pthread_t thread_cons;  

   printf("create....\n");     

   //创建生产者线程。

  

   pthread_create(&thread_pro,NULL,(void *)producer,NULL);  

   //创建消费者线程。

  

   pthread_create(&thread_cons,NULL,(void *)customer,NULL);  

   printf("finished!

\n");  

   while

(1){  

   }  

   return 0;  

/************data.h***********/    

#ifndef DATA_H_  

#define DATA_H_   

//单向链表数据结构  

struct product{  

  struct product *pre_product;  

  char product_data[20];  

  struct product *next_product;  

};  

//向单向链表中加入一个节点(生产)。

  

void addProduct(char *product_data);  

//从单向链表中取出全部节点信息(消费)。

  

void consProduct();   

#endif  

/***********data.c************/  

#include "data.h"  

#include   

#include   

#include    

struct product *present_product=NULL;  

struct product *pre_product = NULL;  

int lock=0; 

void addProduct(char *product_data){  

    while(lock==1);  

    lock=1;  

    struct product *new_product=malloc(sizeof(struct product));  

    if(present_product==NULL){  

      new_product->pre_product=NULL;  

      strcpy( new_product->product_data,product_data);  

      new_product->next_product=NULL;  

      present_product=new_product;  

    }else{  

      new_product->pre_product=present_product;  

      strcpy( new_product->product_data,product_data);  

      new_product->next_product=NULL;  

      present_product->next_product=new_product;  

      present_product=new_product;  

    }  

    lock=0;  

}    

void consProduct(){  

    while(lock==1);  

    lock=1;  

    while(present_product!

=NULL){  

        pre_product=present_product->pre_product;  

        printf("%s\n",present_product->product_data);  

        if(pre_product!

=NULL){  

          pre_product->next_product=0;  

        }  

        free(present_product);  

        present_product=pre_product;  

    }  

    lock=0;  

}  

/*************producer.h*************/  

#ifndef PRODUCER_H_  

#define PRODUCER_H_  

//生产者执行生产任务  

void producer();  

#endif  

/*************producer.c**************/  

#include "producer.h"  

#include "data.h"  

#include   

#include   

#include   

int temp_i=0;  

void producer(){  

    char temp[20]={0};  

    while

(1){  

      sprintf(temp,"number___%d",temp_i);  

      addProduct(temp);  

      temp_i++;  

      usleep((int)(rand()/2000));  

    }  

}  

/************customer.h***********/  

#ifndef CUSTOMER_H_  

#define CUSTOMER_H_  

//消费者执行消费任务。

  

void customer();  

#endif 

/*************customer.c*************/ 

#include "customer.h"  

#include "data.h"  

#include   

#include  

void customer(){  

  while

(1){  

    consProduct();  

    printf("-------------\n");  

    usleep((int)(rand()/1000));  

  }  

}  

intmain(intargc,char**argv) 

    pthread_tproducer_id;

    pthread_tconsumer_id;

pthread_create(&producer_id,NULL,producer,NULL);

void*producer(void*arg) { 

    pthread_detach(pthread_self());  

while

(1)

{        

        pthread_mutex_lock(&mutex);  

        if(size==MALE_LENGTH){ 

            printf("person:

buffisfull(producer)\n"); 

            producer_wait=1; 

            pthread_cond_wait(&full_cond,&mutex); 

            producer_wait=0; 

      } 

        rear=(rear+1)%MALE_LENGTH; 

        buff[rear]=rand()%MALE_LENGTH; 

        printf("producer:

%d:

%d\n",rear,buff[rear]); 

        ++size; 

        if(size==1){ 

            while

(1){ 

                if(consumer_wait){ 

                    pthread_cond_signal(&empty_cond); 

                    break; 

                } 

            } 

        } 

        pthread_mutex_unlock(&mutex); 

    } 

}

pthread_create(&consumer_id,NULL,consumer,NULL); 

void*consumer(void*arg) { 

    pthread_detach(pthread_self());  

    while

(1){ 

        pthread_mutex_lock(&mutex); 

        if(size==0){ 

            printf("person:

buffisempty(consumer)\n"); 

            consumer_wait=1; 

            pthread_cond_wait(&empty_cond,&mutex); 

            consumer_wait=0; 

        }   

        printf("consumer:

%d:

%d\n",front,buff[front]); 

        front=(front+1)%MALE_LENGTH; 

        --size; 

        if(size==MALE_LENGTH-1){ 

            while

(1){ 

                if(producer_wait){ 

                    pthread_cond_signal(&full_cond); 

                    break; 

                } 

            } 

        } 

        pthread_mutex_unlock(&mutex); 

    } 

}

 sleep

(1); 

 return0; 

}

2.3.2函数分析

生产者写入缓冲区和消费者从缓冲区读数的具体流程,生产者首先要获得互斥锁,并且判断资源槽是否已满,如果资源槽已满则进入等待状态,等待信号full;如果不满则向资源槽中写一个整数,并且释放信号为empty,最后释放互斥锁。

消费者线程与生产者线程类似,流程图如下:

图2-2生产消费流程图

1)生产者写入共享的循环缓冲区入口函数 

首先我们需要线程分离,调用pthread_detach()即可,线程分离是不让其他线程等待,继续运行。

在主循环中我们需要给资源槽上锁,不让消费者函数访问,然后判断资源槽是否满,若为满就解锁资源槽,然后等待消费者激活信号full—_cond到来。

若没满就增加一个数值给资源槽,然后判断资源槽是否有数据,若有就激活消费者信号empty_cond来消费。

void*producer(void*arg) { 

    pthread_detach(pthread_self());  

    while

(1){        

        pthread_mutex_lock(&mutex);  

        if(size==MALE_LENGTH)

            printf("person:

buffisfull(producer)\n"); 

            producer_wait=1; 

            pthread_cond_wait(&full_cond,&mutex); 

            producer_wait=0; 

        } 

        rear=(rear+1)%MALE_LENGTH; 

        buff[rear]=rand()%MALE_LENGTH; 

        printf("producer:

%d:

%d\n",rear,buff[rear]); 

        ++size; 

        if(size==1){ 

         while

(1){ 

                if(consumer_wait){

                    pthread_cond_signal(&empty_cond); 

                    break; 

                } 

            } 

        } 

        pthread_mutex_unlock(&mutex); 

    } 

}

2)消费者读取共享的循环缓冲区函数 GET 

首先需要线程分离,调用pthread_detach()即可。

在主循环中我们需要给资源槽上锁,不让生产者函数访问,然后判断资源槽是否满,若不满就解锁资源槽,然后等待消生产者激活信号empty_cond到来。

若满就读取一个数值,然后判断资源槽是否有数据,若无就激活生产者信号full_cond来生产。

void*consumer(void*arg) { 

    pthread_detach(pthread_self());  

    while

(1){ 

        pthread_mutex_lock(&mutex); 

        if(size==0){ 

            printf("person:

buffisempty(consumer)\n"); 

            consumer_wait=1; 

            pthread_cond_wait(&empty_cond,&mutex); 

            consumer_wait=0; 

        }   

        printf("consumer:

%d:

%d\n",front,buff[front]); 

        front=(front+1)%MALE_LENGTH; 

        --size; 

        if(size==MALE_LENGTH-1){ 

            while

(1){ 

                if(producer_wait){ 

                    pthread_cond_signal(&full_cond); 

                    break; 

                } 

            } 

        } 

        pthread_mutex_unlock(&mutex); 

}

3实验数据

3.1下载和调试截图

首先进入目录/mnt/hgfs/share/JXK,然后输入命令gccxiankun-j.c-oxiankun-j.exe-lpthread编译代码,之后运行可执行文件./xiankun-j.exe,运行结果如图3.1所示。

图3.1

4结果分析和总结

1、具体应用情况

生产者-消费者是一个很广泛的问题,代表了多线程互斥访问共享资源,以及线程之间通信的各种问题的总和。

这个可以从数据看出,简单有无等待的设置,可以让数据差异变的如此明显。

毕竟,在实际应用中,生产者如何生产数据,产生怎样的数据,而消费者又如何拿到数据,是通过管道还是内存共享区,拿到数据之后,是进行处理还是写入磁盘,都有可能,因而,简单通过几组数据来判断哪个进程的效率更高,是不科学的。

我们可以通过两个实际的例子来解释有无等待的情况。

有等待更像是在火锅店吃火锅,商家只要把锅准备好,将生菜切好端上来即可,而顾客大量的时间用在食用上,等待的时间也很少,这样资源位置会大量被消耗,但是实际资源消耗的速度很慢,但是由于空间被占用,生产者无法继续生产。

而无等待更像是快餐外卖,商家花大量时间将食物准备好,而消费者只需要交钱拿东西走人即可,资源位置空闲很多,消费者等待时间较长,但是处理数据的过程简单又节约资源。

这里还有一个问题,就是资源槽的数量,理论上这个方案应该放弃资源槽,但是从实际实现方法来看,只不过将每个资源槽的标志位移动到资源内部,然后通过读写指针进行查询,实际上这还是资源槽的变相实现方式。

但是单就资源槽的数目来看,是个很复杂的问题,要保证在生产者想生产的时候不会没槽位,而消费者查询资源槽状态又不会花费太长时间,这需要具体分析每个函数执行的时间,因而本实验中只是简单设计为消费者数量的1-3倍。

2、线程的调度情况

首先要考虑的是线程的调度顺序。

为了方便起见,每个线程在产生的时候都有一个编号,而创建也是按照1-Count这样的顺序for循环创建的。

如果线程调度的顺序和线程创建的顺序一样,那么在无等待情况下应该有这样的结果:

消费者远多于生产者,这样当生产者生产出数据时,前面几个优先完成等待并读取数据的进程就可以占据先机,拿到数据(这里不考虑数据消费的时间,因为程序的思路和食堂占座差不多,只要把位置占掉就可以了),而后面一些进程则由于位置不佳基本拿不到数据。

当然,插入等待时间也是一种解决资源分配的方式,这样可以保证每个线程都有机会获取到资源,不至于让某个线程连续的占用资源很长时间。

但是在实际情况下,每个线程完成工作不一样,又不可能像实验写出的进程那样无私,拿到资源后就自动等待,这就需要使用线程间通信机制了,让拿不到资源的线程挂起,生产者完成生产后再唤醒这些进程。

3、可能的改进

首先,就是线程调度的方式,忙等肯定不是一个好方法,如果换成线程间通信,轮流挂起或者唤醒某个线程,可能会更好。

其次,是消费者的资源分配问题。

程序设计的消费者有一个1024字节的buffer,用来处理接收到的数据,但是这个buffer直到线程消失才被回收,如果加上一些资源回收的机制可能会改善程序的性能。

最后,是对于生产者和消费者具体完成工作的问题,应该说这个实验设计的场景还是很简单,完全的内存拷贝,没有什么复杂运算和文件操作,而且由于手头没有原始版本的代码,无法比较两个代码的性能,整个程序的框架也是重新编写的,这应该也是一点不足。

 

    通过这次试验的

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 经管营销 > 经济市场

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2