网站首页 | 工作总结 | 工作报告 | 工作计划 | 演讲稿 | 自我鉴定 | 思想汇报 | 心得体会 | 书信范文 | 职场知识 | 作文大全 | 述职报告 | 读后感
一起看范文网
您的位置:一起看范文网进程线程的概念进程线程 → 正文

进程线程

第一篇:进程线程

1. 阐述作业、程序、进程的关系。

一个作业是由若干个程序(例:编释程序、装配程序、运行程序等)的相继执行来完成。

每个程序执行时又能创建多个进程来相互合作。

2、什么是线程?多线程技术具有哪些优越性? 线程是进程中可独立执行的子任务,一个进程可以有一个或多个线程,每个线程都有一个惟一的标识符。

线程与进程有许多相似之处,往往把线程又称为"轻型进程",线程与进程的根本区别是把进程作为资源分 配单位,而线程是调度和执行单位。

多线程技术具有多个方面的优越性:① 创建速度快、系统开销小:创建线程不需要另行分配资源;② 通 信简洁、信息传送速度快:线程间的通信在统一地址空间进程,不需要额外的通信机制;③ 并行性高:线 程能独立执行,能充分利用和发挥处理器与外围设备并行工作的能力。

3.在创建一个进程时,所要完成的工作有哪些? ⑴申请空白 PCB。为新进程分配唯一的数字标识符,并从 PCB 集合中索取一 空白 PCB; ⑵为新进程分配资源。包括必要的内存,进程需要的其它资源; ⑶初始化进程控制块。包括初始化标识符信息,处理机状态信息,处理机控制信 息等; ⑷将新进程插入就绪队列 4.在高级通信机制中,进程有哪几种通信方式? ⑴共享存储器系统。相互通信的进程之间共享某些数据结构或共享存储区; ⑵消息传递系统。进程之间的数据交换以消息为单位,进行直接的或间接的通信; ⑶管道通信。管道体现为一个文件,发送信息的进程以字符流形式将数据送入管 道,接收进程可以从管道中读取数据。

5.试述创建进程原语的主要功能。

答:创建进程原语的主要功能有以下三项。

(1)为新建进程申请一个 PCB。

(2)将创建者(即父进程)提供的新建进程的信息填入 PCB 中。

(3)将新建进程设置为就绪状态,并按照所采用的调度算法,把 PCB 排入就绪队列中。

6.多线程技术具有哪些优越性? 答:多线程技术具有多个方面的优越性

① 创建速度快、系统开销小:创建线程不需要另行分配资源; ② 通信简洁、信息传送速度快:线程间的通信在统一地址空间进程,不需要额外的通信机制; ③ 并行性高:线程能独立执行,能充分利用和发挥处理器与外围设备并行工作的能力。

6.处于阻塞状态的一个进程,它所等待的事件发生时,就把它的状态由阻塞改变为就绪,让它到就绪队 列里排队,为什么不直接将它投入运行呢? 答:只要是涉及管理,就应该有管理的规则,没有规则就不成方圆。如果处于阻塞状态的一个进程,在它 所等待的事件发生时就径直将它投入运行(也就是把 CPU 从当前运行进程的手中抢夺过来) ,那么系统就无 法控制对 CPU 这种资源的管理和使用,进而也就失去了设置操作系统的作用。所以,阻塞状态的进程在它 所等待的事件发生时,必须先进入就绪队列,然后再去考虑它使用 CPU 的问题。

7.系统中的各种进程队列都是由进程的 PCB 链接而成的。当一个进程的状态从阻塞变为就绪状态时,它 的 PCB 从哪个队列移到哪个队列?它所对应的程序也要跟着移来移去吗?为什么? 答:当一个进程的状态从阻塞变为就绪时,它的 PCB 就从原先在的阻塞队列移到就绪队列里。在把进 程的 PCB 从这个队列移到另一个队列时,只是移动进程的 PCB,进程所对应的程序是不动的。这是因 为在进程的 PCB 里,总是记录有它的程序的断点信息。知道了断点的信息,就能够知道程序当前应该 从哪里开始往下执行了。这正是保护现场所起的作用。

第一篇:进程线程

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 <stdio.h> #include <pthread.h> #define RUN_TIME 10 void * thread(void * arg) { int i; for(i=0;i<RUN_TIME;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 <pthread.h> #include <sched.h> 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, &param); param.sched_priority=newprio; //设置优先级 pthread_attr_setschedparam(&attr, &param); pthread_create(&tid, &attr, (void *)myfunction, myarg); for(i=0;i<RUN_TIME;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 的线程调用. – 包含头文件 <process.h> – 表示线程数据结构 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 <process.h> #include <stdio.h> #include <stdlib.h> #include <windows.h> 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 );

第一篇:进程线程

提起程序这个概念,大家再也熟悉不过了,程序与进程概念是不可分的。程序是为了 完成某项任务编排的语句序列,它告诉计算机如何执行,因此程序是需要运行的。程序运 行过程中需要占有计算机的各种资源才能运行下去。如果任一时刻,系统中只有一道程序, 即单道程序系统,程序则在整个运行过程中独占计算机全部资源,整个程序运行的过程就 非常简单了,管理起来也非常容易。就象整个一套房子住了一个人,他想看电视就看电视, 想去卫生间就去卫生间,没人和他抢占资源。但为了提高资源利用率和系统处理能力,现 代计算机系统都是多道程序系统,即多道程序并发执行。程序的并发执行带来了一些新的 问题,如资源的共享与竞争,它会改变程序的执行速度。就象多个人同时住一套房子,当 你想去卫生间的时候,如果此时卫生间里有人,你就得等待,影响了你的生活节奏。如果 程序执行速度不当,就会导致程序的执行结果失去封闭性和可再现性,这是我们不希望看 到的。因此应该采取措施来制约、控制各并发程序段的执行速度。由于程序是静态的,我 们看到的程序是存储在存储介质上的,它无法反映出程序执行过程中的动态特性,而且程 序在执行过程中是不断申请资源,程序作为共享资源的基本单位是不合适的,所以需要引 入一个概念,它能描述程序的执行过程而且可以作为共享资源的基本单位,这个概念就是 进程。

进程的生命周期 进程和人一样是有生命的,从诞生到死亡要经历若干个阶段。一般说来进程有三种状 态:就绪、执行、等待。由多种原因可以导致创建一个进程,例如一个程序从外存调入内 存开始执行,操作系统就要为其创建进程,当然还可以有其它原因,如一个应用进程为完 成一个特殊的任务,可以自己创建一个子进程。进程被创建后就是在内存中,处于就绪状 态,所谓就绪状态就是具备除了 CPU 之外的所有资源,万事具备,只欠东风,一旦占有 了 CPU,就变成了执行状态,执行中如果需要等待外围设备输入数据,则进程就沦落为 等待状态,操作系统又会从就绪状态队列中调度一个进程占有 CPU。等到数据到来后, 等待状态的进程又被唤醒成为就绪状态。这些状态的转换是通过进程控制原语实现的。程 序的运行是通过进程体现的,操作系统对进程进行管理和控制,那么操作系统怎么了解到 进程的状态呢,怎么把资源分配给进程呢,而且进程做状态转换时 CPU 现场保存在那呢? 这要说到 PCB(进程控制快)。PCB 是进程的唯一标志,在其中记录了进程的全部信息, 它是一种记录型的数据结构,相当于进程的档案。操作系统就通过 PCB 感知进程的存在, 通过 PCB 了解进程和控制进程的运行。PCB 也是放在内存中的,如果 PCB 太大,有些系 统把 PCB 中一些不重要的信息放在外存中。

进程执行速度的制约 并发进程由于共享系统内部资源,因此导致进程执行速度上的制约,这种制约分为

间接制约与直接制约。间接制约引起进程之间的互斥执行,直接制约引起进程间的同步执 行。例如一个家里如果只有一个卫生间,卫生间这个公有资源使得每个人只能互斥使用它, 这就是间接制约。而直接制约是指并发进程各自执行的结果互为对方的执行条件,例如司 机与售票员的关系,当司机到站停车后,售票员才能开门,而只有售票员关门后,司机才 能开车,他们之间是同步的。进程的互斥与同步可以很好的通过信号量和 PV 原语来实现。

通过读一些同步与互斥的例子,你会体会到 PV 原语的精妙,也会感到一种乐趣。并发进 程的资源竞争不当还会导致死锁现象。

从单进程单线程到多进程多线程是操作系统发展的一种必然趋势,当年的 DOS 系统 属于单任务操作系统,最优秀的程序员也只能通过驻留内存的方式实现所谓的"多任务", 而如今的 Win32 操作系统却可以一边听音乐,一边编程,一边打印文档。

理解多线程及其同步、互斥等通信方式是理解现代操作系统的关键一环,当我们精通 了 Win32 多线程程序设计后,理解和学习其它操作系统的多任务控制也非常容易。许多 程序员从来没有学习过嵌入式系统领域著名的操作系统 VxWorks,但是立马就能在上面 做开发,大概要归功于平时在 Win32 多线程上下的功夫。

因此,学习 Win32 多线程不仅对理解 Win32 本身有重要意义,而且对学习和领会其 它操作系统也有触类旁通的作用。

进程与线程 先阐述一下进程和线程的概念和区别,这是一个许多大学老师也讲不清楚的问题。

进程(Process)是具有一定独立功能的程序关于某个数据集合上的一次运行活动, 是系统进行资源分配和调度的一个独立单位。程序只是一组指令的有序集合,它本身没有 任何运行的含义,只是一个静态实体。而进程则不同,它是程序在某个数据集上的执行, 是一个动态实体。它因创建而产生,因调度而运行,因等待资源或事件而被处于等待状态, 因完成任务而被撤消,反映了一个程序在一定的数据集上运行的全部动态过程。

线程(Thread)是进程的一个实体,是 CPU 调度和分派的基本单位。线程不能够独 立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

线程和进程的关系是:线程是属于进程的,线程运行在进程空间内,同一进程所产生 的线程共享同一内存空间,当进程退出时该进程所产生的线程都会被强制退出并清除。线 程可与属于同一进程的其它线程共享进程所拥有的全部资源,但是其本身基本上不拥有系 统资源,只拥有一点在运行中必不可少的信息(如程序计数器、一组寄存器和栈)。

根据进程与线程的设置,操作系统大致分为如下类型

(1)单进程、单线程,MS-DOS 大致是这种操作系统; (2)多进程、单线程,多数 UNIX(及类 UNIX 的 LINUX)是这种操作系统; (3)多进程、多线程,Win32(Windows NT/2000/XP 等)、Solaris 2.x 和 OS/2 都是 这种操作系统; (4)单进程、多线程,VxWorks 是这种操作系统。

在操作系统中引入线程带来的主要好处是

(1)在进程内创建、终止线程比创建、终止进程要快; (2)同一进程内的线程间切换比进程间的切换要快,尤其是用户级线程间的切换。

另外,线程的出现还因为以下几个原因

(1)并发程序的并发执行,在多处理环境下更为有效。一个并发程序可以建立一个 进程,而这个并发程序中的若干并发程序段就可以分别建立若干线程,使这些线程在不同的 处理机上执行。

(2)每个进程具有独立的地址空间,而该进程内的所有线程共享该地址空间。这样 可以解决父子进程模型中,子进程必须复制父进程地址空间的问题。

(3)线程对解决客户/服务器模型非常有效。 进程是计算机进行资源分配和独立运行的基本单位。

3.1 进程的引入 引入进程是为了使多道程序并发执行。

1.程序的顺序执行 一个程序通常由若干个程序段所组成,它们必须按照某种先后次序来执行,仅当前一个操作执行 完后才能执行后继操作,这类计算过程就是程序的顺序执行过程。

例如:先输入→再计算→最后输出,即:I→C →P。

程序顺序执行时的特征 顺序性:处理机的操作严格按照程序所规定的顺序执行,即每一个操作必须在下一个操作开始之 前结束。

封闭性:程序一旦开始运行,其执行结果不受外界因素影响。

可再现性:只要程序执行时的初始条件和执行环境相同,当程序重复执行时,都将获得相同的结 果。

2.程序的并发执行 程序的并发执行是指若干个程序(或程序段)同时在系统中运行,这些程序(或程序段)的执行在时间 上是重叠的,一个程序(或程序段)的执行尚未结束,另一个程序(或程序段)的执行已经开始。

前驱图 前驱图是一个有向无循环图,图中的每个结点可以表示一条语句、一个程序段或进程,结点间的 有向边表示语句或程序段的执行次序。

程序并发执行例 进程 1、2、3 并发执行。对每个进程而言,其输入、计算和输出这三个操作必须顺序执行。它们 之间存在如下先后关系

I1 先于 C1 和 I2 , C1 先于 P1 和 C2 , P1 先于 P2 I2 和 C1 , I3、 C2 和 P1 可以并发。

与时间有关的错误例 程序并发执行时可能出现与时间有关的错误。

例 进程 1:r1=x; 进程 2:r2=x; r1++; r2++; x=r1; x=r2; 设在两进程运行之前,x 的值为 0。则两进程运行结束后,x 值可为

Bernstein 条件 读集:语句执行期间要引用的变量集合,记为 R(Si)={a1,…,am} 写集:语句执行期间要改变的变量集合,记为 W(Si)={b1,…,bn} Bernstein 条件能保证两条相继的语句并发执行而不会产生与时间有关的错误

R(Si)∩ W(Sj)={ } R(Sj)∩ W(Si)={ } W(Si)∩ W(Sj)={ } 例 考虑下面是条语句: S1:a=x+y S2:b=z+1 S3:c=a-b S4:d=c+1 R(S1)={x,y} R(S2)={z} R(S3)={a,b} W(S1)={a} W(S2)={b} W(S3)={c} 因 R(S1)∩ W(S2)∪R(S2)∩ W(S1)∪W(S1)∩W(S2)={ },故 S1 和 S2 可以并发执行 。

因 R(S2)∩ W(S3)∪R(S3)∩ W(S2)∪W(S3)∩W(S2)={b},故 S2 和 S3 不能并发执行 。

并发语句的描述方式 cobegin S1;S2;…Sn; coend 对应的前驱图如右,其中 S0 和 Sn+1 分别是 cobegin 和 coend 语句前后的两条语句。

程序并发执行时的特征 间断性:并发程序具有“执行---暂停----执行”这种间断性的活动规律。

失去封闭性:多个程序共享系统中的资源,这些资源的状态将由多个程序来改变,致使程序之间 相互影响。

不可再现性:在初始条件相同的情况下,程序的执行结果依赖于执行的次序。

并发程序的其他特征 资源分配动态性:多道程序在运行过程中可根据需要随时提出分配资源的请求。

程序并发执行的相互制约:并发程序执行时相互影响,相互制约。其相互制约关系分为

直接制约:合作进程之间的相互制约。

间接制约:因资源共享产生的相互制约。

相互通信的可能:多个进程之间可能需要相互传递信息。

同步与互斥的必要:并发进程之间需要调整相对执行速度,许多资源需要互斥使用。

3.2 进程的概念 为了描述并发执行程序的动态特性,人们引入了一个新的概念——进程。 1. 进程的定义 进程有多种定义,下面列举一些有代表性的定义

进程是可以并发执行的计算部分。

进程是一个程序与其数据一道通过处理机的执行所发生的活动。

进程是一个数据结构及在其上进行加工处理的过程。

进程是一个可以高度独立的活动。

进程是一个具有一定独立功能的程序在一个数据集合上的运行过程,它是系统进行资源分配和调 度的一个独立单位。

进程的特征 动态性:进程是程序的一次执行过程。动态性还表现为它因创建而产生,因调度而执行,因无资 源而暂停,因撤消而消亡。而程序是静态实体。

并发性:多个进程实体同时存在于内存中,能在一段时间内同时运行。

独立性:在传统 OS 中,进程是独立运行的基本单位,也是系统分配资源和调度的基本单位。

异步性:也叫制约性,进程之间相互制约,进程以各自独立的不可预知的速度向前推进。

结构性:进程实体由程序段、数据段及进程控制块组成,又称为进程映像。

进程与程序的联系与区别 进程是动态概念,程序是静态概念;进程是程序在处理机上的一次执行过程,而程序是指令的集合。

进程具有并发性,但程序没有。

进程是竞争处理机和资源的基本单位。

不同进程可以包含同一个程序。

进程可以创建新进程,而程序不能形成新程序。

2. 进程的基本状态 运行状态:又称执行状态。当一个进程获得必要的资源并正在处理机上执行,此时进程所处的状 态为运行状态。

等待状态:又称阻塞状态、睡眠状态。正在执行的进程,由于发生某事件而暂时无法执行下去(如 等待输入/输出完成),此时进程所处的状态为的等待状态。这时即使把处理机分配给该进程,它也无 法运行。

就绪状态:进程已获得除处理机以外的所有资源,一旦分配了处理机就可以立即执行,此时进程 所处的状态为就绪状态。

新建状态和终止状态 在许多系统中又增加了两种状态

新建状态:进程刚刚建立,但还未进入就绪队列。

终止状态:当一个进程正常或异常结束,操作系统已释放它所占用的资源,但尚未将它撤消时的 状态,又称退出状态。

进程状态转换图 状态转换的有关说明 大多数状态不可逆转,如等待不能转换为运行。

状态转换大多为被动进行,但运行→等待是主动的。

一个进程在一个时刻只能处于上述状态之一。

3. 进程控制块 进程控制块是用于描述和管理进程的数据结构。它是进程实体的一部分,操作系统通过 PCB 感知 进程的存在,PCB 是进程存在的唯一标志。

进程控制块主要包括如下内容

进程标识信息 处理机状态信息 进程调度和状态信息 进程控制信息 进程标识信息 进程标识信息用于标识一个进程。包括

进程名:通常为可执行文件名。

进程标识符:唯一标识进程的整数. 用户标识符:指示进程所属的用户。 父进程标识符和子进程标识符:描述进程家族关系。

处理机状态信息 处理机状态信息用于保存现场,由处理机各寄存器组成。包括

通用寄存器:处理机执行时可以访问的寄存器。

指令计数器:存放将要访问的下一条指令地址。

程序状态字:含执行结果状态、中断屏蔽码等。

栈指针:每进程有多个与之相关的栈,用于保存调用参数。

进程调度和状态信息 进程调度和状态信息用于存放与进程调度及对换有关的信息。包括

进程状态:指明进程当前状态。

进程优先级:描述进程使用处理机的优先级别。

进程调度的其他信息:取决于进程调度算法,如等待时间。

等待事件:进程处于等待状态的原因。

进程控制信息 进程控制信息:包括

程序和数据地址:指出进程的程序及数据在内存的地址。

进程同步及通讯机制:如信号量、消息队列等。

资源清单:记录进程所需的资源和已分配资源。

链接指针:处于同一状态的进程组成一个队列,链接指针指向队首。

进程特权:确定进程可以访问的内存空间及可以执行的指令类型。

3.3 进程控制 进程控制的职能是对系统中的所有进程实施有效的管理。

常见的进程控制功能有进程创建、撤消、阻塞与唤醒等。这些功能一般由操作系统内核来实现。

1.进程控制的有关概念 为了保护操作系统,将处理机的状态分为

用户态:是用户程序执行时机器所处的状态。

核心态:是操作系统内核运行时机器所处的状态。

原语是由若干条机器指令构成的,用以完成特定功能的一段程序,这段程序在执行期间不可分割。

进程图 进程图又称进程树或进程家族树,是描述进程家族关系的一棵有向树。图中的结点表示进程,若 进程 A 创建了进程 B,则从结点 A 有一条边指向结点 B,说明进程 A 是进程 B 的父进程,进程 B 是进 程 A 的子进程。

进程图例 2. 进程创建 导致进程创建的原因有

用户登录:用户登录后,若合法则为用户创建一个进程。

作业调度:为调度到的作业分配资源并创建进程。

OS 服务:创建服务进程。

应用需要:应用程序根据需要创建子进程。

进程创建的方法 引导程序以特殊方式创建系统进程。如 UNIX 系统中的 0 进程。

由作业调度程序创建进程。

由父进程创建子进程。

创建原语的主要功能 进程创建原语的主要功能是为被创建进程建立一个 PCB。其算法思想如下

在 PCB 总链中查找同名进程,若有则出错返回; 向系统申请一个空闲 PCB 结构,若没有则出错返回; 初始化新进程的 PCB:填写进程名、标识符、状态、程序地址等; 将进程 PCB 插入相应队列:插入就绪队列及 PCB 总链。 3. 进程终止 引起进程终止的原因有

正常结束 异常结束:超时、内存不足、地址越界、算术错、I/O 故障、非法指令等。

操作员或系统干预:因某种原因需要操作员或系统终止进程。

父进程请求:请求终止子进程。

终止原语的主要功能 进程终止原语的主要功能是撤消一个进程。其算法思想如下

从 PCB 总链中查找到被终止进程的 PCB,若无则出错返回; 若被终止进程正处于运行状态,则立即停止该进程的执行,设置重新调度标志; 若被终止进程有子孙进程,还应将该进程的子孙进程予以撤消; 对于被终止进程所占有的资源,或者归还给父进程,或者归还给系统; 最后撤消它的进程控制块。若需要转调度程序。

4. 进程阻塞 引起进程阻塞的原因有

请求系统服务:如请求分配资源但尚无资源分配。

新数据尚未到达:如合作进程之间。

无新工作可做:进程已完成了给定任务,新任务未到。

阻塞原语的主要功能 阻塞原语的主要功能是将进程由执行状态转为阻塞状态。其算法思想如下

停止当前执行进程,将进程状态改为阻塞; 保存该进程的现场信息; 将该进程 PCB 插入到等待队列; 转进程调度程序。 5. 进程唤醒 当进程等待的事件发生时,由发现者进程将其唤醒。

唤醒原语的主要功能是将进程唤醒,其算法思想如下

从等待队列中移出相应进程; 将该进程状态改为就绪,并将进程插入就绪队列; 转进程调度或返回。

阻塞与唤醒的关系 一个进程由执行状态转变为阻塞状态,是这个进程自己调用阻塞原语去完成的。

进程由阻塞状态转变为就绪状态,是另一个发现者进程调用唤醒原语实现的。

一般发现者进程与被唤醒进程是合作的并发进程。

6. 进程的挂起 在某些系统中,希望人为将进程挂起使之处于静止状态。

进程挂起的原因有

内存不足:在外存挂起。

用户要求:可以挂起进程以腾出资源。

进程特性:周期性执行,等待下一次执行时可能挂起。

父进程请求:父进程希望挂起子进程检查。

操作系统要求:挂起一个问题进程。

挂起状态 基于上述原因,需引入一个新的状态:挂起状态。

挂起原语的主要功能 挂起原语的主要功能是将指定进程挂起。其算法思想如下

若进程执行则停止其执行; 设置进程状态为挂起状态; 若进程当前为执行则转进程调度。

进程激活 激活原语的主要功能是将指定进程激活。其算法思想如下

将进程状态由挂起改为激活后的状态; 若需要则转进程调度 。

3.4 线程 在操作系统中引入进程的目的是使多道程序能并发执行,以改善资源利用率及提高系统吞吐量; 在操作系统中再引入线程,则是为了减少程序并发执行所付出的时空开销,使操作系统具有更好 的并发性。

1. 线程的引入 进程具有两个属性

拥有资源的独立单位 调度和分派的基本单位 为使进程并发执行,则必须进行诸如创建、撤消、切换等一系列操作,这些操作涉及到资源管理, 所花费的时空开销较大,为此引入了线程。

线程概念 线程是进程内的一个执行单元,是系统独立调度和分派的基本单位; 线程自己基本上不拥有资源,只拥有一点在运行时必不可少的资源(如程序计数器、一组寄存器和 栈); 线程可以与同属一个进程的其他线程共享进程拥有的全部资源。

2.线程的控制 和进程类似,线程也有运行、就绪、阻塞等状态。

创建:当创建一个新进程时,也为该进程创建了一个线程。线程还可以创建新线程。

就绪:线程已获得除处理机外的所有资源。

运行:线程正在处理机上执行。 阻塞:线程因等待某事件而暂停运行。

终止:一个线程已完成。

线程的同步与通信与进程类似。进程的挂起及终止将影响到其中的所有线程。

2.线程的控制(续) 进程中的线程具有 执行状态 线程上下文 执行栈 线程静态存储局部变量 寄存器及对所属进程资源的访问 3.线程与进程的比较 一个进程中的所有线程共享该进程的状态和资源,它们驻留在同一地址空间,并且可以访问到相 同的数据。

线程与进程的区别 调度分派:在传统 OS 中,进程是调度和分配资源的基本单位;引入线程后,线程是调度和分派的 基本单位,进程是拥有资源的基本单位。

资源拥有:进程是拥有资源的基本单位,由一个或多个线程及相关资源构成。

地址空间:不同进程地址空间独立,同一进程中的各线程共享同一地址空间。

一个进程可以包含一个或多个线程。

进程间通信必须使用 OS 提供的进程间通信机制,而同一进程的线程间可以通过直接读写来通信。

线程的优点 创建时间:在已有进程中创建一个新线程比创建一个新进程快。

终止时间:终止一个线程比终止一个进程快。

切换时间:同一进程中线程的切换比进程间切换快。

通信效率:同一进程中线程的通信快。 4.用户级线程和内核级线程 线程的类型

内核级线程:是指依赖于内核,由操作系统内核完成创建、撤消和切换的线程。

用户级线程:是指不依赖于操作系统核心,由应用进程利用线程库提供创建、同步、调度和管理 线程的函数来控制的线程。

线程的调度与切换速度:内核级线程的调度与切换与进程类似,但开销小些;用户级线程切换无需 进入内核,因而切换快。

4.用户级线程和内核级线程(续) 系统调用:内核级线程调用系统调用时,OS 将其看成是该线程的行为,因而阻塞该线程;而用户 级线程调用系统调用时,OS 将其看成整个进程的行为,若阻塞则阻塞整个进程。

线程执行时间:在只有用户级线程的系统中,调度以进程为单位,若进程内线程多则执行时间相 对少;内核级线程系统中,调度以线程为单位。

适应性:用户级线程可以在任何操作系统中运行,但内核级线程只能在支持它的 OS 中运行。

UNIX 的进程描述(P245) 在 UNIX 系统中,采用了段页式存储管理方式(在 UNIX 中将段称为区),因此一个进程实体由若干 个区组成,包括程序区、数据区、栈区等。每个区又可分为若干页。

进程描述的数据结构 为了实施对进程的有效管理,操作系统为每个进程设置了一个 PCB。在 UNIX System Ⅴ中,将 PCB 分成进程表项和 U 区(又称 proc 结构和 user 结构)两部分。除进程表项和 U 区外,管理进程的数据结构 还有本进程区表和系统区表。

进程表项 状态字段用于标识进程的状态。

若干用户标识号,简称 UID 或用户 ID。

若干进程标识号,简称 PID 或进程 ID。

存储区位置和长度。

调度参数,包括优先数等。

软中断信号域。 各种计时域,给出进程执行时间和系统资源的利用情况。

指向 U 区的指针,指向与进程表项对应的 U 区。

事件描述域,记录使进程进入睡眠状态的事件。

U区 指向进程表项的指针,指出对应于该 U 区的进程表项。

真正用户标识符及有效用户标识符。

用户文件描述符表,记录进程已打开的文件。

当前目录和当前根,描述进程的文件系统环境。

计时器域,记录进程及其后代运行所用的时间。

一些输入/输出参数。描述要传输的数据量,源或目的数据地址等。

限制域,指出进程的大小及它能“写”的文件大小限制。

出错域,记录系统调用执行期间所发生的错误。

返回值域,指出系统调用的返回结果。

信号处理数组,指出进程接收到软中断信号时的处理方式。

系统区表 UNIX System Ⅴ把一个进程的虚地址空间划分为正文区、数据区、栈区等。系统设置区表对区进行 管理,区表主要包含以下信息

区的类型和大小。指明区的类型为正文、数据或栈。

区的状态。一个区具有状态:锁住、在请求中、在装入过程中、有效(区已装入内存)。

区在物理存储器中的位置。

引用计数。共享该区的进程数。

指向文件索引节点的指针。

本进程区表 系统为每个进程配置了一张本进程区表,表中每一项记录一个区的起始虚地址及指向系统区表中 对应区表项的指针。核心通过查找本进程区表和系统区表,将区的逻辑地址变换为物理地址。 进程的数据结构 进程状态及其转换 在 UNIX System Ⅴ中,为进程设置了 9 种状态。

用户态执行 核心态执行 内存中就绪 内存中睡眠 就绪且换出 睡眠且换出 被剥夺状态 创建状态 僵死状态 UNIX 系统的状态转换图 进程上下文 进程上下文又称进程映像,它由三部分组成:用户级上下文、寄存器上下文和系统级上下文。

用户级上下文 用户级上下文由进程虚地址空间中的正文、数据、用户栈和共享存储区组成。

寄存器上下文 寄存器上下文主要由 CPU 中的一些寄存器内容构成。主要的寄存器有

程序计数器。其中存放的是 CPU 要执行的下条指令的虚地址。

处理机状态寄存器。其中包括运行方式(用户态、核心态),处理机当前的运行级,以及记录处理 机与该进程有关的硬件状态信息。

栈指针。指向栈的下一个可用单元或栈中最后使用的单元(因机器而异)。

通用寄存器。用于存放进程在运行过程中所产生的数据,通用寄存器的数目因机器而异。

系统级上下文 系统级上下文可分为静态和动态两部分

静态部分:系统级上下文的静态部分由进程表项、U 区、本进程区表项、系统区表项和页表组成。

动态部分:系统级上下文动态部分的数目是可变的。它包括:核心栈、若干层寄存器上下文。

进程控制 在 UNIX 系统中,用于对进程实施控制的主要系统调用有:fork,创建进程;exec,执行文件;exit, 进程终止;wait,等待子进程终止。

系统调用 fork 系统调用 fork 用于创建一个新进程。

fork 系统调用的语法格式如下

int fork( ) fork 系统调用没有参数,如果执行成功,则创建一个子进程,子进程继承父进程的许多特性,并 具有与父进程完全相同的用户级上下文。

fork 的算法描述 算法 fork,无输入参数,父进程返回子进程 PID,子进程返回 0 { 检查可用的内核资源; 取一个空闲的进程表项和惟一的 PID 号; 检查用户没有过多运行进程; 将子进程的状态设置为“创建”状态; 将父进程进程表项的数据拷贝到子进程进程表项中; 当前目录和根目录的索引节点引用计数加 1; 文件表中打开文件的引用计数加 1; 在内存中作父进程上下文的拷贝; fork 的算法描述(续) 在子进程的系统级上下文中压入虚设系统级上下文层; if (正在执行的进程是父进程) { 将子进程的状态设置为“就绪”状态; return(子进程的 PID); } else { 初始化 U 区的计时域; return(0); }} 系统调用 exec exec 系列中的系统调用都完成同样的功能,它们把一个新的程序装入调用进程的内存空间,以改 变调用进程的执行代码,从而使调用进程执行新引入的程序功能。 这一组系统调用的主要差别在于给出参数的数目和形式不同。下面给出两种基本的 exec 调用格式 说明: int execl(path , arg0 [,arg1,…,argn],0); char *path,*arg0,*arg1, …,*argn ; int execv(path,argv); char *path,*argv[ ]; exec 算法描述 算法 exec,输入参数有文件名、参数表、环境变量,无输出。 { 取文件的索引节点(算法 namei); 验证文件可被执行,用户有执行许可权; 读文件头,检查它是否为装入模块; 将 exec 参数从老地址空间拷贝到系统空间; for (与该进程附接的每个区) 使区与进程断接(算法 detachreg); for (装入模块中指定的每个区); { 分配新区(算法 alloreg); exec 算法描述(续) 将新区附接到进程(算法 attachreg);
进程线程》由(一起看范文网)整理提供,版权归原作者、原出处所有。
Copyright © 一起看范文网 All Rights Reserved.