嵌入式软件开发技术:第5章 嵌入式Linux多线程编程_第1页
嵌入式软件开发技术:第5章 嵌入式Linux多线程编程_第2页
嵌入式软件开发技术:第5章 嵌入式Linux多线程编程_第3页
嵌入式软件开发技术:第5章 嵌入式Linux多线程编程_第4页
嵌入式软件开发技术:第5章 嵌入式Linux多线程编程_第5页
已阅读5页,还剩27页未读 继续免费阅读

下载本文档

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

文档简介

1

5.1线程基本编程5.2线程之间的同步与互斥5.3线程属性5.4多线程实验第5章嵌入式Linux多线程编程2

为了进一步减少处理机的空转时间,支持多处理器以及减少上下文开销,进程在演化中出现了另一个概念——线程。线程是进程内独立的一条运行路线,处理器调度的最小单元,也可以称为轻量级进程。线程可以对进程的内存空间和资源进行访问,并与同一进程中的其他线程共享。因此,线程的上下文切换的开销比创建进程小得多第5章嵌入式Linux多线程编程3

3.1.1任务多任务系统中有3个功能单位:任务、进程和线程。任务、进程和线程之间的关系:复习:

Linux下多任务机制的介绍4

3.1.2进程进程的内

存结构:3.1Linux下多任务机制的介绍5

3.1.2进程进程的内存结构:只读段:包含程序代码(.init和.text)和只读数据(.rodata);数据段:存放已初始化的全局变量和静态变量(.data)、未初始化的全局变量和静态变量(.bss);堆栈:系统自动分配,存放函数的参数值、局部变量值、返回地址;堆:存放动态分配的数据(malloc);共享库的内存映射区域:Linux动态链接库和其他共享库代码的映射区域。3.1Linux下多任务机制的介绍6

每个线程拥有有各自的栈、寄存器同一进程下的线程之间共享全局数据空间、堆空间、代码段5.1线程基本编程7

Linux系统下的多线程遵循POSIX线程接口,称为pthread。编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a。多线程程序编译 gcc-lpthreadthread.c-othread5.1线程基本编程8

最基本的线程操作:线程的创建、挂起和退出。创建线程实际上就是确定调用该线程函数的入口点,这里通常使用的函数是pthread_create()。在线程创建之后,就开始运行相关的线程函数,在该函数运行完之后,该线程也就退出了,这也是线程退出的一种方法。另一种退出线程的方法是使用函数pthread_exit(),这是线程的主动行为。

注意:在线程编程中要慎用exit()5.1线程基本编程9

pthread_join()可以用于将当前线程挂起来等待其它线程的结束。这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源就被收回。pthread_cancel()向其他线程发送终止信号,在被取消的线程的内部需要调用pthread_setcancel()函数和pthread_setcanceltype()函数设置自己的取消状态。

5.1线程基本编程10

phtread_create()函数语法:

intpthread_create(pthread_t*thread,constpthread_attr_t*attr,void*(*start_routine)(void*),void*arg);第一个参数为指向线程标识符的指针;第二个参数用来设置线程属性。设为空指针时将生成默认属性的线程;第三个参数是线程运行函数的起始地址,最后一个参数是运行函数的参数,不需要参数时最后一个参数设为空指针NULL。当创建线程成功时,函数返回0,若不为0则说明创建线程失败。创建线程成功后,新创建的线程则运行参数三和参数四确定的函数,原来的线程则继续运行下一行代码。5.1线程基本编程11

phtread_join()函数语法:用来等待一个线程的结束,相当于进程中的wait()系统调用。pthread_join()将当前线程挂起,等待线程结束。这个函数是一个线程阻塞函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源才被收回。它的函数原型为:intpthread_join(pthread_tth,void**thread_return);第一个参数为被等待的线程标识符,第二个参数为一个用户定义的指针,它可以用来存储被等待线程的返回值。5.1线程基本编程12

phtread_exit()函数语法:用来退出一个线程,是线程的主动行为。它的函数原型为:voidpthread_exit(void*retval);唯一的参数是函数的返回代码,也就是pthread_exit()调用者线程的返回值,可由pthread_join来检索。只要pthread_join中的第二个参数thread_return不是NULL,这个值将被传递给thread_return。最后要说明的是,一个线程不能被多个线程等待,否则第一个接收到信号的线程成功返回,其余调用pthread_join的线程则返回错误代码ESRCH。5.1线程基本编程13

#include<stdio.h>#include<stdlib.h>#include<pthread.h>#defineTHREAD_NUMBER 3 /*线程数*/#defineREPEAT_NUMBER 5 /*每个线程中的小任务数*/#defineDELAY_TIME_LEVELS10.0 /*小任务之间的最大时间间隔*/5.1线程基本编程——简单示例场景:创建3个线程,3个线程共用同一个执行函数,每个线程都有5次循环(可以看成5个小任务),第次循环随机等待1~10s。14

void*thrd_func(void*arg){/*线程函数例程*/

intthrd_num=(int)arg; intdelay_time=0; intcount=0; printf("Thread%disstarting\n",thrd_num); for(count=0;count<REPEAT_NUMBER;count++) { delay_time=(int)(rand()*DELAY_TIME_LEVELS/(RAND_MAX))+1; sleep(delay_time); printf("\tThread%d:job%ddelay=%d\n", thrd_num,count,delay_time); } printf("Thread%dfinished\n",thrd_num);

pthread_exit(NULL);}5.1线程基本编程——简单示例15

intmain(void){ pthread_tthread[THREAD_NUMBER]; intno=0,res; void*thrd_ret;

srand(time(NULL));

for(no=0;no<THREAD_NUMBER;no++) { /*创建多线程*/ res=pthread_create(&thread[no],NULL,thrd_func,(void*)no); if(res!=0) { printf("Createthread%dfailed\n",no); exit(res); } }5.1线程基本编程——简单示例16

printf("Createtreadssuccess\nWaitingforthreadstofinish...\n"); for(no=0;no<THREAD_NUMBER;no++) { /*等待线程结束*/ res=pthread_join(thread[no],&thrd_ret); if(!res) { printf("Thread%djoined\n",no); } else { printf("Thread%djoinfailed\n",no); } }5.1线程基本编程——简单示例编译多线程程序:gcc-lpthreadthread.c-othread17

5.2.1互斥锁线程控制由于线程共享进程的资源和地址空间,因此在对这些资源进行操作时,必须使用信号量、互斥等方法来保证对变量等临界资源的正确使用。互斥锁通常适合用于可用资源惟一时的互斥访问.信号量通常适合用于多个进程之间的同步。5.2线程之间的同步和互斥18

5.2.1互斥锁线程控制互斥锁是用一种简单的加锁方法来控制对共享资源的原子操作。互斥锁只有两种状态,也就是上锁和解锁,可以把互斥锁看作某种意义上的全局变量。在同一时刻只能有一个线程掌握某个互斥锁,拥有上锁状态的线程能够对共享资源进行操作。若其他线程希望上锁一个已经被上锁的互斥锁,则该线程就会挂起,直到上锁的线程释放掉互斥锁为止。5.2线程之间的同步和互斥19

5.2.1互斥锁线程控制互斥锁可以分为快速互斥锁、递归互斥锁和检错互斥锁.这三种锁的区别主要在于其他未占有互斥锁的线程在希望得到互斥锁时是否需要阻塞等待。快速锁是指调用线程会阻塞直至拥有互斥锁的线程解锁为止。递归互斥锁能够成功地返回,并且增加调用线程在互斥上加锁的次数。检错互斥锁为快速互斥锁的非阻塞版本,它会立即返回并返回一个错误信息。互斥锁的默认属性为快速互斥锁。5.2线程之间的同步和互斥一个线程可对该锁多次上锁而不阻塞20

5.2.1互斥锁线程控制互斥锁的基本操作:互斥锁初始化:pthread_mutex_init()互斥锁上锁:pthread_mutex_lock()互斥锁判断上锁:pthread_mutex_trylock()互斥锁解锁:pthread_mutex_unlock()消除互斥锁:pthread_mutex_destroy()5.2线程之间的同步和互斥21

5.2.1互斥锁线程控制pthread_mutex_init()函数语法:5.2线程之间的同步和互斥22

5.2.1互斥锁线程控制pthread_mutex_lock()等函数语法:5.2线程之间的同步和互斥23

5.2.1互斥锁线程控制

——利用互斥锁,实现thread.c中无序的多个线程按顺序执行(thread_mutex.c)5.2线程之间的同步和互斥24

5.2.2信号量线程控制信号量也就是操作系统中所用到的PV原子操作,它广泛用于进程或线程间的同步与互斥。信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问。PV原子操作是对整数计数器信号量sem的操作。一次P操作使sem减一,而一次V操作使sem加一。进程(或线程)根据信号量的值来判断是否对公共资源具有访问权限。当信号量sem的值大于等于零时,该进程(或线程)具有公共资源的访问权限;相反,当信号量sem的值小于零时,该进程(或线程)就将阻塞直到信号量sem的值大于等于0为止。5.2线程之间的同步和互斥25

5.2.2信号量线程控制当用于进程或线程互斥时,往往只设置一个信号量,其操作流程如右图所示。5.2线程之间的同步和互斥26

5.2.2信号量线程控制当用于进程或线程同步操作时,往往会设置多个信号量,并安排不同的初始值来实现它们之间的顺序执行。其操作流程如右图所示。5.2线程之间的同步和互斥27

5.2.2信号量线程控制Linux实现了POSIX的无名信号量,主要用于线程间的互斥与同步。这里主要介绍几个常见函数。sem_init()用于创建一个信号量,并初始化它的值。sem_wait()和sem_trywait()都相当于P操作,在信号量大于零时它们都能将信号量的值减一,两者的区别在于若信号量等于零时,sem_wait()将会阻塞进程,而sem_trywait()则会立即返回。sem_post()相当于V操作,它将信号量的值加一同时发出信号来唤醒等待的进程。sem_getvalue()用于得到信号量的值。sem_destroy()用于删除信号量。5.2线程之间的同步和互斥28

5.2.2信号量线程控制sem_init()函数语法:5.2线程之

温馨提示

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

评论

0/150

提交评论