没有合适的资源?快使用搜索试试~ 我知道了~
嵌入式系统/ARM技术中的基于Linux系统下的多线程简单编程
3 下载量 83 浏览量
2020-10-21
21:19:27
上传
评论
收藏 181KB PDF 举报
温馨提示
引言 早在60年代线程( thread, 在台湾称作执行绪 是"进程"中某个单一顺序的控制流。)技术就被提出,但真正应用多线程到操作系统中去却是在80年代中期。这就不得不说个人了,他就是solaris,这方面的佼佼者。传统的Unix也支持线程的概念,但是在一个进程(process,是操作系统结构的基础;是一个正在执行的程序;计算机中正在运行的程序实例;可以分配给处理器并由处理器执行的一个实体;由单一顺序的执行显示,一个当前状态和一组相关的系统资源所描述的活动单元。)中只允许有一个线程,这样多线程就意味着多进程。这样就大大影响了效率。现在,多线程技术已经被许多操作系统所支持,包括Windows
资源推荐
资源详情
资源评论
嵌入式系统嵌入式系统/ARM技术中的基于技术中的基于Linux系统下的多线程简单编程系统下的多线程简单编程
引言 早在60年代线程( thread, 在台湾称作执行绪 是"进程"中某个单一顺序的控制流。)技术就被提出,但
真正应用多线程到操作系统中去却是在80年代中期。这就不得不说个人了,他就是solaris,这方面的佼佼者。
传统的Unix也支持线程的概念,但是在一个进程(process,是操作系统结构的基础;是一个正在执行的程序;
计算机中正在运行的程序实例;可以分配给处理器并由处理器执行的一个实体;由单一顺序的执行显示,一个
当前状态和一组相关的系统资源所描述的活动单元。)中只允许有一个线程,这样多线程就意味着多进程。这
样就大大影响了效率。现在,多线程技术已经被许多操作系统所支持,包括Windows
引言引言
早在60年代线程( thread, 在台湾称作执行绪 是"进程"中某个单一顺序的控制流。)技术就被提出,但真正应用多线程到
操作系统中去却是在80年代中期。这就不得不说个人了,他就是solaris,这方面的佼佼者。传统的Unix也支持线程的概念,但
是在一个进程(process,是操作系统结构的基础;是一个正在执行的程序;计算机中正在运行的程序实例;可以分配给处理
器并由处理器执行的一个实体;由单一顺序的执行显示,一个当前状态和一组相关的系统资源所描述的活动单元。)中只允许
有一个线程,这样多线程就意味着多进程。这样就大大影响了效率。现在,多线程技术已经被许多操作系统所支持,包括
Windows/NT,当然,也包括Linux。就比如以前你能看网页就不能玩游戏,玩了游戏就不能看网页,而现在你能边玩游戏边
看网页上的东西了。所以说我们现在可以边听音乐边写文,或者看网上的书都有着多线进程的功劳。接下来让我们首先了解下
进程,线程以及多线程。
简介进程,线程以及多线程简介进程,线程以及多线程
在Linux 操作系统中,一个进程(Process)相当于一个任务(Task),进程具有一段可执行的程序、专用的系统堆栈空
间、私有的"进程控制块"(即task_struct 数据结构)和独立的存储空间。
内核空间是通过进程模拟线程的, 在用户空间用pthread 创建线程。与进程相似,但是没有自己的存储空间。
接着我们说说多线程。通常单独一个程序运行时, 缺省的包含一个主线程,主线程以函数地址的形式(如main 函数)提供
程序的启动点,这就是单进程单线程的情况。若在main 函数中创建多个线程,则该程序运行时,操作系统为每个线程分配不
同的CPU 时间片,并根据线程优先级进行调度。由于每个时间片时间很短, 看上去好象各个线程是并发执行的, 实际上同一
时刻只有一个线程在运行,这就是单进程多线程的情况。若用fork 函数创建多个进程,而每个进程只采用默认的一个主线程,
则程序运行时,由内核调度操作系统,将cpu 分配给各个进程使用,这就是多进程的情况。
在前面我们知道了进程,线程以及多线程。但是我们还不知道为什么在有了进程的概念后,还要再引入线程呢?有必要性
吗?使用多线程好处在哪里?什么的系统应该选用多线程?现在我们就来回答这些问题。
我们使用多线程的第一个理由是和进程相比,它是一种非常"节俭"的多任务操作方式。我们知道,在Linux系统下,启动
一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种"昂贵"的多任
务工作方式。而运行于一个进程中的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的
空间远远小于启动一个进程所花费的空间,而且,线程间彼此切换所需的时间也远远小于进程间切换所需要的时间。据统计,
总的说来两者相差20倍左右,当然,在具体的系统上,这个数据可能会有较大的区别。但是相差很是明显的。
我们使用多线程的第二个理由是线程间方便的通信机制。每个不同进程,它们都具有独立的数据空间,要进行数据的传递
只能通过通信的方式进行,这种方式不仅费时,而且很不方便。线程则不一样,由于同一进程下的线程之间共享数据空间,所
以一个线程的数据可以直接为其它线程所用,这不仅快捷,而且方便。当然,数据的共享也带来其他一些问题,有的变量不能
同时被两个线程所修改,有的子程序中声明为static的数据更有可能给多线程程序带来灾难性的打击,这些正是编写多线程程
序时最需要注意的地方。
知道了以上两大优点,不和进程比较,多线程程序作为一种多任务、并发的工作方式,当然还有着以下的优点:
1 使多CPU系统更加有效。操作系统会保证当线程数不大于CPU数目时,不同的线程运行于不同的CPU上。
2 提高应用程序响应。这对图形界面的程序尤其有意义,当一个操作耗时很长时,整个系统都会等待这个操作,此时程序
不会响应键盘、鼠标、菜单的操作,而使用多线程技术,将耗时长的操作(time consuming)置于一个新的线程,可以避免这
种尴尬的情况。就如我们常遇到的因为某件程序机子卡了,什么事情都不能做了。现在当然我们可以把那个导致卡机的程序关
掉一切问题就解决了。但是在没有多线程程序的那会就不能这么做了,只能干等那个程序完全运行起来。
3 改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序会利于
理解和修改。
总的来说可以把一个正在运行的软件看做一个进程,就像一个大的管道,这个管道不运送什么东西,但里面有很多个小的
管道,每个小管负责的东西不同~~而这些小管道就可以看做是一个个线程~如果运行的是一个单线程的程序的话,而这个线程
需要连续运行几个功能时,如果正在运行的那个功能因碰到一个等待或者睡眠的指令的话,他就会停在那里不做任何事,此是
这个CPU就空闲在那里,同时还会等待知道程序重新继续运行~~如果使用多线程技术,那么可以把这几个功能同时(并不是
绝对意义上的同时)运行,当其中一个功能遇到睡眠指令的时候,其他没有睡眠的继续运行,这个可以花更短的时间,让
CPU更充分的被利用来完成需要的事情,线程通常共享一个代码区,但有各自独立的数据存储区。
当然每件事都有两面性,在这里也是一样的。在单cpu 的机器上,采用多进程单线程(每个进程只创建一个线程) 和单
进程多线程(一个进程创建多个线程)模型来设计程序,后者(多线程)的上下文切换开销就比前者要小的多。虽然多线程提
供的优点是单个线程的进程所欠缺的,但是它们也不乏一些缺点:
* 由于线程间共享存储器和进程状态, 一个线程的动作可能会对同一个进程中的其他线程产生影响。例如当两个线程同一
时刻访问同一个变量时, 他们之间就会产生相互干扰。
* 当多个线程试图并发调用同一个库函数时, 返回结果是不可预知的。如果多个线程调用某个库函数, 线程之间必须互
相加以协调, 确保某个时刻只有一个线程调用该库函数。
* 缺乏健壮性, 在单线程的操作系统中, 如果某个存储器出错, 操作系统会终止引发故障的进程, 但是在多线程操作系
统中, 如果一个线程出错, 操作系统将终止整个进程, 从而其他的无关线程也被终止了。这与线程的正常终止是不同的。线
程正常终止时可以通过调用exit 函数终止它所在的整个进程, 也可以终止自己而不影响进程内的其他线程。可以在主线程返
回时终止该线程, 也可以调用pthreaad_exit 终止该线程。
接下来让我们就先来尝试编写一个简单的多线程程序。
简单的多线程编程简单的多线程编程
Linux系统下的多线程遵循POSIX(可移植操作系统接口)线程接口,称为pthread。编写基于Linux下的多线程程序,需
要使用头文件pthread.h,连接时需要使用库libpthread.a。顺便说一下,Linux下pthread的实现是通过系统调用clone()来实
现的。clone()是Linux所特有的系统调用,它的使用方式类似fork,关于clone()的详细情况,有兴趣的话可以查看相关书
籍。下面我们展示两个个最简单的多线程程序example1.c和pthread_create.c 。
首先来看下多线程程序example1.c
/* example.c*/
#include <stdio.h>
#include <pthread.h>
void thread(void)
{
int i;
for(i=0;i<3;i )
printf("This is a pthread.n");
}
int main(void)
{
pthread_t id;
int i,ret;
ret=pthread_create(&id,NULL,(void *) thread,NULL);
if(ret!=0){
printf ("Create pthread error!n");
exit (1);
}
for(i=0;i<3;i )
printf("This is the main process.n");
pthread_join(id,NULL);
return (0);
}
我们编译此程序:
gcc example1.c -lpthread -o example1
运行example1,我们得到如下结果:
This is the main process.
This is a pthread.
This is the main process.
This is the main process.
This is a pthread.
This is a pthread.
再次运行,我们可能得到如下结果:
This is a pthread.
This is the main process.
This is a pthread.
This is the main process.
This is a pthread.
This is the main process.
前后两次结果不一样,这是两个线程争夺CPU资源的结果。上面的示例中,我们使用到了两个函数,pthread_create和
pthread_join,并声明了一个pthread_t型的变量。
pthread_t在头文件/usr/include/bits/pthreadtypes.h中定义:
typedef unsigned long int pthread_t;
它是一个线程的标识符。函数pthread_create用来创建一个线程,它的原型为:
extern int pthread_create __P ((pthread_t *__thread, __const pthread_attr_t *__attr,void *(*__start_routine)
(void *), void *__arg));
第一个参数为指向线程标识符的指针,第二个参数用来设置线程属性,第三个参数是线程运行函数的起始地址,最后一个
参数是运行函数的参数。这里,我们的函数thread不需要参数,所以最后一个参数设为空指针。第二个参数我们也设为空指
针,这样将生成默认属性的线程。对线程属性的设定和修改我们将在下一节阐述。当创建线程成功时,函数返回0,若不为0
则说明创建线程失败,常见的错误返回代码为EAGAIN和EINVAL。前者表示系统限制创建新的线程,例如线程数目过多了;
后者表示第二个参数代表的线程属性值非法。在创建线程成功后,新创建的线程则运行参数三和参数四确定的函数,原来的线
程则继续运行下一行代码。
函数pthread_join用来等待一个线程的结束。函数原型为:
extern int pthread_join __P ((pthread_t __th, void **__thread_return));
第一个参数为被等待的线程标识符,第二个参数为一个用户定义的指针,它可以用来存储被等待线程的返回值。这个函数
是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。一个
线程的结束有两种途径,一种是象我们上面的例子一样,函数结束了,调用它的线程也就结束了;另一种方式是通过函数
pthread_exit来实现。它的函数原型为:
extern void pthread_exit __P ((void *__retval)) __attribute__ ((__noreturn__));
唯一的参数是函数的返回代码,只要pthread_join中的第二个参数thread_return不是NULL,这个值将被传递给
thread_return。最后要说明的是,一个线程不能被多个线程等待,否则第一个接收到信号的线程成功返回,其余调用
pthread_join的线程则返回错误代码ESRCH。
我们来看看pthread_create.c是怎么样的。
********************************************************************************************
** Name:pthread_create.c
** Used to study the multithread programming in Linux OS
** Author:zeickey
** Date:2006/9/16
** Copyright (c) 2006,All Rights Reserved!
*********************************************************************************************/
#include
#include
void *myThread1(void)
{
int i;
剩余14页未读,继续阅读
资源评论
weixin_38665775
- 粉丝: 3
- 资源: 946
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功