当前位置:文档之家› 进程线程

进程线程

进程线程
进程线程

Linux 中线程的编程 (2010-10-31 16:52)

分类:linux驱动学习

线程的概念

1. 线程的优点

线程的实现时间远晚于进程.最早实现是solaris 上线程,多线程技术已

经被许多操作系统所支持,包括Windows/NT,和Linux。使用多线程的理由之一是和进程相比,它是一种非常"节俭"的多任务操作方式。启动

一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种"昂贵"的多任务工作方式。而运行于一个进程中的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据,.–线程间方便的通信机制 ,由于同一进程下的线程之间共享数据空间,所以一个线程的数据可以直接为其它线程所用,这不仅快捷,而且方便。多线程的程序会提高响应速度.特别是GUI使多CPU系统更加有效。操作系统会保证当线程数不大于CPU 数目时,不同的线程运行于不同的CPU上。改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序会利于理解和修改。

2. Linux 对线程的支持

Linux系统下的多线程遵循POSIX线程接口 ,所以被称为pthread.

pthread是目前Linux平台上使用最为广泛的线程库,由Xavier Leroy 负责开发完成,并已绑定在GLIBC中发行。

Linux内核并不支持真正意义上的线程,LinuxThreads是用与普通进程具有同样内核调度视图的轻量级进程来实现线程支持的。这些轻量级进程拥有独立的进程id,在进程调度、信号处理、IO等方面享有与普通进程一样的能力。因此一个多线程程序用ps查看,可以看到每一个线程也占用一行显行。LinuxThreads 项目最初将多线程的概念引入了 Linux,但是LinuxThreads 并不完全遵守POSIX 线程标准。一个更新的Native POSIX Thread Library(NPTL)正在应用开来.由于历史原因.有大量应用采用pthread,很多嵌入式平台也只是支持pthread库.

3. 线程与进程区别

进程是一个应用程序独立运行单位,而线程不能独立存在,必须由在一个进程创建.在Windows下,线程和进程都是内核内置的机制,而Linux一开始就在内核创建进程机制,直到2.2后才开始加入线程实现,到2.6才稳定Linux的线程库

是基于应用库实现,远没有基于内核的进程稳定.在重负衡的关键任务的服务器,往往采用多进程机制实现.

进程空间

每个进程都独立占有4G的独立虚拟内存空间,各自拥有完整的堆,栈,代码段和数据段在调用fork时,子进程完全从父进程4G空间复制过来这意味,现有堆栈的局域变量,全局变量等的值完全一样在fork后,父子进程各自独立修改自己空间的变量两者即便是有同名变量,各自值也是独立修改进程间,包括父子进程之间交换数据必须需要进程间通讯机制来实现

线程空间

同一个进程创建的所有线程之间共享创建进程的空间,即大家拥有相同2G 空间,当一个线程修改一个全局变量后,另一个线程也访问得到这个值因此在多线程并发修改某个值,必须要进行加锁保护,以便能正确修改值,Linux 线程基本编程

Linux 线程的基本函数

l 常用线程函数

– pthread_create 创建一个线程

– pthead_exit 线程自行退出

– pthread_join 其它线程等待某一个线程退出

– pthread_cancel 其它线程强行杀死某一个线程

pthread线程库的使用

– glib库内置了线程库.

–在源码中使用头文件 pthread.h

–用gcc链接时加上–lpthread 选项,链接线程库

1)pthread_create 创建一个线程

l 线程的创建

–int pthread_create(pthread_t *thread,pthread_attr_t *attr,

void *(*start_routine)(void *), void *arg);

pthread_create创建一个线程,thread是用来表明创建线程的ID,attr 指出线程创建时候的属性,我们用NULL来表明使用缺省属性.start_routine函数指针是线程创建成功后开始执行的函数,arg是这个函数的唯一一个参数.表

明传递给start_routine的参数.一个进程中的每个线程都由一个线程ID (thread ID)标识,其数据类型是pthread_t(常常是unsigned int)。如果新的线程创建成功,其ID将通过thread指针返回。

2)pthread_exit 退出一个线程

线程的退出有两种方式,一种线程函数运行结束,比如到函数结尾或用

return退出.线程自然结束.这是最常用的方式.

调用pthread_exit退出.

– void pthread_exit(void *retval);

退出当前线程,并且设线程的返回值为retval

返回值可以用pthread_join取得

pthread_join 等待线程退出

int pthread_join(pthread *thread,void **thread_return);

这个函数类似于waitpid,pthread_join是当前线程在等待另一个线程结束,只不过前者是在等待一个进程退出,后者在等待一个线程编号为thread的线程退出.当一个线程调用pthread_exit时,如果其它线程或进程使用了

pthead_join在等待这个线程结束,那线程ID和退出状态将一直保留到

pthread_join执行时.

pthread_exit()设定的返回值,或者return的返回值可以被pthread_join的thread_return捕获

4)pthread_cancel 杀死一个线程

pthread_cancel(pthread_t thread) ;

当前线程将杀死线程ID为thread的线程

pthread_exit()是当前线程自已退出,而pthread_cancel是其它线程杀死别的线程

2. 关于线程的生存周期

程序的主进程默认为主线程.

一个子线程的生存周期由pthread_create 创建后开始,

一直到线程函数执行完毕,或者执行到pthread_exit 处.线程的生命到此结束.

其它线程可以用pthread_cancel强制杀死另一线程.

主线程退出,(比如在主函数里调用exit),它的子线程无论是否执行完毕,都

会随主线程退出而一同消失.(所以在主线程退出之前要等待子线程先退出,子线程先退出就可以释放某些资源,如果不等待子线程退出,子线程将会随主线程一起强制退出,这样子线程的资源可能就不能释放,可能就会造成系统内存泄露。所以必须调用pthread_join()来等待子线程的退出)

所以在一般在主函数里,必须要判断的一下子线程是否真正退出,如是方可以把主线程退出.否则很可能造成程序结果不正确

判断线程是否结束最简单的方法是在主线程的退出用 pthread_join来等

待子线程退出即可线程示例

#include

#include

#define RUN_TIME 10

void * thread(void * arg)

{

int i;

for(i=0;i

{ printf("This is a pthread.\n"); sleep(1);}

}

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);

}

3. 修改线程的属性

绝大部分情况下,创建线程使用了默认参数,即将pthread_create函数的第二个参数设为

NULL。

在特殊情况才需要设置线程属性pthread_attr_t,

属性对象主要包括是否绑定、是否分离、堆栈地址、堆栈大小、优先级。默认的属性

为非绑定、非分离、缺省1M的堆栈、与父进程同样级别的优先级。

初始化线程属性

– pthread_attr_init(&attr);

–这个函数必须在pthread_create函数之前调用

设置线程绑定特性

– pthread_attr_setscope

–设置线程绑定状态的函数为pthread_attr_setscope,它有两个参数,第一个是指向属

性结构的指针,第二个是绑定类型,它有两个取值:PTHREAD_SCOPE_SYSTEM(绑定的)和PTHREAD_SCOPE_PROCESS(非绑定的)。下面的代码即创建了一个绑定的线程。

l 设置线程的优先级

–它存放在结构sched_param

–用函数pthread_attr_getschedparam和函数pthread_attr_setschedparam 进行存

放,一般说来,我们总是先取优先级,对取得的值修改后再存放回去

修改线程属性实例

多线程拷贝文件实例

#include

#include

pthread_attr_t attr;

pthread_t tid;

struct sched_param param;

int newprio=20;

pthread_attr_init(&attr);

pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);

pthread_attr_getschedparam(&attr, ¶m);

param.sched_priority=newprio; //设置优先级

pthread_attr_setschedparam(&attr, ¶m);

pthread_create(&tid, &attr, (void *)myfunction, myarg);

for(i=0;i

{

printf("This is the main process.\n");

sleep(1);

}

pthread_join(id,NULL);

return (0);

}

扫描一个目录,把这一个目录下所有文件名加上*.bak复制一次

这一个实例为每一个文件创建一个线程进行拷贝

没有做优化.因此文件较多的情况下,线程可能较多

每个程序在内部使用read,write来处理文件

Windows线程支持

1. Windows线程

l Windows线程机制非常类似Linux的线程调用.

–包含头文件

–表示线程数据结构 unsigned long

–创建一个线程 _beginthread

l unsigned long _beginthread( void( __cdecl *start_address )( void * ), unsigned stack_size, void *arglist );

l 第一个参数为线程函数,第二个函数为堆栈空间,取0由系统分配一个缺省尺寸,第三

是线程函数参数,当线程创建时,arglist 将传送给线程函数

–线程函数执行完毕,将自动销毁线程,或提前用_endthread()进行销毁

–链接时时候需要使用LIBMT.LIB

2. CreateThread:创建一个线程

l CreateThread()实现在Windows内核,即kernel.dll的实现,_beginthread实际上是调用

CreateThread()来创建一个线程

l 如果想对线程做更复杂的控制,可以使用CreateThread来创建一个线程.

– CreateThread创建线程数据结构用handle表示

–用CreateThread创建可以对线程做更多控制,如挂起,等待…

#include

#include

#include

#include

static void thread_func(void * arg)

{

int i,count = (int)arg;

fprintf(stderr,"count =%d,pid=%d\n",count,getpid());

for(i=0; i< count ; i++)

{

fprintf(stderr," I am a thread %d\n",count);

Sleep(1000);

}

}

int main()

{

_beginthread(thread_func,0,(void *)10);

_beginthread(thread_func,0,(void *)20);

getchar();

}

3. WaitForSingleObject

l WaitForSingleObject从字面意思上可以理解为等待单个对象,在Windows下,线程,互斥量,

事件等各个操作系统对象都用使用这个参数.

l 如果是一个线程被等待,相当于是pthread_join的功能,在等待一个线程运行完毕

l WaitForSingleObject的优点之一是可以带超时参数,即到了指定时间未等想要结果,可以

结束等待,而pthread_join无此功能.

–用宏定义INFINITE 表示无穷大,即无限等待下去

– WaitForSingleObject(thread, INFINITE);

l 将test_mutex例子用Windows来实现

– 1.线程用_beginThread或CreateThread

– 2.加锁用WaitSingleObject来lock,用ReleaseMutex来解锁

–具体对应表参见上页,调用请参见MSDN

–最好定义一组相同接口的宏来封装操作系统细节,

l 要求设计一个双线程结构

–输入线程负责接收用户输入,并把结果通过消息队列发往服务器.用

read(0…)或getchar均

可实现

–显示线程接收输入线程发来的字符串,并显示在屏幕上.

–消息队列用数组+mutex/链表来实现

HANDLE CreateThread(

LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD

DWORD dwStackSize, // initial stack size

LPTHREAD_START_ROUTINE lpStartAddress, // thread function

LPVOID lpParameter, // thread argument

DWORD dwCreationFlags, // creation option

LPDWORD lpThreadId // thread identifier );

进程与线程的区别 进程的通信方式 线程的通信方式

进程与线程的区别进程的通信方式线 程的通信方式 进程与线程的区别进程的通信方式线程的通信方式2011-03-15 01:04 进程与线程的区别: 通俗的解释 一个系统运行着很多进程,可以比喻为一条马路上有很多马车 不同的进程可以理解为不同的马车 而同一辆马车可以有很多匹马来拉--这些马就是线程 假设道路的宽度恰好可以通过一辆马车 道路可以认为是临界资源 那么马车成为分配资源的最小单位(进程) 而同一个马车被很多匹马驱动(线程)--即最小的运行单位 每辆马车马匹数=1 所以马匹数=1的时候进程和线程没有严格界限,只存在一个概念上的区分度 马匹数1的时候才可以严格区分进程和线程 专业的解释: 简而言之,一个程序至少有一个进程,一个进程至少有一个线程.

线程的划分尺度小于进程,使得多线程程序的并发性高。另外,进程在执 行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序 的运行效率。 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行 的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在 应用程序中,由应用程序提供多个线程执行控制。 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可 以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程 的调度和管理以及资源分配。这就是进程和线程的重要区别。 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位. 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的 能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中 必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的 其他的线程共享进程所拥有的全部资源. 一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以 并发执行 进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有 独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响, 而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线 程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程 的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。如果有兴趣深入的话,我建议你们看看《现代操作系统》或者 《操作系统的设计与实现》。对就个问题说得比较清楚。 +++ 进程概念

第二章进程管理答案

第二章进程管理 一、单项选择题 1、顺序程序和并发程序的执行相比,()。 A.基本相同 B. 有点不同 C.并发程序执行总体上执行时间快 D.顺序程序执行总体上执行时间快 2、在单一处理机上,将执行时间有重叠的几个程序称为()。 A.顺序程序 B. 多道程序 C.并发程序 D. 并行程序 3、进程和程序的本质区别是()。 A.存储在内存和外存 B.顺序和非顺序执行机器指令 C.分时使用和独占使用计算机资源 D.动态和静态特征 4、在下列特性中,不是进程的特性的是()。 A. 异步性 B. 并发性 C. 静态性 D. 动态性 5 A 6 A. 7 A. 8 A. 9 A. 10 A. 11 A. 12。 A. 13 A. 14 A. 15 A. 16、在操作系统中,对信号量S的P原语操作定义中,使进程进入相应阻塞队列等待的条件是()。 A. S>0 B. S=0 C. S<0 D. S≠0 17、信号量S的初值为8,在S上执行了10次P操作,6次V操作后,S的值为()。 A.10 B.8 C.6 D.4 18、在进程通信中,使用信箱方式交换信息的是()。 A.低级通信B.高级通信C.共享存储器通信D.管道通信 19.( )必定会引起进程切换。A.一个进程被创建后进入就绪态B.一个进程从运行态变成等待态c.一个进程从运行态变成就绪态 D.一个进程从等待态变成就绪态 20、操作系统使用( )机制使计算机系统能实现进程并发执行,保证系统正常工作。 A.中断B.查询c.同步D互斥 21.对于一个单处理器系统来说,允许若干进程同时执行,轮流占用处理器.称它们为()的。 A.顺序执行 B.同时执行c.并行执行D.并发执行

操作系统第二章进程和线程复习题

第二章练习题 一、单项选择题 1.某进程在运行过程中需要等待从磁盘上读入数据,此时该进程的状态将( C )。 A. 从就绪变为运行; B.从运行变为就绪; C.从运行变为阻塞; D.从阻塞变为就绪 2.进程控制块是描述进程状态和特性的数据结构,一个进程( D )。 A.可以有多个进程控制块; B.可以和其他进程共用一个进程控制块; C.可以没有进程控制块; D.只能有惟一的进程控制块。 3.临界区是指并发进程中访问共享变量的(D)段。 A、管理信息 B、信息存储 C、数 据 D、程序 4. 当__ B__时,进程从执行状态转变为就绪状态。 A. 进程被调度程序选中 B. 时间片到 C. 等待某一事件 D. 等待的事件发生 5. 信箱通信是一种( B )通信方式。 A. 直接通信 B. 高级通信 C. 低级通信 D. 信号量 6. 原语是(B)。

A、一条机器指令 B、若干条机器指令组成 C、一条特定指令 D、中途能打断的指令 7. 进程和程序的一个本质区别是(A)。 A.前者为动态的,后者为静态的; B.前者存储在内存,后者存储在外存; C.前者在一个文件中,后者在多个文件中; D.前者分时使用CPU,后者独占CPU。 8. 任何两个并发进程之间存在着(D)的关系。 A.各自完全独立B.拥有共享变量 C.必须互斥D.可能相互制约 9. 进程从运行态变为等待态可能由于(B )。 A.执行了V操作 B.执行了P操作 C.时间片用完 D.有高优先级进程就绪 10. 用PV操作管理互斥使用的资源时,信号量的初值应定义为(B)。 A.任意整数 B.1 C.0 D.-1 11. 现有n个具有相关临界区的并发进程,如果某进程调用P操作后变为等待状态,则调用P操作时信号量的值必定为(A)。 A.≤0 B.1 C.n-1 D.n

查看程序的进程和线程实验报告

查看程序的进程和线程实验报告 篇一:程序实验2:11-多线程编程---实验报告 程序实验二:11-多线程编程实验 专业班级实验日期 5.21 姓名学号实验一(p284:11-thread.c) 1、软件功能描述 创建3个线程,让3个线程重用同一个执行函数,每个线程都有5次循环,可以看成5个小任务,每次循环之间会有随即等待时间(1-10s)意义在于模拟每个任务到达的时间是随机的没有任何的特定规律。 2、程序流程设计 3.部分程序代码注释(关键函数或代码) #include #include #include #define T_NUMBER 3 #define P_NUMBER 5 #define TIME 10.0

void *thrd_func(void *arg ) { (本文来自:https://www.doczj.com/doc/9810375918.html, 小草范文网:查看程序的进程和线程实验报告) int thrd_num=(int)arg; int delay_time =0; int count =0; printf("Thread %d is staraing\n",thrd_num); for(count=0;count { delay_time =(int)(rand()*TIME/(RAND_MAX))+1; sleep(delay_time); printf("\tTH%d:job%d delay =%d\n",thrd_num,count,delay_time); } printf("%d finished\n",thrd_num); pthread_exit(NULL); } int main()

操作系统--进程和线程实验报告

一.进程的创建 1.编辑源程序。 2. 编辑结果如下。 3.编译和运行程序。 4.运行解释结果 在语句p1=fork()之前,只有一个进程在执行这段代码,但在这条语句之后,就变成两个进程在执行了.这两个进程的几乎完全相同,将要执行的下一条语句都是if(p1==0). 而fork函数有三种返回值。(1)在父进程中,fork返回新创建子进程的进程ID; (2)在子进程中,fork返回0; (3)如果出现错误,fork返回一个负值; 所以,子进程中p1==0,输出I am child。父进程p1>0,输出I am parent。

1.编辑源程序。 2.编辑结果如下。 3.编译和运行程序。 4. 运行解释结果 在语句p1=fork()之前,只有父进程执行,putchar(‘x’)语句将x放入父进程的缓冲区。当成功创建子进程后,子进程复制父进程的缓冲区。接着子进程运行输出xby,父进程输出xay。

1.编辑源程序。 2.编辑结果如下。 3.编译和运行程序。 4. 运行解释结果 在语句p1=fork()之前,只有父进程执行,putchar(‘x’)语句将x放入父进程的缓冲区。当成功创建子进程后,子进程复制父进程的缓冲区。接着子进程输出b后,执行exit(0)系统调用终止执行。父进程输出a 后继续输出y。所以父进程输出xay而子进程输出xb。

1.编辑源程序。 2.编辑结果如下。 3.编译和运行程序。 4. 运行解释结果 语句while(p1=fork()==-1)创建了子进程和父进程。父进程执行到wait()时,等待子进程的终止信号,当子进程执行完exit(0)后,父进程才继续执行。实现了父进程等待子进程。

北大操作系统高级课程-陈向群作业-XV6进程线程

阅读代码: 1.基本头文件: types.h param.h memlayout.h defs.h x86.h asm.h mmu.h elf.h 2.进程线程部分: vm.c proc.h proc.c swtch.S kalloc.c 以及相关其他文件代码 强调一下:由于内存管理部分还没有学到,所以请同学们遇到相关的代码和问题时,先将问题记录下来,到学过之后,再结合进程线程管理部分进行深入学习,最后要求对XV6有整体的理解。 请大家围绕如下一些问题阐述原理课的相关内容,以及XV6中是如何实现的。 1.什么是进程,什么是线程?操作系统的资源分配单位和调度单位分别是什么?XV6中的 进程和线程分别是什么,都实现了吗? 答:进程是在多道程序系统出现以后,为了描述系统内部各作业的活动规律而引进的概念。进程有3个基本状态,运行状态、就绪状态和等待状态(或称阻塞状态);进程只能由父进程建立,系统中所有的进程形成一种进程树的层次体系;挂起命令可有进程自己和其他进程发出,但是解除挂起命令只能由其他进程发出。进程是具有独立功能的程序关于某个数据集合上的一次运行活动,是系统进行资源分配和调度的独立单位。 线程可称为轻量级的进程,是操作系统可以运行调度的最小单位。线程是进程内的一个相对独立的可执行的单元。若把进程称为任务的话,那么线程则是应用中的一个子任务的执行。 不论操作系统中是否引入了线程,操作系统中资源分配的基本单位都是进程。如果操作系统没有引入线程那么进程就是调度的基本单位。线程并不独立拥有资源,它仅仅分配了一些运行必备的资源。一个进程中的多个线程共同分享进程中的资源。在引入了线程的操作系统中,线程就变成了调度的基本单位,进程中的部分线程阻塞并不代表该线程被阻塞。 xv6操作系统实现了一个基于进程(没有实现线程)的简单进程管理机制。通过对proc.h 文件的阅读了解到xv6的进程中定义了一个context结构,一个枚举类型proc_state定义了UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE 这6种进程的状态,proc结构定义了进程控制块的内容,cpu结构定义了寄存器和栈指针。 2.进程管理的数据结构是什么?在Windows,Linux,XV6中分别叫什么名字?其中包含哪 些内容?操作系统是如何进行管理进程管理数据结构的?它们是如何初始化的? 答:进程管理的数据结构是进程控制块(PCB)。在Linux中进程控制块的结构是由一个叫task_struct的数据结构定义的,ask_struct存在/include/ linux/sched.h中,其中包括管理进程

任务、进程和线程的区别

任务、进程和线程的区别 推荐 摘: 任务(task)是最抽象的,是一个一般性的术语,指由软件完成的一个活动。一个任务既可以是一个进程,也可以是一个线程。简而言之,它指的是一系列共同达到某一目的的操作。例如,读取数据并将数据放入内存中。这个任务可以作为一个进程来实现,也可以作为一个线程(或作为一个中断任务)来实现。 进程(process)常常被定义为程序的执行。可以把一个进程看成是一个独立的程序,在内存中有其完备的数据空间和代码空间。一个进程所拥有的数据和变量只属于它自己。 线程(thread)则是某一进程中一路单独运行的程序。也就是说,线程存在于进程之中。一个进程由一个或多个线程构成,各线程共享相同的代码和全局数据,但各有其自己的堆栈。由于堆栈是每个线程一个,所以局部变量对每一线程来说是私有的。由于所有线程共享同样的代码和全局数据,它们比进程更紧密,比单独的进程间更趋向于相互作用,线程间的相互作用更容易些,因为它们本身就有某些供通信用的共享内存:进程的全局数据。 一个进程和一个线程最显著的区别是:线程有自己的全局数据。线程存在于进程中,因此一个进程的全局变量由所有的线程共享。由于线程共享同样的系统区域,操作系统分配给一个进程的资源对该进程的所有线程都是可用的,正如全局数据可供所有线程使用一样。 简而言之,一个程序至少有一个进程,一个进程至少有一个线程。线程的划分尺度小于进程,使得多线程程序的并发性高。另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。从逻辑角度来看,多线程的意义在于一个应用程序中,由多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配,这就是进程和线程的重要区别。 一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行。 进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。 进程概念

进程和线程的CPU亲和性

进程和线程的亲缘性(affinity)是指可以将进程或者是线程强制限制在可用的CPU子集上运行的特性,它一定程度上把进程/线程在多处理器系统上的调度策略暴露给系统程序员。 CPU的数量和表示在有n个CPU的Linux上,CPU是用0...n-1来进行一一标识的。CPU的数量可以通过proc文件系统下的CPU相关文件得到,如cpuinfo和stat: $ cat /proc/stat | grep "^cpu[0-9]\+" | wc -l 8 $ cat /proc/cpuinfo | grep "^processor" | wc -l 8 在系统编程中,可以直接调用库调用sysconf获得: sysconf(_SC_NPROCESSORS_ONLN); 进程的亲缘性Linux操作系统在2.5.8引入了调度亲缘性相关的系统调用: int sched_setaffinity(pid_t pid, unsigned int cpusetsize, cpu_set_t *mask); int sched_getaffinity(pid_t pid, unsigned int cpusetsize, cpu_set_t *mask); 其中sched_setaffinity是设定进程号为pid的进程调度亲缘性为mask,也就是说它只能在mask中指定的CPU 之间进行调度执行;sched_getaffinity当然就是得到进程号为pid的进程调度亲缘性了。如果pid为0,则操纵当前进程。 第二个参数指定mask所指空间的大小,通常为sizeof(cpu_set_t)。 第三个参数mask的类型为cpu_set_t,即CPU集合,GNU的c库(需要在include头文件之前定义 __USE_GNU)还提供了操作它们的宏: void CPU_CLR(int cpu, cpu_set_t *set); int CPU_ISSET(int cpu, cpu_set_t *set); void CPU_SET(int cpu, cpu_set_t *set); void CPU_ZERO(cpu_set_t *set); 如果我们所关心的只是CPU#0和CPU#1,想确保我们的进程只会运作在CPU#0之上,而不会运作在CPU#1之上。下面程序代码可以完成此事: cpu_set_t set; int ret, i; CPU_ZERO(&set); CPU_SET(0, &set); CPU_CLR(1, &set); ret = sched_setaffinity(0, sizeof(cpu_set_t), &set); if( ret == -1) { perror("sched_se"); } for( i=0; i < 3; i++) { int cpu; cpu = CPU_ISSET(i, &set); printf("cpu = %i is %s/n", i, cpu? "set" : "unset"); } Linux只提供了面向线程的调度亲缘性一种接口,这也是上面只提调度亲缘性而不直言进程亲缘性的原因。当前Linux系统下广泛采用的线程库NPTL(Native Posix Thread Library)是基于线程组来实现的,同一个线程组中的线程对应于一组共享存储空间的轻量级进程,它们各自作为单独调度单位被内核的调度器在系统范围内调度,这种模型也就是我们通常所说的1-1线程模型。正因如此,目前线程的调度范围

(完整版)操作系统第二章课后答案

第二章进程管理 2. 试画出下面4条语句的前趋图: S2: b:=z+1; S3: c:=a-b; S4: w:=c+1; 3. 程序在并发执行时,由于它们共享系统资源,以及为完成同一项任务而相互合作, 致使在这些并发执行的进程之间,形成了相互制约的关系,从而也就使得进程在执行期间出现间断性。 4. 程序并发执行时为什么会失去封闭性和可再现性? 因为程序并发执行时,是多个程序共享系统中的各种资源,因而这些资源的状态是 由多个程序来改变,致使程序的运行失去了封闭性。而程序一旦失去了封闭性也会导致其再失去可再现性。 5. 在操作系统中为什么要引入进程概念?它会产生什么样的影响? 为了使程序在多道程序环境下能并发执行,并能对并发执行的程序加以控制和描述,从而在操作系统中引入了进程概念。 影响: 使程序的并发执行得以实行。 6. 试从动态性,并发性和独立性上比较进程和程序? a. 动态性是进程最基本的特性,可表现为由创建而产生,由调度而执行,因得不到资源 而暂停执行,以及由撤销而消亡,因而进程由一定的生命期;而程序只是一组有序指令的集合,是静态实体。 b. 并发性是进程的重要特征,同时也是OS的重要特征。引入进程的目的正是为了使其 程序能和其它建立了进程的程序并发执行,而程序本身是不能并发执行的。 c. 独立性是指进程实体是一个能独立运行的基本单位,同时也是系统中独立获得资源和 独立调度的基本单位。而对于未建立任何进程的程序,都不能作为一个独立的单位来运行。 7. 试说明PCB的作用?为什么说PCB是进程存在的唯一标志? a. PCB是进程实体的一部分,是操作系统中最重要的记录型数据结构。PCB中记录了操 作系统所需的用于描述进程情况及控制进程运行所需的全部信息。因而它的作用是使一个在多道程序环境下不能独立运行的程序(含数据),成为一个能独立运行的基本单位,一个能和其它进程并发执行的进程。 b. 在进程的整个生命周期中,系统总是通过其PCB对进程进行控制,系统是根据进程 的PCB而不是任何别的什么而感知到该进程的存在的,所以说,PCB是进程存在的唯一标志。 8. 试说明进程在三个基本状态之间转换的典型原因. a. 处于就绪状态的进程,当进程调度程序为之分配了处理机后,该进程便由就绪状态变 为执行状态。 b. 当前进程因发生某事件而无法执行,如访问已被占用的临界资源,就会使进程由执行 状态转变为阻塞状态。 c. 当前进程因时间片用完而被暂停执行,该进程便由执行状态转变为就绪状态。 9. 为什么要引入挂起状态?该状态有哪些性质? a. 引入挂起状态主要是出于4种需要(即引起挂起的原因): 终端用户的请求,父进程 请求,负荷调节的需要,操作系统的需要。

进程和线程的选择

鱼还是熊掌:浅谈多进程多线程的选择 关于多进程和多线程,教科书上最经典的一句话是“进程是资源分配的最小单位,线程是CPU调度的最小单位”,这句话应付考试基本上够了,但如果在工作中遇到类似的选择问题,那就没有这么简单了,选的不好,会让你深受其害。 经常在网络上看到有的XDJM问“多进程好还是多线程好?”、“Linux下用多进程还是多线程?”等等期望一劳永逸的问题,我只能说:没有最好,只有更好。根据实际情况来判断,哪个更加合适就是哪个好。 我们按照多个不同的维度,来看看多线程和多进程的对比(注:因为是感性的比较,因此都是相对的,不是说一个好得不得了,另外一个差的无法忍受) 看起来比较简单,优势对比上是“线程 3.5 v 2.5 进程”,我们只管选线程就是了? 呵呵,有这么简单我就不用在这里浪费口舌了,还是那句话,没有绝对的好与坏,只有哪个更加合适的问题。我们来看实际应用中究竟如何判断更加合适。 1)需要频繁创建销毁的优先用线程 原因请看上面的对比。 这种原则最常见的应用就是Web服务器了,来一个连接建立一个线程,断了就销毁线程,要是用进程,创建和销毁的代价是很难承受的

2)需要进行大量计算的优先使用线程 所谓大量计算,当然就是要耗费很多CPU,切换频繁了,这种情况下线程是最合适的。 这种原则最常见的是图像处理、算法处理。 3)强相关的处理用线程,弱相关的处理用进程 什么叫强相关、弱相关?理论上很难定义,给个简单的例子就明白了。 一般的Server需要完成如下任务:消息收发、消息处理。“消息收发”和“消息处理”就是弱相关的任务,而“消息处理”里面可能又分为“消息解码”、“业务处理”,这两个任务相对来说相关性就要强多了。因此“消息收发”和“消息处理”可以分进程设计,“消息解码”、“业务处理”可以分线程设计。 当然这种划分方式不是一成不变的,也可以根据实际情况进行调整。 4)可能要扩展到多机分布的用进程,多核分布的用线程 原因请看上面对比。 5)都满足需求的情况下,用你最熟悉、最拿手的方式 至于“数据共享、同步”、“编程、调试”、“可靠性”这几个维度的所谓的“复杂、简单”应该怎么取舍,我只能说:没有明确的选择方法。但我可以告诉你一个选择原则:如果多进程和多线程都能够满足要求,那么选择你最熟悉、最拿手的那个。 需要提醒的是:虽然我给了这么多的选择原则,但实际应用中基本上都是“进程+线程”的结合方式,千万不要真的陷入一种非此即彼的误区。

操作系统实验报告(包括线程,进程,文件系统管理,linux+shell简单命令)

操作系统实验报告 班级:030613 学号:03061331 姓名:裴帅帅

实验一:进程的建立 一、实验内容 创建进程及子进程,在父子进程间实现进程通信,创建进程并显示标识等进 程控制块的属性信息,显示父子进程的通信信息和相应的应答信息。 使用匿名管道实现父子进程之间的通信。 二、源程序 1、创建匿名管道 SECURITY_ATTRIBUTES sa; sa.bInheritHandle=true; sa.lpSecurityDescriptor=NULL; sa.nLength=sizeof(SECURITY_ATTRIBUTES); if(!CreatePipe(&m_hRead,&m_hWrite,&sa,0)) { MessageBox("创建匿名管道失败"); return false; } 2、创建子进程 STARTUPINFO si; ZeroMemory(&si,sizeof(STARTUPINFO)); si.cb=sizeof(STARTUPINFO); si.dwFlags=STARTF_USESTDHANDLES; si.hStdInput=m_hRead; si.hStdOutput=m_hWrite; si.hStdError=GetStdHandle(STD_ERROR_HANDLE); if(!CreateProcess(NULL,"子 进.exe",NULL,NULL,true,0,NULL,NULL,&si,&pi)) { MessageBox("创建子进程失败"); CloseHandle(m_hRead); CloseHandle(m_hWrite); m_hRead=NULL; m_hWrite=NULL; return; } 3、销毁子进程 if(m_hRead) CloseHandle(m_hRead);

《操作系统》习题集:第2章 进程与线程(第1部分)

第2章进程与线程-习题集 一、选择题 1.以下关于进程的描述中,正确的是()。【*,联考】 A. 进程获得CPU运行是通过调度得到的 B. 优先级是进程调度的重要依据,一旦确定就不能改变 C. 在单CPU的系统中,任意时刻都有一个进程处于运行状态 D. 进程申请CPU得不到满足时,其状态变为阻塞 2.一个进程是()。【*,联考】 A. 由处理机执行的一个程序 B. 一个独立的程序+数据集 C. PCB结构、程序和数据的组合 D. 一个独立的程序 3.并发进程指的是()。【*,★,联考】 A. 可并行执行的进程 B. 可同一时刻执行的进程 C. 可同时执行的进程 D. 不可中断的进程 4.当一个进程处于这样的状态时,(),称为阻塞态。【*,★,联考】 A. 它正等着输入一批数据 B. 它正等着进程调度 C. 它正等着分给它一个时间片 D. 它正等进入内存 5.某个运行中的进程要申请打印机,它将变为()。【*,联考】 A. 就绪态 B. 阻塞态 C. 创建态 D. 撤销态 6.以下进程状态转变中,()转变是不可能发生的。【**,★,联考】 A. 运行→就绪 B. 运行→阻塞 C. 阻塞→运行 D. 阻塞→就绪 7.当()时,进程从执行状态转变为就绪状态。【*,联考】 A. 进程被调度程序选中 B. 时间片到 C. 等待某一事件 D. 等待的事件发生 8.一个进程的基本状态可以从其他两种基本状态转变过来,这个基本状态一定是()。【**,联考】 A. 运行状态 B. 阻塞状态 C. 就绪状态 D. 完成状态 9.当一个进程完成一个时间片后,系统需要将该进程的状态由运行状态转变为()。【*,联考】 A. 就绪状态 B. 阻塞状态 C. 撤销状态 D. 创建状态 10.进程状态由就绪态转换为运行态是由()引起的。【**,联考】 A. 中断事件 B. 进程状态转换 C. 进程调度 D. 为程序创建进程 11.下列选项中,降低进程优先级的合理时机是()。【***,10考研】 A. 进程的时间片用完 B. 进程刚完成I/O,进入就绪队列 C. 进程长期处于就绪队列中 D. 进程从就绪状态转为运行态 12.()必会引起进程切换。【**,★,联考】

进程和线程的区别

进程和线程的区别 进程和线程的概念 先了解一下操作系统的一些相关概念,大部分操作系统(如Windows、Linux)的任务调度是采用时间片轮转的抢占式调度方式,也就是说一个任务执行一小段时间后强制暂停去执行下一个任务,每个任务轮流执行。任务执行的一小段时间叫做时间片,任务正在执行时的状态叫运行状态,任务执行一段时间后强制暂停去执行下一个任务,被暂停的任务就处于就绪状态等待下一个属于它的时间片的到来。这样每个任务都能得到执行,由于CPU的执行效率非常高,时间片非常短,在各个任务之间快速地切换,给人的感觉就是多个任务在“同时进行”,这也就是我们所说的并发(并发简单来说多个任务同时执行)。 进程 计算机的核心是CPU,它承担了所有的计算任务;而操作系统是计算机的管理者,它负责任务的调度、资源的分配和管理,统领整个计算机硬件;应用程序侧是具有某种功能的程序,程序是运行于操作系统之上的。 进程是一个具有一定独立功能的程序在一个数据集上的一次动态执行的过程,是操作系统进行资源分配和调度的一个独立单位,是应用程序运行的载体。进程是一种抽象的概念,从来没有统一的标准定义。进程一般由程序、数据集合和进程控制块三部分组成。程序用于描述进程要完成的功能,是控制进程执行的指令集;数据集合是程序在执行时所需要的数据和工作区;程序控制块(Program Control Block,简称PCB),包含进程的描述信息和控制信息,是进程存在的唯一标志。 进程具有的特征: 动态性:进程是程序的一次执行过程,是临时的,有生命期的,是动态产生,动态消亡的; 并发性:任何进程都可以同其他进程一起并发执行; 独立性:进程是系统进行资源分配和调度的一个独立单位; 结构性:进程由程序、数据和进程控制块三部分组成。 进程的生命周期 ? 在早期只有进程的操作系统中,进程有五种状态,创建、就绪、运行、阻塞(等待)、退出。

进程和线程的管理

2. 进程和线程的管理 例题解析 例2.2.1 试说明进程和程序之间的区别和联系。 解进程和程序是既有区别又有联系的两个概念。 (1)进程是动态的,程序是静态的。程序是一组有序的指令集合,是一个静态的概念;进程则是程序及其数据在计算机上的一次执行,是一个动态的集合。离开了程序,进程就失去了存在的意义,但同一程序在计算机上的每次运行将构成不同的进程。程序可看作是电影的胶片,进程可以看作电影院放电影的过程。 (2)一个进程可以执行多个程序,如同一个电影院的一场电影可放映多部影片。 (3)一个程序可被多个进程执行,如同多个影院同时利用一个电影的胶片放映同一部电影。 (4)程序可以长期保存,进程只能存在于一段时间。程序是永久存在的,而进程有从被创建到消亡的生命周期。 例2.2.2 举例说明多道程序系统失去了封闭性和再现性。 解例如,有两个循环程序A和B,共享一个变量N。程序A每执行一次时,都要做N:=N+1操作;程序B则每执行一次时,都要执行print(N)操作,然后再将N的值置成“0”。程序A和B在多道程序系统中同时运行。假定某时刻变量N的值为n,可能出现下述三种情况: (1)N:=N+1 在print(N)和N:=0之前,此时得到N值变化过程为n+1、n+1、0; (2)N:=N+1 在print(N)和N:=0之后,此时得到N值变化过程为n 、0 、1; (3)N:=N+1 在print(N)之后和N:=0之前,此时得到N值变化过程为n、n+1、0。 所以,在A、B程序多次执行过程中,虽然其每次执行时的环境和初始条件都相同,但每次得到的结果却不一定相同。 例2.2.3 为什么将进程划分成执行、就绪和阻塞三个基本状态? 解根据多道程序执行的特点,进程的运行是走走停停的。因此进程的初级状态应该是执行和等待状态。处于执行状态的进程占用处理机执行程序,处于等待状态的进程正在等待处理机或者等待其它某种事件的发生。但

进程与线程的区别[试题]

进程与线程的区别[试题] 进程与线程的区别: 通俗的解释 一个系统运行着很多进程,可以比喻为一条马路上有很多马车 不同的进程可以理解为不同的马车而同一辆马车可以有很多匹马来拉----这些马就是线程 假设道路的宽度恰好可以通过一辆马车道路可以认为是临界资源 那么马车成为分配资源的最小单位(进程) 而同一个马车被很多匹马驱动(线程)----即最小的运行单位 每辆马车马匹数>=1 所以马匹数=1的时候进程和线程没有严格界限,只存在一个概念上的区分度马匹数>1的时候才可以严格区分进程和线程 专业的解释: 简而言之,一个程序至少有一个进程,一个进程至少有一个线程. 线程的划分尺度小于进程,使得多线程程序的并发性高。另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位. 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源. 一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行 进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。如果有兴趣深入的话,我建议你们看看《现代操作系统》或者《操作系统的设计与实现》。对就个问题说得比较清楚。 +++++++++++++++++++++++++++++++++++++++++++++++ 进程概念 进程是表示资源分配的基本单位,又是调度运行的基本单位。例如,用户运行自己的程序,系统就创建一个进程,并为它分配资源,包括各种表格、内存空间、磁盘空间、I,O设备等。然后,把该进程放人进程的就绪队列。进程调度程序选中它,为它分配CPU以及其它有关资源,该进程才真正运行。所以,进程是系统中的并发执行的单位。

(完整版)第二章进程管理习题和答案

--一、填空题 1. 进程是一个程序对某个数据集的一次执行过程。进程从结构上讲,包括程序、 数据和PCB 三部分。 2. 进程是一个动态的概念,程序是一个静态的概念。 3. 操作系统中,可以并行工作的基本单位是进程,它是由程序、数据集和PCB 组 成。 4. 进程存在的唯一标志是PCB 的存在。当系统创建一个进程时,系统为其建立 一个PCB ,当进程被撤销时系统就将其收回。 5. 进程有三种基本状态,即运行状态、就绪状态、阻塞状态。当进程由(1) 变换到(2)或(3)时,就会立即引起重新调度。 6. 在操作系统中,不可中断执行的操作称为原语。 7. 并发进程之间的基本关系是同步或互斥。其中互斥是指进程之间的一种间接关 系。 8?临界资源是指一段时间只允许一个进程使用的资源_,而临界区是指—进程中访问临界资源的程序代码。 9. P,V 操作原语是在信号量上操作的。 10. 信号量的物理意义是:当信号量的值大于零时,表示_ 可用资源的数量当信 号量值小于零时,其绝对值为—等待使用信号量所代表资源的进程的数量。 11. 有n 个进程共享同一个临界区,若使用信号量机制实现对临界资源的互斥访 问, 则信号量值的变化范围是1~-(n-1 )。 12. 如果系统中有n 个进程,则在等待(阻塞)队列中进程的个数最多可为个 n 。 13. 如果信号量的当前值为- 5,则表示系统中在该信号量上有 5 个等待进程。 14. 某程序运行时经常需打印中间结果。计算时,该进程处于_ 用户态,打印时处 于系统态,打印结束时进程处于用户态。(指系统状态)、

15. 在操作系统中引入线程的主要目的是—减少程序并发执行时的时空开销,使 OS 更具有并发性。 16. 如果一个程序能为多个进程同时共享执行,那么它应该以纯码形式编写,即

进程管理习题及答案

一、判断题 1.( )操作系统的所有程序都必须常驻内存。 2.( )多道程序设计可以缩短系统中作业的执行时间。 3.( )实时系统中的作业周转时间有严格的限制。 4.( )进程获得处理机而运行是通过申请而得到的。 5.( )同一个程序不能被创建成多个进程。 6.( )子进程可以继承它的父进程所拥有的所有资源。 7.( )对于临界区,最重要的是断定哪个进程先执行临界区里的那段程序。 8.( )若进程A和进程B在临界区上互斥,那么当A位于临界区内时不能打断它的 运行。 9.( )进程间的互斥是一种特殊的同步关系。 10.( )临界区是指进程中用于实现进程互斥的那段代码。 11.( )资源的同时共享是指多个用户作业可以在同一时刻使用同一资源。 12.( )并发性是指若干事件在同一时间间隔内发生。 13.( )进程在运行中,可以自行修改自己的进程控制块PCB。 14.( )进程申请CPU得不到满足时,其状态变为等待态。 15.( )当一个进程从等待态变成就绪态,则一定有一个进程从就绪态变成运行态。 16.( )进程状态的转换是由操作系统完成的,对用户是透明的。 17.( )优先数是进程调度的重要依据,优先数大的进程首先被调度运行。 18.( )不可抢占式动态优先数法一定会引起进程长时间得不到运行。 19.( )进程调度的主要功能是从所有处于等待状态的进程中挑选一个"最合适"的进 程,创建好进程运行所需要的环境,然后把处理机分配给它。 20.( )无限循环和无限延迟是一个概念。 21.( )导致系统出现死锁的一种原因是某个用户作业发生了死循环。 22.( )一旦出现死锁,所有进程都不能运行。 23.( )所有进程都挂起时系统陷入死锁。 24.( )参与死锁的进程至少有两个已经占有资源。 25. ( )有M个进程的操作系统出现死锁时,死锁进程的个数为1

线程与进程

1.进程与线程区别 从概念上: 进程:一个程序对一个数据集的动态执行过程,是分配资源的基本单位。 线程:一个进程内的基本调度单位。 线程的划分尺度小于进程,一个进程包含一个或者更多的线程。 从执行过程中来看: 进程:拥有独立的内存单元,而多个线程共享内存,从而提高了应用程序的运行效率。 线程:每一个独立的线程,都有一个程序运行的入口、顺序执行序列、和程序的出口。但是线程不能够独立的执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。 从逻辑角度来看:(重要区别) 多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但是,操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理及资源分配。 2.我们写的程序,不论是C、C++、java还是其他的,其实都是一种文本,真正 运行、跑动的是进程。 程序可以分为两部分:源代码和可执行的二进制代码(经过汇编或编译)。操作系统加载这个可执行的二进制代码后,还要分配相应的内核数据结构——进程控制块(PCB:process control block),并进行一系列的初始化等过程(如:创建PID、分配时间片等)后才创建了真正可以“跑动”的进程。所以程序相当于是一个项目的计划书(或行动方案),而进程才是对该方案的实施过程。 进程对CPU来说其实就是一串可执行的指令序列,这个执行序列也叫执行线程,它是进程的控制流程。传统的用户进程只有一个执行流程,所以传统的进程都是单线程的。有了线程就是执行流程的概念后,进程模型得到了扩展,因为一个进程中完全可以设置多个执行流程,即多个执行线程。所以一个进程中可以创建多个线程,当然不创建的话,进程本身也可以看成是线程。 创建多个进程的话,每个进程都是独立的(都有自己独立的PCB数据结构,该数据结构比较大,将近1K的信息量,包括唯一的PID、上下文环境、持有的内存地址等等),内核要管理进程间的切换、内存管理等,开销相对比较大。 如果一个进程里创建多个线程的话,开销比进程要小,各线程共享进程的状态和资源,内核为线程创建的数据结构相对比进程的PCB就要小的多,当然额外的开销是CPU需要跟踪线程,同时线程间存在争用资源的问题。如果程序要完成一组相关任务,则用线程比较好。 下面再细讲下进程:

进程线程的空间问题

进程与线程的空间问题 这两天有同学问到进程线程的地址空间的问题,提到在linux下每个进程单独占有4G的虚拟地址空间,而这个进程下的所有线程共享着它的地址空间。这只是一个概念上的理解,具体是怎么回事呢? 在说这个问题之前我们先说一下早期的内存管理机制。在早期的计算机中,程序都是直接运行在内存上的,也就是说程序中访问的内存地址都是实际的物理内存地址。当计算机同时运行多个程序时,必须保证这些程序用到的内存总量要小于计算机实际物理内存的大小。那当程序同时运行多个程序时,操作系统顺次向下分配物理内存地址例如一台计算机的内存大小是128M,现在同时运行程序A和B,A需占用内存30M,B需占用内存60M。计算机在给程序分配内存时先将内存中的前30M分配给程序A,接着再从内存中剩余的98M中划分出60M分配给程序B。这种分配方法可以保证程序A和程序B都能运行,但是这种简单的内存分配策略问题很多。首先进程地址空间不隔离。由于程序都是直接访问物理内存,恶意程序可以很容统修改别的进程的内存数据,以达到破坏的目的。即使是非恶意的,但是有bug的程序也可能不小心修改了其它程序的内存数据,就会导致其它程序的运行出现异常。其中一个任务失败了,可能也会影响其它的任务。其次是程序运行的地址不确定。当内存中的剩余空间可以满足程序C的要求后,操作系统会在剩余空间中随机分配一段连续的20M大小的空间给程序C使用,因为是随机分配的,所以程序运行的地址是不确定的。

内存使用效率低。在A和B都运行的情况下,如果用户又运行了程序C,而程序C需要20M大小的内存才能运行,而此时系统只剩下8M的空间可供使用,所以此时系统必须在已运行的程序中选择一个将该程序的数据暂时拷贝到硬盘上,释放出部分空间来供程序C使用,然后再将程序C的数据全部装入内存中运行。可以想象得到,在这个过程中,有大量的数据在装入装出,导致效率十分低下。 为了解决上述问题,人们设计了间接的地址访问方法访问物理内存。按照这种方法,程序中访问的内存地址不再是实际的物理内存地址,而是一个虚拟地址,然后由操作系统将这个虚拟地址映射到适当的物理内存地址上。这样,只要操作系统处理好虚拟地址到物理内存地址的映射,就可以保证不同的程序最终访问的内存地址位于不同的区域,彼此没有重叠,就可以达到内存地址空间隔离的效果。 当创建一个进程时,操作系统会为该进程分配一个4GB大小的虚拟进程地址空间。之所以是4GB,是因为在32位的操作系统中,一个指针长度是4字节(64位系统是8字节,由cpu的寻址位数决定),而4字节指针的寻址能力是从0x00000000~0xFFFFFFFF,最大值0xFFFFFFFF表示的即为4GB大小的容量。与虚拟地址空间相对的,还有一个物理地址空间,这个地址空间对应的是真实的物理内存。如果你的计算机上安装了1G大小的内存,那么这个物理地址空间表示的范围是0x00000000~0x3FFFFFFF。当操作系统做虚拟地址到物理地址映射时,只能映射到这一范围。当进程创建时,每个进程都会有一个自己的4GB虚拟地址空间。要注意的是这个4GB的地址空间是“虚

相关主题
文本预览
相关文档 最新文档