基于ARM的多线程应用程序设计_第1页
基于ARM的多线程应用程序设计_第2页
基于ARM的多线程应用程序设计_第3页
基于ARM的多线程应用程序设计_第4页
基于ARM的多线程应用程序设计_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、开放性实验报告题 目: 基于ARM的多线程应用程序设计 院系名称: 电气工程学院 专业班级: 自动1302 学生姓名: 蒋贤坤 学 号: 201323020217 指导教师: 张晓东 成绩:指导老师签名: 目 录1 系统概况12 完成步骤12.1 思路分析12.2 结构流程图22.3 重要函数32.3.1源程序32.3.2函数分析93 实验数据123.1下载和调试截图124 结果分析和总结12设计心得15参考文献161 系统概况 生产者-消费者问题是一个经典的线程同步问题,该问题最早由Dijkstra提出,用以演示他提出的信号量机制。在同一个线程地址空间内执行的两个线程。生产者线程生产物品,然

2、后将物品放置在一个空缓冲区中供消费者线程消费。消费者线程从缓冲区中获得物品,然后释放缓冲区。当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。 多个生产/消费者在有界缓冲上操作。它利用N个字节的共享内存作为有界循环缓冲区,利用写一字符模拟放一个产品,利用读一字符模拟消费一个产品。当缓冲区空时消费者应阻塞睡眠,而当缓冲区满时生产者应当阻塞睡眠。一旦缓冲区中有空单元,生产者线程就向空单元中入写字符,并报告写的内容和位置。一旦缓冲区中有未读过的字符,消费者线程就

3、从该单元中读出字符,并报告读取位置。生产者不能向同一单元中连续写两次以上相同的字符,消费者也不能从同一单元中连续读两次以上相同的字符。2 完成步骤2.1 思路分析 本试验是练习生产者-消费者问题,成性能分析,使理解掌握线程的同步、通信以及互斥和多线程的安全问题。 一般情况下,解决互斥方法常用信号量和互斥锁,即semaphore和mutex,而解决这个问题,多采用一个类似资源槽的结构,每个槽位标示了指向资源的指针以及该槽位的状态,生产者和消费者互斥查询资源槽,判断是否有产品或者有空位可以生产,然后进行相应的操作。同时,为了告诉生产者或者消费者资源槽的情况,还要有一个消息传送机制,无论是管道还是线

4、程通信。 为了保证互斥要求,需要定义一个数据结构,这个数据结构包含两个指针,一个读一个写,同时有一个资源数目量,告诉生产者和消费者是否可以生产或者消费。由于该数据结构很小,因而可以对此结构互斥访问。同时,对于每组数据,都有一个标志位,表示此组数据是否被占用,生产者和消费者均可以先占用此位置然后完成相应的操作。 当消费者互斥访问此结构时,首先判断是否有数据可以取,如果没有,直接等待,若有数据可取,先更改标志位占用此数据,并将资源数目-1。然后交出互斥,把数据拷贝到自己缓冲区内,清空数据。当生产者访问时,首先判断有没有空位可以生产,如果没有,直接等待,若有数据可以生产,先判断该位是否被占用,如果没

5、被占用,则占用此位置进行生产。生产完成后,将占用位改为未占用,同时将资源数目+1。2.2 结构流程图 试验为生产者-消费者问题模型的实现,主程序中分别启动生产者线程和消费者线程。生产者线程不断顺序地将0到9的数字写入共享的循环缓冲区,同时消费者线程不断地从共享的循环缓冲区读取数据。试验流程图如下:图2-1 结构流程图2.3 重要函数2.3.1源程序试验代码:/*main.c*/  #include "producer.h"  #include "customer.h"  #i

6、nclude "data.h"  #include <pthread.h>  #include <stdio.h>  /* *实现生产者线程生产数据放入一个单向链表中,消费者线程负责消费数据*/  int main()     pthread_t thread_pro;     pthread_t thr

7、ead_cons;     printf("create.n");        /创建生产者线程。     pthread_create(&thread_pro,NULL,(void *)producer,NULL);     /创建消费者线程。     pthread_crea

8、te(&thread_cons,NULL,(void *)customer,NULL);     printf("finished!n");     while(1)          return 0;   /*data.h*/    #ifndef DATA_H_&#

9、160; #define DATA_H_   /单向链表数据结构  struct product    struct product *pre_product;    char product_data20;    struct product *next_product;    /向单向链表中加入一个节点(

10、生产)。  void addProduct(char *product_data);  /从单向链表中取出全部节点信息(消费)。  void consProduct();   #endif  /*data.c*/  #include "data.h"  #include <stdio.h>  #include <stdlib.h&

11、gt;  #include <string.h>   struct  product *present_product=NULL;  struct product *pre_product = NULL;  int lock=0; void addProduct(char *product_data)      while(l

12、ock=1);      lock=1;      struct product *new_product=malloc(sizeof(struct product);      if(present_product=NULL)        new_product->pre_product=NULL;

13、        strcpy( new_product->product_data,product_data);        new_product->next_product=NULL;        present_product=new_product;      el

14、se        new_product->pre_product=present_product;        strcpy( new_product->product_data,product_data);        new_product->next_product=NULL;   &#

15、160;    present_product->next_product=new_product;        present_product=new_product;            lock=0;      void consProduct()  &

16、#160;   while(lock=1);      lock=1;      while(present_product!=NULL)          pre_product=present_product->pre_product;        

17、0; printf("%sn",present_product->product_data);          if(pre_product!=NULL)            pre_product->next_product=0;        

18、60;           free(present_product);          present_product=pre_product;            lock=0;    /*producer.h*/

19、0; #ifndef PRODUCER_H_  #define PRODUCER_H_  /生产者执行生产任务  void producer();  #endif  /*producer.c*/  #include "producer.h"  #include "data.h"  #include <stdio.h>

20、  #include <string.h>  #include <stdlib.h>  int temp_i=0;  void producer()      char temp20=0;      while(1)        sprintf

21、(temp,"number_%d",temp_i);        addProduct(temp);        temp_i+;        usleep(int)(rand()/2000);          /*customer

22、.h*/  #ifndef CUSTOMER_H_  #define CUSTOMER_H_  /消费者执行消费任务。  void customer();  #endif /*customer.c*/ #include "customer.h"  #include "data.h"  #include <stdlib.h>&#

23、160; #include <stdio.h> void customer()    while(1)      consProduct();      printf("-n");      usleep(int)(rand()/1000);     

24、60;  int main(int argc, char *argv)      pthread_t producer_id;    pthread_t consumer_id; pthread_create(&producer_id, NULL, producer, NULL); void *producer(void *arg)      pthread_detach(pthread_self();

25、60;  while(1)                 pthread_mutex_lock(&mutex);          if (size = MALE_LENGTH)            

26、; printf("person:buff is full(producer)n");             producer_wait = 1;             pthread_cond_wait(&full_cond, &mutex);   

27、0;         producer_wait = 0;                 rear = (rear + 1) % MALE_LENGTH;         buffrear = rand() % MALE_LENGTH;  

28、;       printf("producer: %d: %dn", rear, buffrear);         +size;         if (size = 1)            

29、0;while (1)                 if (consumer_wait)                     pthread_cond_signal(&empty_cond); 

30、                    break;                             

31、                   pthread_mutex_unlock(&mutex);      pthread_create(&consumer_id, NULL, consumer, NULL);  void *consumer(void *arg)     

32、  pthread_detach(pthread_self();       while(1)         pthread_mutex_lock(&mutex);         if(size = 0)           &

33、#160; printf("person:buff is empty(consumer)n");             consumer_wait = 1;             pthread_cond_wait(&empty_cond, &mutex);  

34、0;          consumer_wait = 0;                    printf("consumer:%d: %dn", front, bufffront);       

35、60; front = (front + 1) % MALE_LENGTH;         -size;         if (size = MALE_LENGTH-1)             while(1)     &#

36、160;           if(producer_wait)                     pthread_cond_signal(&full_cond);        

37、60;            break;                                    

38、60;           pthread_mutex_unlock(&mutex);       sleep(1);  return 0; 2.3.2函数分析 生产者写入缓冲区和消费者从缓冲区读数的具体流程,生产者首先要获得互斥锁,并且判断资源槽是否已满,如果资源槽已满则进入等待状态,等待信号 full ;如果不满则向资源槽中写一个整数,并且释放信号为 empty,最后释放互斥

39、锁。消费者线程与生产者线程类似,流程图如下:图2-2 生产消费流程图 1)生产者写入共享的循环缓冲区入口函数  首先我们需要线程分离,调用pthread_detach()即可,线程分离是不让其他线程等待,继续运行。在主循环中我们需要给资源槽上锁,不让消费者函数访问,然后判断资源槽是否满,若为满就解锁资源槽,然后等待消费者激活信号full _cond到来。若没满就增加一个数值给资源槽,然后判断资源槽是否有数据,若有就激活消费者信号empty_cond来消费。void *producer(void *arg)      pthr

40、ead_detach(pthread_self();      while(1)                pthread_mutex_lock(&mutex);          if (size = MALE_LENGTH)    &

41、#160;         printf("person:buff is full(producer)n");             producer_wait = 1;             pthread_cond_wai

42、t(&full_cond, &mutex);             producer_wait = 0;                  rear = (rear + 1) % MALE_LENGTH;     

43、0;   buffrear = rand() % MALE_LENGTH;         printf("producer: %d: %dn", rear, buffrear);         +size;         if (size = 1)  &

44、#160;       while (1)                 if (consumer_wait)                    pthr

45、ead_cond_signal(&empty_cond);                     break;                      

46、60;                         pthread_mutex_unlock(&mutex);      2)消费者读取共享的循环缓冲区函数 GET  首先需要线程分离,调用pthread_detach()即可。在主循环中我们需要给资源槽上锁

47、,不让生产者函数访问,然后判断资源槽是否满,若不满就解锁资源槽,然后等待消生产者激活信号empty _cond到来。若满就读取一个数值,然后判断资源槽是否有数据,若无就激活生产者信号full_cond来生产。void *consumer(void *arg)      pthread_detach(pthread_self();      while(1)         pthread

48、_mutex_lock(&mutex);         if(size = 0)             printf("person:buff is empty(consumer)n");             co

49、nsumer_wait = 1;             pthread_cond_wait(&empty_cond, &mutex);             consumer_wait = 0;          

50、60;         printf("consumer:%d: %dn", front, bufffront);         front = (front + 1) % MALE_LENGTH;         -size;      

51、0;  if (size = MALE_LENGTH-1)             while(1)                 if(producer_wait)         &#

52、160;           pthread_cond_signal(&full_cond);                     break;          &#

53、160;                                     pthread_mutex_unlock(&mutex);  3 实验数据3.1下载和调试截图首先进入目录/mnt/hg

54、fs/share/JXK,然后输入命令gcc xiankun-j.c -o xiankun-j.exe -lpthread编译代码,之后运行可执行文件./xiankun-j.exe,运行结果如图3.1所示。图3.14 结果分析和总结1、具体应用情况 生产者-消费者是一个很广泛的问题,代表了多线程互斥访问共享资源,以及线程之间通信的各种问题的总和。这个可以从数据看出,简单有无等待的设置,可以让数据差异变的如此明显。毕竟,在实际应用中,生产者如何生产数据,产生怎样的数据,而消费者又如何拿到数据,是通过管道还是内存共享区,拿到数据之后,是进行处理还是写入磁盘,都有可能,因而,简单通过几组数据来判断哪

55、个进程的效率更高,是不科学的。 我们可以通过两个实际的例子来解释有无等待的情况。有等待更像是在火锅店吃火锅,商家只要把锅准备好,将生菜切好端上来即可,而顾客大量的时间用在食用上,等待的时间也很少,这样资源位置会大量被消耗,但是实际资源消耗的速度很慢,但是由于空间被占用,生产者无法继续生产。而无等待更像是快餐外卖,商家花大量时间将食物准备好,而消费者只需要交钱拿东西走人即可,资源位置空闲很多,消费者等待时间较长,但是处理数据的过程简单又节约资源。 这里还有一个问题,就是资源槽的数量,理论上这个方案应该放弃资源槽,但是从实际实现方法来看,只不过将每个资源槽的标志位移动到资源内部,然后通过读写指针进行查询,实际上这还是资源槽的变相实现方式。但是单就资源槽的数目来看,是个很复杂的问题,要保证在生产者想生产的时候不会没槽位,而消费者查询资源槽状态又不会花费太长时间,这需要具体分析每个函数执行的时间,因而本实验中只是简单设计为消费者数量的1-3倍。2、线程的调度情况 首先要考虑的是线程的调度顺序。为了方便起见,每个线程在产生的时候都有一个编号,而创

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论