zoukankan      html  css  js  c++  java
  • 【操作系统】进程

      进程的经典定义是一个执行中的程序的实例。注意,一个程序运行了两遍,则算作两个进程。操作系统能够使他们共享代码,因此只有一个副本放在内存中。

      在传统的操作系统中,每个进程都有一个地址空间和控制线程。不过,经常存在在同一个地址空间中准并行运行多个控制线程的情形

      系统中的每个程序都是运行在某个进程的上下文(context)中的。上下文是由程序正确运行所需的状态的组成。这个状态包括存放在春初其中的程序的代码和数据,它的栈、通用寄存器的内容、程序计数器、环境变量以及打开文件描述符的集合。进程提供给应用程序两个关键抽象:

      1. 一个独立的逻辑控制流,它提供一个假象,好像我们的程序度独占地使用处理器。

      2. 一个私有的地址空间,它提供一个假象,好像我们的程序独占地使用存储器系统。

    逻辑控制流

      即使在系统中通常有许多其他的程序在执行,进程也可以向每个程序提供一种假象,好像他在独占地使用处理器。如果想用调试器单步执行程序,我们会看到一系列的程序计数器(PC)的值,这些程序唯一地对应于包含在程序的可执行目标中的指令,或者是包含在运行时状态连接到程序共享对象中的指令。这个PC值的序列叫做逻辑控制流,或者简称逻辑流。

      

      考虑一个运行着三个进程的系统,如上图所示。处理器的一个物理控制流分成了三个逻辑控制流,每个进程一个。每个竖直的条表示一个进程的逻辑流的一部分。在这个例子中,三个逻辑流的执行是交错的。进程A运行了一会,然后是进程B开始云新高完成。然后,进程C运行了一会儿,进程A接着运行直到完成。最后,进程C可以运行到结束了。

      上图的关键点在于进程是轮流使用处理器的。每个进程执行它的流的一部分,然后被抢占(暂时挂起),然后轮到其他进程。对于一个运行在这些进程之一的上下文中的程序,它看上去就像是在独占地使用处理器。唯一的反例是,如果我们精确地测量每条指令使用的时间,会发现在程序中一些指令的执行之间,CPU好像会周期性地停顿。然而,每次处理器停顿,它随后继续执行我们的程序,并不改变程序存取器位置或寄存器内容。

    进程描述符

      操作系统内核把进程组织为叫做task list的双向循环链表。task list中的每一个元素都是类型为task_struct结构体的进程描述符,即一个进程描述符就是一个task_struct结构体。这个结构体定义在<linux/sched.h>中。进程描述符包含描述一个进程的所有信息——打开的文件,进程的地址空间,挂起的信号,指向父进程结构体的指针以及pid等等。操作系统就是通过pid来识别每个进程的。它的类型是pid_t,一般底层的类型为int。

    私有地址空间

      进程也为每一个程序提供一种假象,好像它独占地使用系统地址空间。在一台有n位地址的机器上,地址空间是2n个可能地址的集合,0,1,...,2n-1。一个进程为每个程序提供它自己的私有地址空间。一般而言,和这个空间中某个地址相关联的那个存储器字节是不能被其他进程读或者写的,从这个意义说。这个地址空间是私有的。

      尽管和每个私有地址空间相关联的存储器内容一般是不同的,但是每个这样的空间都有想同的通用结构。比如,下图所示。

      

      上图展示了一个x86 Linux进程的地址空间的组织结构。地址空间底部是保留给用户程序的,包括通常的文本、数据、堆和段。对于32位程序进程来说,代码段从地址0x08048000开始,对于64位进程来说,代码段从地址0x00400000开始。地址空间顶部是保留给内核的。地址空间的这个部分包括内核在代表进程执行命令时 (比如,当应用程序执行一个系统调用时)使用的代码、数据和栈。

      32位应用程序都有4GB的进程地址空间。在Linux系统中,用户地址空间为3G,内核地址空间为1G。在Windows系统中,用户地址空间是2G,内核地址空间也是2G。

    进程的状态

      通常进程有5种状态,其中前3种是进程的基本状态:

      1) 运行状态:进程正在处理器上执行。在单处理器环境下,每一时刻最多只有一个进程处于运行状态。

      2) 就绪状态:进程已经处于准备运行状态,即进程获得了除处理器之外的一切所需资源,一旦得到处理器即可运行。

      3) 阻塞状态:又称为等待状态,进程正在等待某一事件而暂停运行,如等待某资源为可用(不包括处理器)或等待输入/输出完成。即使处理器空闲,该继承也不能运行。

      4)创建状态:进程正在被创建,尚未转到就绪状态。在unix系统中,只有一个系统调用可以用来创建新进程:fork。在调用了fork之后,这两个进程(父进程和子进程)拥有相同的存储映像、同样的环境字符串和同样的打开文件。

      5) 结束状态:进程正从系统中消失。通常由下列条件引起: 

        (1)正常退出(自愿的)。进程完成工作后,调用一个系统调用,通知操作系统它的工作已经完成。在Unix调用的是exit,而在windows中是ExitProcess

        (2)出错严重(自愿的)。如,读文件不存在。

        (3)严重错误(非自愿)。如,执行了一条非法指令,引用不存在的内存,或除数为0.

        (4)被其他进程杀死。 在Unix系统之,这个系统调用的是kill。在win32中对应的函数是TerminateProcess。

    状态之间的转换

       

      当一个就绪进程获取处理机时,其状态由就绪变为执行。

      当一个运行进程被剥夺处理机时,如果用完系统分给它的时间片、出现更高级别的其他进程,其状态由运行变为就绪。

      当一个运行进程因某事件而受阻时,如所申请资源被占用、启动I/O传输未完成,其状态由执行变为阻塞。在某些系统中,进程可以执行一个诸如pause的系统调用来进入阻塞状态。

      当所等待事件发生时,如得到申请资源,I/O传输完成,其状态由阻塞变成就绪。如果此时没有其他进程运行,则立即转换到运行态。

      一个就绪态进程不能做I/O操作或者其他会让它变为阻塞态的事情。只有运行态的进程可以被阻塞。所以,不可能存在从就绪态到阻塞态的转变。

      

    用户模式和内核模式

      为了使操作系统内核提供一个无懈可击的进程抽象,处理器必须提供一种机制,限制一个应用可以执行的指令以及它可以访问的地址空间范围。

      处理器通常是用某个控制器中的一个模式位来提供这种这种功能,该寄存器描述了进程当前享有的特权。当设置了模式位时,进程就运行在内核模式中(有时候叫做超级用户模式)。一个运行在内核模式的进程可以执行指令集中的任何指令,并且可以访问系统中任何存储器位置。

      没有设置模式位时,进程就运行在用户模式中。用户模式中的进程不允许执行特权指令,比如停止处理器、改变模式位,或者发起一个I/O操作。也不允许用户模式中的进程直接引用地址空间中内核区内的代码和数据。任何这样的尝试都会导致致命的保护故障。反之,用户程序必须通过系统调用接口间接地访问内核代码和数据。

      运行应用程序代码的进程初始时是在用户模式中的。进程从用户模式变为内核模式的唯一方法是通过诸如中断、故障或者陷入系统调用这样的异常。当异常发生时,控制传递到异常处理程序,处理器将模式从用户模式变为内核模式。处理程序运行在内核模式中,当它返回到应用程序代码时,处理器就把模式从内核模式改回到用户模式。

      Linux提供了一种聪明的机制,叫做proc文件系统,它允许用户模式进程访问内核数据结构内容。/proc文件系统将许多内核数据的内容输出为一个用户程序可以读的文本文件的层次结构。比如,你可以使用proc文件系统找出一般的系统属性,如CPU类型(PROC/cpuinfo),或者某个特殊的进程使用的存储器段(/proc/<process id>/maps).

      2.6版本的Linux内核引入/sys文件系统,它输出关于系统总线和设备的额外的底层信息。


    进程与程序的区别:

      1)进程是程序及其数据在计算机上的一次运行活动,是一个动态的概念。而程序是一组有序地指令集合,是一种静态的概念。

      2)进程是程序的一次执行过程,它是动态地创建和消亡的,具有一定的生命期,是暂时存在的;而程序则是一组代码的集合,它是永久存在的,课长期保存。

      3)一个进程可执行一个或几个程序,一个程序可构成多个进程。进程可创建进程,而程序不可创建新的程序。

      4)进程和程序的组成不同。进程的组成包括程序、数据和进程控制块。

    参考资料: 

      1.《现代操作系统》(原书第三版)  机械工业出版社   【1.51, 2.1】

      2. 《深入理解计算机系统》(原书第2版)  机械工业出版社  【第8章】

  • 相关阅读:
    Verilog语言
    OrCAD --从SNAPEDA导入封装库
    RAM/ROM IP一次性总结
    USB之Main item, Local item和Global item 的作用范围与归类
    发光LED压降与工作电流总结
    C之输入输出函数(3) -- 请使用sscanf()
    C之输入输出函数(2) -- gets()
    C之输入输出函数(1) -- fgets()
    C中的lvalue和rvalue
    关于字符串的一点补充
  • 原文地址:https://www.cnblogs.com/vincently/p/4431523.html
Copyright © 2011-2022 走看看