操作系统实验5线程管理与控制.docx
《操作系统实验5线程管理与控制.docx》由会员分享,可在线阅读,更多相关《操作系统实验5线程管理与控制.docx(10页珍藏版)》请在冰点文库上搜索。
操作系统实验5线程管理与控制
第4章线程管理与控制
4.1线程概念简介
每个进程都拥有自己的数据段、代码段和堆栈段,这就造成了进程在进行切换等操作时都需要有比较复杂的上下文切换等动作。
为了进一步减少处理机的空转时间,支持多处理器以及减少上下文切换开销,进程在演化中出现了另一个概念一一线程。
它是进程内独立的一条运行路线,处理器调度的最小单元,也可以称为轻量级进程。
线程可以对进程的内存空间和资源进行访问,并与同一进程中的其他线程共享。
因此,线程的上下文切换的开销比创建进程小很多。
同进程一样,线程也将相关的执行状态和存储变量放在线程控制块(TCB)内。
一个进程可以有多个线程,也就是有多个线程控制块及堆栈寄存器,但却共享一个用户地址空间。
要注意的是,山于线程共享了进程的资源和地址空间,因此,任何线程对系统资源的操作都会给其他线程带来影响。
山此可知,多线程中的同步是非常重要的问题。
在多线程系统中,进程与进程的关系如图所示。
进程
用户地址空间
线程一线程二线程三
进程与线程关系
4.2Linux多线程编程API与实验任务
4.3.1Linux多线程编程API
创建线程pthread_create()函数实际上就是确定调用该线程函数的入口点,在线程创建以后,就开始运行相关的线程函数,在该函数运行完之后,该线程也就退出了,这也是线程退出一种方法。
另一种退出线程的方法是使用函数pthread.exitO,这是线程的主动行为。
这里要注意的是,在使用线程函数时,不能随意使用exit()退出函数进行出错处理,山于exit()的作用是使调用进程终止,往往一个进程包含多个线程,因此,在使用exit()之后,该进程中的所有线程都终止了。
因此,在线程中就可以使用pthread.exitO来代替进程中的exit()o
山于一个进程中的多个线程是共享数据段的,因此通常在线程退出之后,退岀线程所占用的资源并不会随着线程的终止而得到释放。
正如进程之间可以用WditO系统调用来同步终止并释放资源-样,线程之间也有类似机制,那就是pthread_join()函数。
pthread_join()可以用于将当前线程挂起来等待线程的结束。
这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源就被收回。
(1)创建线程函数pthread_create()
功能:
创建线程和启动线程,与进程管理函数fork()的功能相似。
pthread_create()函数语法要点
所需头文件
Sinclude
函数原型
intpthread_create(pthread_t*thread,pthread_attr_tvoid*(*start_routine)(void*),void*arg))
函数传入值
thread:
线程标识符
attr:
线程属性设置(其具体设置参见9.2.3小节),通常取为NULL
start_routine:
线程函数的起始地址,是一个以指向void的指针作为参数和返回值的函数指针
arg:
传递给startroutine的参数
函数返回值
成功:
0
出错:
返回错误码
(2)线程退出函数pthread_exit()
pthread_exit()函数语法要点
所需头文件
^include
函数原型
voidpthread_exit(void*retval)
函数传入值
retval:
线程结朿时的返回值,可由其他函数如pthread_join0来获取
(3)等待线程结束函数pthread.join()
等待线程结束,读取线程的返回结果。
pthread.joinO函数语法要点
所需头文件
^include
函数原型
intpthread_join(pthread_tth,void**thread_return)
th:
等待线程的标识符
函数传入值
thread_return:
用户左义的指针,用来存储被等待线程结束时的返回值(不为NULL时)
函数返回值
成功:
0
岀错:
返回错误码
(4)线程取消函数pthread_cancel()
pthread.cancel()函数语法要点
所需头文件
^include
函数原型
intpthread_cancel((pthread_tth)
函数传入值
th:
要取消的线程的标识符
函数返回值
成功:
0
出错:
返回错误码
4.3.3Linux多线程同步API
1.线程同步信号量及系统调用
POSIX的线程同步信号量定义了3个函数:
(1)信号量初始化
函数说明:
#includeintsem_init(sem_t*sem,intpshared,unsignedvalue);
参数说明:
sem:
指向信号量变量的指针,*sem是定义好的信号量。
pshared:
为0表示进程局部信号量,通常为0
value:
信号量初始值,为1时是二值信号量
返回值:
0:
执行成功,非0执行失败
(2)信号量加1原子操作
intsem_post(sem_t*sem);
说明:
类似于进程的V操作。
(3)信号量减1原子操作
intsem_wait(sem_t*sem)
说明:
在信线程号量值为0时执行该操作使线程进入等待状态,直到另一个线程执行加1原子操作为止。
类似于进程的P操作。
2.线程互斥量及系统调用
互斥量可在多线程程序中作为临界区互斥访问手段。
操作互斥量的基本函数有:
(1)初始化函数
函数说明:
#include
intphread_mutex_init(pthread_mutex_t*mutex,
constpthread_mutexattr_texattr));
参数说明:
mutex:
定义好的互斥量指针
mutexattr:
互斥量属性,通常可以为NULL
(2)加锁操作
intpthread_mutex_lock(pthread_mutex_t*mutex);
(3)开锁操作
intpthread_mutex_unlock(pthread_mutex_t*mutex);
(4)互斥量撤销操作
intpthread_mutex_destroy(pthread_mutex_t*mutex);
4.3.4Linux多线程同步实验任务
1.用互斥量实现对4.3.2中多线程并发程序中共享变量的互斥访问。
1in—thread—4・c:
#include
#include
^include
staticinta.10000];
staticsuml,sum2,sum,p;
pthread_mutex_tmutex;//互斥量,用于共享变量访问
void*threadl(void*arg)
{
inti;
sum2=0;for(;;){pthread_mutex_lock(&mutex);
if(p<10000)7sum2=sum2-a[p」;usleep(l);
p++;pthread_mutex_unlock(&mutex);
}else{
pthread_mutex_unlock(Smutex);break;
}
}
${:
0ujniQj
:
(j*[nsoj"p^Qjqi:
u\p%stjqS[ppQJipjourns)jiuijd
:
(urns\zu\p%st[00001]他nejo师s叫»)尹巴血
!
乙ums+[uins二uins
!
(l|nsQj"ppQjqi^'dpii)uiop-peojqid
:
apzq
!
(x^munj)^oo-[un~xoinm~pp^jqjd
}"2
!
(x^iran^)^□o{un~xojnui~ppo;npd3+d
:
[djs[ums二[urns](0000l>d)孑!
!
(XQ)nin专)^ooj~XQjnui~p^ojqjd
:
[一ujniQj
-(/zu\**ioustpp^jqiJjiuiJd:
"“}
(0=id")其
(nnx'ip^^Hi"nnx:
!
=[!
]?
(++!
:
0000I>Tg)珂
:
(TE1NWznu鸟)iTUT~xsinui~p^Qjqid
1l|nsoj~ppQjqj4.UT:
s*1UT
!
T1UT
:
dp”LpsHipd
}
([jaSjp*二叫。
8;reiUT)uie(njut
J(Sums(*pyoA))iTX9~puojqjd
car傲执iiitu;z7oxfe$听jhlin-thread-4.c
cai飒buntu:
*cc■螂磐1in-thread-4.c-1pthread-o1in-thread-4
1in-thread-4.c:
1:
error:
ejgsctsd:
S:
Asrm,orl_attribute_,beforetoken”
1in-thread-4.c:
Infunctionifain,:
1in-thread-4.c:
42:
■warm略incorfiiB.tj.bleimplicitcfedarationofbuLlt-xn.functionprintf,
lin-thr©9d-4.c:
62:
陌ming:
pgaing;argument2offrthrsdoin'frvMnim>nip9.tib
lepointertype
1in-thread-4.c:
64:
iraniing:
incorfipatibleimplicitcbclarationofbuilt-in.functi
onJrintf5
carfi>untu:
1s
1in-thread-4.c
canOlbuntu:
VcocfeSvirn1in-thread-4.c
caMbuntu;VcocHi妙1in-thread-4.c-1pthread-o1in-thread-4
1in-thr^id-4.cInfunction統if:
1in-thread-4.c:
62:
^rarningtjsssingargument2ofthreadJfrowinooffipatiblepintertype
C3iVotxteS1s
1mthrzd‘1in-thread-4.c
caMbuntu;VoxHi./Iin-thread-4
thesumofsrra丈10000]is4^5000
thej^rtsumofthreadlgetis4^5000canAbuntu:
VotxteS|
2.分析、调试和执行一个多线程示例程序
该程序创建两个线程,一个线程负责读入键盘输入的文本,另一个线程负责统计和显示输入的字符个数,文本输入以“end”表示输入结束。
程序在主线程中对结束的两个线程进行归并。
lin-thread-5.c
^include
#include#include
#include
#include
#includevoid*input_text(void*arg):
void*count_text(void*arg);
〃信号量,用于线程同步
intres;〃线程函数执行的返回值
pthread_tinput_thread,stat_thread;//线程标识符变量
void*thread_result;//线程执行的返回值
//线程同步信号量初始化为0if(res!
=O){
perror(^Semaphoreinitfailed");exit(EXIT_FAILURE);
}
res=if(res!
=0){
perror("InputThreadinitfailed");exit(EXIT_FAILURE);
}
res=if(res!
=0){
perror(,?
StatThreadinitfailed");exit(EXIT_FAILURE);
■:
printf("Waitingforthreadtofinish・・・\n");
printf(^Threadsjoined'n");
sem^destroy(&bin_sem);
exit(EXIT.SUCCESS);
}
void*input_text(void*arg){
printf("Inputsometext・Enter"end'tofinish'n");
while(strncmp(/,end,\work_area,3)!
=0){fgets(work_area,W0RK_SIZE,stdin);
/*产生事件*/
};
void*stat_text(void*arg){
/*等待事件*/
while(strncmpCend"",work_area,3)!
=0){
printf("Youinput%dcharacters\nz,,strlen(work_area)-l);
}
;
S
S
Inputsometext.Entervendftofinish?
7aitingforthreadtofinish...
and
Threadsjoined
(注:
可编辑下载,若有不当之处,请指正,谢谢!
)