进程_进程 线程 - CSDN
精华内容
参与话题
  • 什么是进程

    千次阅读 多人点赞 2018-09-01 10:25:05
    进程:进行就是正在进行中的程序  1、用户角度: 进程是程序的一次动态执行过程  2、操作系统: 进程是操作系统分配资源的基本单位,也是最小单位 很抽象的概念,那么,到底什么是进程呢?又为什么要有进程? ...

     

    程序:完成特定任务的一系列指令集合 

             代码段+数据段

             -----放在磁盘中的程序 

    进程:进行就是正在进行中的程序

             1、用户角度: 进程是程序的一次动态执行过程

             2、操作系统: 进程是操作系统分配资源的基本单位,也是最小单位

    很抽象的概念,那么,到底什么是进程呢?又为什么要有进程?

    CPU一次只能处理一个程序,CPU速度很快,而内存很慢,所以CPU会有大量的时间都是空闲的。而CPU又是很昂贵的,为了解决浪费CPU的情况,就出现了中断处理,将程序分成一小片一小片的,这个进程执行一点,那个进程执行一点。虽然在内部进程的执行是一段一段的,但是CPU的速度很快的(速度都是纳秒级别的),所以我们是感受不到进程执行过程中的停顿的。

    CPU执行程序的过程

     

           既然是一段一段执行,CPU在执行一个进程时,其他的进程就处于等待状态,为什么执行当前的这个进程而不是其他进程呢?这就要分情况讨论了,有可能是因为轮到它们的时间片用完了,也可能是它在等待某种资源等,所以在内存中,每个进程的状态可能是不同的,那么,进程的状态有哪些呢?

    再分详细一点的话就有七态了

          

     

    现在的系统都是多道程序处理系统,那就代表着在同一段时间内,系统里边执行的程序可能有很多个,那么,系统通过什么去区分他们呢?

     

    进程的标识号:

    系统为每一个进程分配一个唯一的标识号(正整数),这个标识号就称为进程ID(progress identifer),即PID。最早的时候有一个0号进程,是写死在内核里边的,所以操作系统在启用的时候,0号进程就启用了。

    0号进程的作用:启动1号进程,将1号进程启动了之后就没事干了

    1号进程是系统启动的第一个用户态进程,其他进程就相当于1号进程的子孙。

    所以之后我们创建的进程的最小为2号。

    想象一下一个小区里边,每套房都有一个门牌号(相当于我们的PID),为什么仅凭一个房间号就能确认哪个是你自己的家,而不会走到你邻居家呢?因为每一个门牌号都有属于自己的空间,所以每个进程也应该要有属于自己的地址空间。这个空间给多大呢?4G,Linux下有3G在用户空间,1G在内核。Windows下,有2G在内核,2G在用户空间。每个进程都有4G,同一时间内可能会有成百上千乃至上万个进程,累加起来,所需的内存是非常庞大的,然而我们的计算机内存并没有那么多的内存(内存可是很贵的),所以,进程的地址空间其实是虚拟地址,是操作系统给它们画的一个大饼。

           前边已经说了,进程是一小片一小片的执行的,所以,即使进程认为自己拥有4G空间,但是并不会在同一时刻使用4G空间,那么,操作系统只需要在你需要使用的时候给你分配一点空间就行了。你不用的时候,操作系统就可以将这块空间给别的进程使用。那怎么通过虚拟地址找到对应的物理地址(在内存中真时存在的地址)呢?操作系统为每个进程提供了一个MMU(内存管理单元),里边有一张表,里边将虚拟内存映射到物理内存的情况记录着,然后每个进程里边都有一个指针(在mm_struct 里边的pgd指针)指向这张表

    除了以上讲的进程pid地指空间,进程在执行过程中,可能会打开文件等资源,还有进程在切换的时候,当前的状态和它执行到哪了(上下文信息)这些信息是不是都应该记录下来呢?那这些信息都存放在哪呢?

    接下来要提出一个进程中最重要的概念,PCB(process control block)即,进程控制块。既然是控制进程的,进程的相关信息都应该存放在里边。那么PCB到底是何方神圣呢?其实PCB的本质就是一个名为task_struct 的结构体。里边存放着进程几乎所有的信息。

    task_struct(PCB)内容分类

     

    标识符:就是进程的PID。

    状态:任务状态、退出代码,退出信号等。

    优先级:相对于其他进程的优先级。

    程序计数器:程序中即将被执行的下一条指令的地址。

    内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。

    上下文数据:进程执行时处理器的寄存器中的数据。

    I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。

    记账信息:可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。

     

    PCB可以说是很强大的了,那么,操作系统想要控制一个进程,只需控制其PCB就行了。所以操作系统控制一个进程分两步:

            1、通过PCB将一个进程描述起来

            2、将这些PCB组织起来。

    怎么将这些PCB组织起来呢?前边已经说了,PCB是一个结构体,那么创建一个链表,每个节点都存放一个PCB,来一个进程,就把他的PCB挂到链表上,来一个挂一个,那么,操作系统只要拎着这个链表的头,后边所有的PCB都可以获取到了,PCB获取到了,整个进程的控制权也就拿到了。

           进程有不同的状态,如果不同状态的进程都放在一个链表上的话,如果进程很多,链表就会很长,这就降低了操作系统调度在对进程进行调度时的查找效率。为了解决这个问题,操作系统创建了索引表。让同一状态的进程归入一个索引表再由索引指向PCB,多个状态对应多个不同的索引表,各状态的进程形成不同的索引表,就绪索引表、阻塞索引表……

    展开全文
  • 什么是进程? ( 进程的详细概念 )

    千次阅读 多人点赞 2018-07-13 12:57:12
    进程管理是操作系统重点、难点问题,也是贯穿Linux学习的知识点。那么什么是进程? 为什么引入进程的概念?  从理论角度看,是对正在运行的程序过程的抽象;  从实现角度看,是一种数据结构,目的在于清晰...

    进程管理是操作系统重点、难点问题,也是贯穿Linux学习的知识点。那么什么是进程?

    • 为什么引入进程的概念?

       从理论角度看,是对正在运行的程序过程的抽象;
       从实现角度看,是一种数据结构,目的在于清晰地刻画动态系统的内在规律,有效管理和调度进入计算机系统主存储器运行的程序。

    • 什么是进程?

       狭义定义:进程就是一段程序的执行过程。
       广义定义:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。

    • 进程有怎么样的特征?

      动态性:进程的实质是程序在多道程序系统中的一次执行过程,进程是动态产生,动态消亡的。
      并发性:任何进程都可以同其他进程一起并发执行
      独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位;
      异步性:由于进程间的相互制约,使进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推 进
      结构特征:进程由程序、数据和进程控制块三部分组成;
      多个不同的进程可以包含相同的程序:一个程序在不同的数据集里就构成不同的进程,能得到不同的结果; 但是执行过程中,程序不能发生改变。

    • Linux进程结构?

          Linux进程结构:可由三部分组成:代码段、数据段、堆栈段。也就是程序、数据、进程控制块PCB(Process Control Block)组成。进程控制块是进程存在的惟一标识,系统通过PCB的存在而感知进程的存在。
          系统通过PCB对进程进行管理和调度。PCB包括创建进程、执行程序、退出进程以及改变进程的优先级等。而进程中的PCB用一个名为task_struct的结构体来表示,定义在include/linux/sched.h中,每当创建一新进程时,便在内存中申请一个空的task_struct结构,填入所需信息,同时,指向该结构的指针也被加入到task数组中,所有进程控制块都存储在task[]数组中。

    • 进程的三种基本状态?

         a> 就绪状态:进程已获得除处理器外的所需资源,等待分配处理器资源;只要分配了处理器进程就可执行。就绪进程可以按多个优先级来划分队列。例如,当一个进程由于时间片用完而进入就绪状态时,排入低优先级队列;当进程由I/O操作完成而进入就绪状态时,排入高优先级队列。
         b> 运行状态:进程占用处理器资源;处于此状态的进程的数目小于等于处理器的数目。在没有其他进程可以 执行时(如所有进程都在阻塞状态),通常会自动执行系统的空闲进程。
         c> 阻塞状态:由于进程等待某种条件(如I/O操作或进程同步),在条件满足之前无法继续执行。该事件发生 前即使把处理机分配给该进程,也无法运行。

    • 进程和程序的区别?

         a> 程序是指令和数据的有序集合,是一个静态的概念。而进程是程序在处理机上的一次执行过程,它是一个 动态的概念。
         b> 程序可以作为一种软件资料长期存在,而进程是有一定生命期的。程序是永久的,进程是暂时的。
          c> 进程是由进程控制块、程序段、数据段三部分组成;
          d> 进程具有创建其他进程的功能,而程序没有。
          e> 同一程序同时运行于若干个数据集合上,它将属于若干个不同的进程,也就是说同一程序可以对应多个进 程。
          f> 在传统的操作系统中,程序并不能独立运行,作为资源分配和独立运行的基本单元都是进程。

    • 进程控制?

      创建进程
      引起创建进程的事件:
      1) 用户登录
      2) 作业调度
      3) 提供服务
      4) 应用请求
      进程的创建过程
      一旦操作系统发现了要求创建新进程的事件后,便调用进程创建原语Creat()按下述步骤创建一个新 进程。
      1) 申请空白PCB。为新进程申请获得唯一的数字标识符,并从PCB集合中索取一个空白PCB。
      2) 为新进程分配资源。
      3) 初始化进程控制块。PCB的初始化包括:
      ①初始化标识信息,将系统分配的标识符和父进程标识符,填入新的PCB中。
      ②初始化处理机状态信息,使程序计数器指向程序的入口地址,使栈指针指向栈顶。
      ③初始化处理机控制信息,将进程的状态设置为就绪状态或静止就绪状态,对于优先级,通常 是将它设置为最低优先级,除非用户以显式的方式提出高优先级要求。
      4) 将新进程插入就绪队列,如果进程就绪队列能够接纳新进程,便将新进程插入到就绪队列中
      进程终止
      引起进程终止的事件
      1)正常结束
      2)异常结束
      3)外界干预
      进程的终止过程
      如果系统发生了上述要求终止进程的某事件后,OS便调用进程终止原语,按下述过程去终止指定的进 程。
      1)根据被终止进程的标识符,从PCB集合中检索出该进程的PCB,从中读出该进程状态。
      2)若被终止进程正处于执行状态,应立即终止该进程的执行,并置调度标志为真。用于指示该进程 被终止后应重新进行调度。
      3)若该进程还有子孙进程,还应将其所有子孙进程予以终止,以防他们成为不可控的进程。
      4)将被终止的进程所拥有的全部资源,或者归还给其父进程,或者归还给系统。
      5)将被终止进程(它的PCB)从所在队列(或链表)中移出,等待其它程序来搜集信息。
      阻塞唤醒
      1.引起进程阻塞和唤醒的事件
      1)请求系统服务
      2)启动某种操作
      3)新数据尚未到达
      4)无新工作可做
      2.进程阻塞过程
      正在执行的进程,当发现上述某事件后,由于无法继续执行,于是进程便通过调用阻塞原语block把自 己阻塞。可见,进程的阻塞是进程自身的一种主动行为。进入block过程后,由于此时该进程还处于执 行状态,所以应先立即停止执行,把进程控制块中的现行状态由执行改为阻塞,并将PCB插入阻塞队 列。如果系统中设置了因不同事件而阻塞的多个阻塞队列,则应将本进程插入到具有相同事件的阻塞 (等待)队列。最后,转调度程序进行重新调度,将处理机分配给另一就绪进程,并进行切换,亦即, 保留被阻塞进程的处理机状态(在PCB中),再按新进程的PCB中的处理机状态设置CPU环境。
      3.进程唤醒过程
      当被阻塞的进程所期待的事件出现时,如I/O完成或者其所期待的数据已经到达,则由有关进程(比如, 用完并释放了该I/O设备的进程)调用唤醒原语wakeup(),将等待该事件的进程唤醒。唤醒原语执行 的过程是:首先把被阻塞的进程从等待该事件的阻塞队列中移出,将其PCB中的现行状态由阻塞改为就 绪,然后再将该PCB插入到就绪队列中。

    展开全文
  • 进程的基本概念

    万次阅读 2018-11-15 13:39:26
    1.什么是进程?  1. 进程就是运行起来的程序,程序运行起来需要被加载到内存中。(这是站在用户的角度看待进程的)  2. 进程就是操作系统的描述,这个描述叫PCB(进程控制块),Linux下PCB有自己的名字叫task_...

    1.什么是进程?

          1. 进程就是运行起来的程序,程序运行起来需要被加载到内存中。(这是站在用户的角度看待进程的)
          2. 进程就是操作系统的描述,这个描述叫PCB(进程控制块),Linux下PCB有自己的名字叫task_struct.而操作系统就是使用task_struct结构体描述进程,使用双向链表来将这些结构体组织起来进行管理。

    task_struct结构体的内容分类(进程的描述信息)下面简单的介绍几类:

        进行(运行)中的程序------程序是死的。放在硬盘中,当运行起来>的时候就会被加载到内存中。        站在操作系统的角度:进程是PCB(进程控制块) ---task struct
                    标识符:描述本进程的唯一标识符,用来区别其他进程的。
                    状态:任务状态,退出代码,推出信号等。
                    上下文数据:进程执行时处理器的寄存器中的数据。
                    程序计数器:记录每个进程下一次要进行的指令的地址。
                    优先级:相对于其他进程的优先级。

                    文件的状态信息
                    记账信息。

    如果想深入的了解的话可以查看大佬的详解:https://blog.csdn.net/bit_clearoff/article/details/54292300

    2.查看进程信息的命令

            ps -ef:查看所有的进程信息。
            ps aux:查看进程的详细信息。
            top;(查看进程的信息)
            查看你所要的进程信息: ps -ef | 名字。
                    getpid();(在代码中获取一个进程的id)(一个系统的调用接口)

    #include<stdio.h>
    
    int main()
    {
        printf("%d\n", getpid());//使用getpid()来获取一个进程的id
        return 0;
    }

    3.如何创建一个进程:

            shell---命令行解释器(shell相当于我们命令行的界面,如果我们从键盘中敲入一个指令时,shell就会执行这条指令)。

    系统调用open返回的是一个文件描述符,类型为int,C库中的fopen返回的是文件流指针:FILE*。
    我们所说的缓冲区(printf),用户态的一个缓冲区,是文件流指针自带的
        printf,  fwrite这些库函数都是先把数据写入到缓冲区中,等缓冲区写满了之后或者其他;条件满足之后才会写入到真正的文件中,而系统调用没有这个用户态的缓冲区(是直接将数据写入到文件中)这个说法不准确
    fork() ---(通过复制调用生成一个新的进程)创建一个子进程。
                    对于父进程来说,fork()的返回值是子进程的pid
                    对于子进程来说,fork()的返回值是0

            因为子进程是根据父进程为模板来创建的,因此父子的代码段是一样的(父子进程运行的是同一段代码)。但是父子进程的返回值不同。父子进程的数据不相同。子进程的数据会另外开辟内存来存放。
            对于代码来说父子进程是相同的(相同的代码只是fork()之下的代码,而不是从头到尾),但是父子进程的数据是独有的(写时复制技术)。
            父进程是从代码头到代码的结束。子进程是从fork()开始到代码结束。
            用户就是通过返回值来判断分辨父子进程,来进行代码的分流。

            kill 进程号----》杀死进程。

    4.进程的状态

            R(running)            运行态:并不意味着程序一定在运行中,它表明进程要么在运行中要么在运行队列里。
            S(sleeping)           可中断的休眠(浅度睡眠)
            D(disk sleep)         不可被中断的休眠,只能通过指定的方式--->唤醒(深度睡眠)
            T(stopped)            停止的状态
            t(tracing stop)       追踪状态
            X(dead)                 死亡状态
            Z(zombie)             僵死态

    5.僵尸进程

            产生原因:
                    子进程先于父进程退出它会保存自己的退出状态,因此它不会自动释放所有资源。子进程退出后会通知父进程子进程退出了,然后让父进程去获取退出状态,然后完全释放子进程资源。假如父进程不管子进程的退出状态,那么这个子进程就会变成一个僵死进程。
            僵尸进程的危害:资源泄露,正常的进程可能无法创建。
            僵死进程如何杀死:杀死它的父进程就可以了。

    下面是一个僵尸进程的演示:

    #include<stdio.h>
    #include<stdlib.h>
    
    int main()
    {
            pid_t pid = fork();
            if(pid < 0)
            {
                    perror("fork error");
                    return -1;
            }
            else if(pid == 0)
            {
                    printf("this is a child\n");
                    sleep(10);//为了方便我们观察子进程退出之前的状态
                    exit(0);
            }
            else
            {
                    sleep(30);//为了使子进程先于父进程退出
                    printf("this is parent\n");
            }
            while(1)
            {
                    sleep(1);
            }
            return 0;
    }
    

    当子进程还没有退出的时候:此时的子进程和父进程都没有退出。(使用ps aux查看进程的状态)

     当子进程退出的时候:因为父进程还没有退出的时候,而子进程退出了,所以子进程就变成了一个僵尸进程。如下所示:(第一个是父进程,第二个是子进程(现在变成了僵尸进程))。

     上面这个就是一个僵尸进程。

    6.孤儿进程

            产生的原因:
                    父进程先于子进程退出,那么这个子进程就会变成一个孤儿进程,并且进入后台运行。
            特性:
                    它原来的父进程退出后。它的父进程就变成了init进程,如果子进程退出后,init进程将负责释放子进程的资源,所以子进程就不会变成一个僵死进程。
            孤儿进程运行时,是后台运行,你可以继续输入其他的指令。

    下面是孤儿进程的代码演示:

    #include<stdio.h>
    #include<unistd.h>
    
    int main()
    {
            pid_t pid = fork();
            if(pid < 0)
            {
                    return -1;
            }
            else if(pid == 0)
            {
                    sleep(10);//让子进程睡的时间长一点,让父进程先退出
                    printf("this is child\n");
            }
            else
            {
                    sleep(5);//这里睡几秒是为了执行后观察父进程退出之前的状态
                    printf("this is parent\n");
            }
            return 0;
    }
    

    当父进程退出之前的状态:此时的父进程和子进程都没有退出:

    当父进程先于子进程退出的时候:父进程因为退出而消失,子进程就变成了一个孤儿进程。

    这就是一个孤儿进程。

    7.进程的优先级

     为什么要有进程的优先级?

             因为进程的功能不同,因此进程对CPU的资源的要求也不同,所以对进程的调度就有了优先级,进程的优先级决定以一个进程的CPU资源的优先级分配权。

             cpu资源分配的先后顺序,就是指进程的优先权。

    使用命令ps -l来查看

    上面的一些列是什么意思呢?

            UID:代表执行者的身份
            PID:代表这个进程的id
            PPID:代表的是父进程的id
            PRI:代表这个进程可被执行的优先级,它的值越小优先级越高
            NI:代表这个进程的nice值。(表示进程可被执行的优先级的修正数据)      

    其实进程的优先级最后等于PRI(New) = PRI(Old)+ nice  (所以当nice的值是负数的时候,优先级越高)。    PRI越小,越早执行。

    修改进程的优先级命令:

            nice:可以指定进程(还没有运行起来的进程)的优先级。(nice -n 你要设置的nice值  程序)nice -n -10  ./test
            renice:也可以指定进程(已经运行起来的进程)的优先级。(renice 你要设置的nice值   -p   进程的id)renice -10 -p 5200

    修改演示:首先编写一个死循环的程序,然后执行这个程序

    nice 对进程的修改:

    renice 对进程的修改:首先将程序执行起来,然后找到这个进程的id,然后用renice来修改优先级。

    其他的概念:

            竞争性:系统的进程数目过多,而CPU只有少量,甚至只有1个,所以进程之间具有竞争的属性,为了高效的完成任务,更合理的竞争相关的资源,所以就有了优先级。
            独立性:一个进程出现问题不会影响其他的进程。多个进程运行期间互不干扰。
            并行:多个进程在多个CPU下分别同时运行,这称之为并行。
            并发:多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发

    环境变量

            概念:环境变量一般是指在操作系统中用来指定操作系统运行环境的一些参数。

    查看环境变量的命令:env.

            环境变量保存操作系统环境相关的一些功能性的数据的变量。
            环境变量具有全局性,就是在哪里都可以找到这个环境变量。

    环境变量的一些操作:

            1.通过main函数的第3个参数来获取环境变量。

    #include<stdio.h>
    #include<unistd.h>
    
    int main(int argc, char *argv[], char *env[])
    {
            int i = 0;
            for(i = 0; env[i] != NULL; i++)
            {
                    printf("%s\n ",env[i]);
            }
        return 0;
    }
    

            2.通过一个全局变量**environ来获取环境变量。

    #include<stdio.h>
    include<unistd.h>
    int main(int argc, char *argv[], char *env[])
    {
       extern char **environ;//存放环境变量的全局变量(因为它没有包含在头文件中,所以要声明)
       int i = 0;
       for(i = 0; environ[i];i++)
       printf("%s \n",environ[i]);
       return 0;
    }
    

            3.getenv() ---》-获取指定的环境变量。(getenv("PATH")).
                              putenv()-----设置一个环境变量

    #include<stdio.h>
    #include<unistd.h>
    #include<stdlib.h>
    int main()
    {
            printf("%s\n", getenv("PATH");//用getenv来访问PATH这个环境变量
            return 0;
    }
    

            4.export (设置一个环境变量)。

            5.set :查看一个环境变量。(它查看的环境变量比env更加的详细)
            6.echo :可以打印一个环境变量,在变量前加$.
            如何干掉一个环境变量:
                 unset:删除一个环境变量(unset 环境变量的名字)

    程序(进程)地址空间:

            首先它是一个线性的地址空间。(进程的虚拟地址空间)
            程序没有地址空间,因为程序在被激活运行起来之后才会有一个运行空间。

            内存地址就是对内存的一个编号,一个地址指向内存的一个位置。

    那我们可以直接访问到物理内存呢?看下面的两段代码,思考为什么?

    zone1.c

    #include<stdio.h>
    #include<unistd.h>
    
    int val = 100;
    
    int main()
    {
            pid_t pid = fork();
            if(pid < 0)
            {
                    return -1;
            }
            else if(pid == 0)
            {
                    printf("child val:%d----%p\n",val);//在子进程中打印出val的值和它的地址
            }
            else
            {
                    printf("parent val:%d----%p\n", val);//在父进程中打印出val的值和他的地址
            }
            return 0;
    }
    

    zone.c

    #include<stdio.h>
    #include<unistd.h>
    
    int val = 100;
    
    int main()
    {
            pid_t pid = fork();
            if(pid < 0)
            {
                    return -1;
            }
            else if(pid == 0)
            {
                    val = 200;//在子进程中修改val的值,然后查看父进程中的val的值是否改变
                    printf("child val:%d----%p\n",val);//在子进程中打印val的值和地址,
            }
            else
            {
                    sleep(3);//这里让父进程先睡三秒,让子进程先执行。
                    printf("parent val:%d----%p\n", val);//在子进程中打印val的值和地址,查看与父进程中的val和地址有什么区别。
            }
            return 0;
    }
    

    这两个代码段执行的结果为: 

    这是就会产生一个问题:为什么在zone的执行结果中,父子进程的变量的值不相同,但是地址为什么相同呢?

            1.变量的内容不一样,代表父进程和子进程输出的变量绝对不是同一个变量

            2.地址一样,代表该地址一定不是物理地址。

    其实进程的地址空间是一个虚拟的地址,并不是物理内存的地址。

    一个虚拟地址如何找到真正的物理地址?

            其实虚拟地址和物理地址直接有一个页表的存在。

            页表:1.记录虚拟地址与物理地址之间的映射关系。
                       2.内存的访问控制(记录了属性的信息,比如:记录了该代码段是只读或者是只写的)。

    页表也是一个结构体。

    什么是虚拟地址空间:
            虚拟地址空间是一个结构体mm_struct结构描述的,结构体的名字叫struct_mm,因此程序地址空间应该叫虚拟地址空间。

    程序的地址空间都是虚拟地址,而不是真正的物理内存地址,而访问虚拟地址空间是通过页表的转换后得到物理内存地址而访问内存的。

    为什么计算机告诉我们每个进程都有4G的地址空间?
            因为计算机知道我们用不了这门多的地址空间,所以我们使用多少就通过页表给我们在物理内存中映射多少地址空间。

    写时复制技术:
            假设有一个全局变量,那么在物理内存中就有一段空间来存放这个全局变量,如果父子进程不修改这个全局变量的话,那么父子进程的虚拟地址空间通过页表都指向同一块物理空间。如果父子进程修改这个全局变量的话,虚拟内存的地址不变,但是在物理内存空间会重新分配一块内存来保存你父子进程修改后的数据,并更新页表,这样也就是为什么你发现父子进程中一个变量它的虚拟地址相同但是值不同原因。

    展开全文
  • 操作系统(进程篇)

    千次阅读 2018-09-20 03:12:20
    2.系统中一个进程由 程序 、 数据集合 和 进程控制块(PCB) 三部分组成。 3.在多道程序设计系统中,进程是一个 动 态概念,程序是一个 静 态概念。 4.在一个单CPU系统中,若有5个用户进程。假设当前系统为用户...

    一、填空

    1.进程在执行过程中有三种基本状态,它们是 运行 态、 就绪 态和 阻塞 态。
    2.系统中一个进程程序数据集合进程控制块(PCB) 三部分组成。
    3.在多道程序设计系统中,进程是一个 态概念,程序是一个 态概念。
    4.在一个单CPU系统中,若有5个用户进程。假设当前系统为用户态,则处于就绪状态的用户进程最多有 4 个,最少有 0 个。
    注意,题目里给出的是假设当前系统为用户态,这表明现在有一个进程处于运行状态,因此最多有4个进程处于就绪态。也可能除一个在运行外,其他4个都处于阻塞。这时,处于就绪的进程一个也没有。
    5.总的来说,进程调度有两种方式,即 不可剥夺 方式和 剥夺 方式。

    6.进程调度程序具体负责中央处理机(CPU)的分配。
    7.为了使系统的各种资源得到均衡使用,进行作业调度时,应该注意 CPU忙碌 作业和 I/O忙碌 作业的搭配。
    8.所谓系统调用,就是用户程序要调用 操作系统 提供的一些子功能。
    9.作业被系统接纳后到运行完毕,一般还需要经历 后备 、 运行 和 完成 三个阶段。
    10.假定一个系统中的所有作业同时到达,那么使作业平均周转时间为最小的作业调度算法是 短作业优先 调度算法。
    11.进程是程序的 一次执行 过程,程序是进程 赖以存在 的基础。
    12. 可以把CPU的指令分为两类,一类是操作系统和用户都能使用的指令,一类是只能由操作系统使用的指令。前者称为**“ 非特权 ”指令,后者称为“ 特权 ”**指令。
    13. 系统调用命令的程序属于操作系统,它应该在 管 态下执行。用户程序只有通过计算机系统提供的“ 访管 ”指令,才能实现由目态转为管态、进而调用这些系统调用命令。
    14. 访管指令是一条非特权指令,功能是执行它就会产生一个软中断,促使中央处理机由 态转为 态,进入操作系统,并处理该中断。
    15. 一个进程创建后,系统就感知到它的存在;一个进程撤销后,系统就无法再感知到它。于是,从创建到撤销,这个时间段就是一个进程的“ 生命期 ”。
    16. 由于PCB是随着进程的创建而建立,随着进程的撤销而取消的,因此系统是通过PCB来“感知”系统中的进程的,PCB是进程 存在 的唯一标志。

    二、选择

    1.在进程管理中,当 C 时,进程从阻塞状态变为就绪状态。
    A.进程被调度程序选中 B.进程等待某一事件发生
    C.等待的事件出现 D.时间片到

    2.在分时系统中,一个进程用完给它的时间片后,其状态变为 A
    A.就绪 B.等待 C.运行 D.由用户设定

    3.下面对进程的描述中,错误的是 D
    A.进程是动态的概念 B.进程的执行需要CPU
    C.进程具有生命周期 D.进程是指令的集合

    4.操作系统通过 B 对进程进行管理。
    A.JCB B.PCB C.DCT D.FCB
    5.一个进程被唤醒,意味着该进程 D
    A.重新占有CPU B.优先级变为最大
    C.移至等待队列之首 D.变为就绪状态
    6.由各作业JCB形成的队列称为 C
    A.就绪作业队列 B.阻塞作业队列
    C.后备作业队列 D.运行作业队列
    7.既考虑作业等待时间,又考虑作业执行时间的作业调度算法是 A
    A.响应比高者优先 B.短作业优先
    C.优先级调度 D.先来先服务
    8.作业调度程序从处于 D 状态的队列中选取适当的作业投入运行。
    A.就绪 B.提交 C.等待 D.后备
    9. A 是指从作业提交系统到作业完成的时间间隔。
    A.周转时间 B.响应时间
    C.等待时间 D.运行时间
    10.计算机系统在执行 C 时,会自动从目态变换到管态。
    A.P操作 B.V操作 C.系统调用 D.I/O指令
    11.进程状态由就绪变为运行,是由于 C 引起的。
    A.中断事件 B.进程状态变迁
    C.进程调度 D.为作业创建进程
    12. 当一个进程处于 D 时,称其为就绪状态。
    A.等着读磁盘上的信息 B.等着进入内存
    C.等着输入一批数据 D.等着获得CPU的控制权
    13. 在操作系统中,处于就绪和阻塞状态的进程都没有占用处理机。当处理机空闲时,正确的操作应该是 B
    A.就绪和阻塞进程都可以变迁成为运行状态
    B.只有就绪进程可以变迁成为运行状态
    C.只有阻塞进程可以变迁成为运行状态
    D.就绪和阻塞状态的进程都不能变迁成为运行进程
    14. 我们把“逻辑上独立的程序,在执行时间上相互重叠,一个程序的执行还没有结束,另一个程序的执行已经开始”的这种特性,称为程序执行的 A
    A.并发性 B.并行性 C.可执行性 D.可交互性

    3、简答题:

    1.在多道程序设计系统中,如何理解“内存中的多个程序的执行过程交织在一起,大家都在走走停停”这样一个现象?

    答:在多道程序设计系统中,内存中存放多个程序,它们以交替的方式使用CPU。因此,从宏观上看,这些程序都开始了自己的工作。但由于CPU只有一个,在任何时刻CPU只能执行一个进程程序。所以这些进程程序的执行过程是交织在一起的。也就是说,从微观上看,每一个进程一会儿在向前走,一会儿又停步不前,处于一种“走走停停”的状态之中。

    2.什么是“原语”、“特权指令”、“系统调用命令”和“访管指令”?它们之间有无一定的联系?
    答:特权指令和访管指令都是CPU指令系统中的指令,只是前者是一些只能在管态下执行的指令,后者是一条只能在目态下执行的指令。原语和系统调用命令都是操作系统中的功能程序,只是前者执行时不能被其他程序所打断,后者没有这个要求。操作系统中有些系统调用命令是以原语的形式出现的,例如创建进程就是一条原语式的系统调用命令。但并不是所有系统调用命令都是原语。因为如果那样的话,整个系统的并发性就不可能得到充分地发挥。
    3.操作系统是如何处理源程序中出现的系统调用命令的?
    答:编译程序总是把源程序中的系统调用命令改写成为一条访管指令和相应的参数。这样在程序实际被执行时,就通过访管指令进入操作系统,达到调用操作系统功能子程序的目的。
    4.系统调用与一般的过程调用有什么区别?
    (1)一般的过程调用,调用者与被调用者都运行在相同的CPU状态,即或都处于目态(用户程序调用用户程序),或都处于管态(系统程序调用系统程序);但发生系统调用时,发出调用命令的调用者运行在目态,而被调用的对象则运行在管态,即调用者与被调用者运行在不同的CPU状态。
    (2)一般的过程调用,是直接通过转移指令转向被调用的程序;但发生系统调用时,只能通过访管指令提供的一个统一的入口,由目态进入管态,经分析后,才转向相应的操作系统命令处理程序。
    (3)一般的过程调用,在被调用者执行完后,就径直返回断点继续执行;但系统调用可能会导致进程状态的变化,从而引起系统重新分配处理机。因此,系统调用处理结束后,不一定是返回调用者断点处继续执行。

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

    答:创建进程原语的主要功能有以下三项。
    (1)为新建进程申请一个PCB。
    (2)将创建者(即父进程)提供的新建进程的信息填入PCB中。
    (3)将新建进程设置为就绪状态,并按照所采用的调度算法,把PCB排入就绪队列中。

    6.处于阻塞状态的一个进程,它所等待的事件发生时,就把它的状态由阻塞改变为就绪,让它到就绪队列里排队,为什么不直接将它投入运行呢?

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

    7.作业调度与进程调度有什么区别?
    答:作业调度和进程调度(即CPU调度)都涉及到CPU的分配。但作业调度只是选择参加CPU竞争的作业,它并不具体分配CPU。而进程调度是在作业调度完成选择后的基础上,把CPU真正分配给某一个具体的进程使用。
    8.系统中的各种进程队列都是由进程的PCB链接而成的。当一个进程的状态从阻塞变为就绪状态时,它的PCB从哪个队列移到哪个队列?它所对应的程序也要跟着移来移去吗?为什么?
    答:当一个进程的状态从阻塞变为就绪时,它的PCB就从原先在的阻塞队列移到就绪队列里。在把进程的PCB从这个队列移到另一个队列时,只是移动进程的PCB,进程所对应的程序是不动的。这是因为在进程的PCB里,总是记录有它的程序的断点信息。知道了断点的信息,就能够知道程序当前应该从哪里开始往下执行了。这正是保护现场所起的作用。

    9.为什么说响应比高者优先作业调度算法是对先来先服务以及短作业优先这两种调度算法的折中?
    答:先来先服务的作业调度算法,重点考虑的是作业在后备作业队列里的等待时间,因此对短作业不利;短作业优先的作业调度算法,重点考虑的是作业所需的CPU时间(当然,这个时间是用户自己估计的),因此对长作业不利。“响应比高者优先”作业调度算法,总是在需要调度时,考虑作业已经等待的时间和所需运行时间之比,即:
    该作业已等待时间 / 该作业所需CPU时间

    计算
    在这里插入图片描述

    分别采用先来先服务和短作业优先作业调度算法。试问它们的平均周转时间各是什么?你是否还可以给出一种更好的调度算法,使其平均周转时间优于这两种调度算法?

    解:(1)采用先来先服务作业调度算法时的实施过程如下。

    在这里插入图片描述
    周转时间:完成时间-到达时间
    完成时间:开始时间+所需CPU时间

    在这里插入图片描述

    这里要注意,在作业1运行完毕进行作业调度时,作业2和3都已经到达。由于是实行短作业优先作业调度算法,因此先调度作业3运行,最后调度作业2运行。所以,这时的作业调度顺序是1→3→2。其平均周转时间为:
    (8 + 8 + 12.6)/ 3 = 9.53

    (3)还可以有更好的作业调度算法,使其平均周转时间优于这两种调度算法。例如,如果知道在作业1后面会来两个短作业,那么作业1到达后,先不投入运行。而是等所有作业到齐后,再按照短作业优先作业调度算法进行调度,具体实施过程如下。

    在这里插入图片描述

    这时的作业调度顺序是3→2→1。其平均周转时间为:
    (1 + 5.6 + 14)/ 3 = 6.87

    2.设有一组作业,它们的到达时间和所需CPU时间如下所示。

    在这里插入图片描述

    分别采用先来先服务和短作业优先作业调度算法。试问它们的调度顺序、作业周转时间以及平均周转时间各是什么?
    在这里插入图片描述

    这时,作业的调度顺序是1→2→3→4。其平均周转时间为:
    (70 + 60 + 60 + 45)/ 4 = 58.75

    (2)采用短作业优先作业调度算法时的实施过程如下。
    在这里插入图片描述

    这时,作业的调度顺序是1→4→3→2。其平均周转时间为:
    (70 + 5 + 35 + 75)/ 4 = 46.25

    3.某系统有三个作业:

    在这里插入图片描述

    系统确定在它们全部到达后,开始采用响应比高者优先调度算法,并忽略系统调度时间。试问对它们的调度顺序是什么?各自的周转时间是多少?

    响应比= (最长到达时间-到达时间)/所需cpu时间;响应比最高开始运行

    解:三个作业是在9.5时全部到达的。这时它们各自的响应比如下:
    作业1的响应比 =(9.5 – 8.8)/ 1.5 = 0.46
    作业2的响应比 =(9.5 – 9.0)/ 0.4 = 1.25
    作业3的响应比 =(9.5 – 9.5)/ 1.0 = 0
    因此,最先应该调度作业2运行,因为它的响应比最高。它运行了0.4后完成,这时的时间是9.9。再计算作业1和3此时的响应比:
    作业1的响应比 =(9.9 – 8.8)/ 1.5 = 0.73
    作业3的响应比 =(9.9 – 9.5)/ 1.0 = 0.40
    因此,第二个应该调度作业1运行,因为它的响应比最高。它运行了1.5后完成,这时的时间是11.4。第三个调度的是作业3,它运行了1.0后完成,这时的时间是12.4。整个实施过程如下。
    在这里插入图片描述

    展开全文
  • 一、操作系统对进程的管理 1、了解进程 2、操作系统对进程的控制方式 二、进程的状态
  • 操作系统(一):概述、进程与线程、死锁 操作系统(二):内存管理、输入输出系统、磁盘、链接   一、操作系统概述: 操作系统是配置在计算机硬件上的第一层软件,是计算机系统中最基本最重要的系统软件,是对...
  • 进程&线程&死锁

    2016-03-21 21:27:01
    进程&线程&死锁 标签: 任务多线程算法存储windows磁盘 2011-09-22 22:02 2608人阅读 评论(0) 收藏 举报 版权声明:本文为博主原创文章,未经博主允许不得转载。  线程与进程  程序...
  • 一句话总结:父进程创建子进程时,子进程会复制父进程的内存(包括锁状态),需仔细处理。 1、死锁例子 #include #include #include #include pthread_mutex_t mutex = PTHREAD_MUTEX_...
  • 进程,多线程的并发执行虽然提升了系统资源的利用率,提高了系统的性能,但是并发执行也带来了新的问题-----死锁。 死锁是指多个进程(线程)在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象...
  • 关于进程线程和死锁

    2020-08-25 13:09:53
    进程和线程的关系 死锁是什么: 当线程A持有独占锁a,尝试去获取独占锁b,线程B拥有独占锁b,并尝试获取独占锁a,就会发生AB两个线程由于互相持有对方需要的锁,而发生的阻塞现象,我们称为死锁 造成死锁必须达成的...
  • 重学操作系统原理系列 - 进程管理

    万次阅读 2020-06-02 09:14:57
    一、进程 1.1 多道程序设计 允许多个程序同时进入内存并运行,提高CPU的利用率,目的是提高系统效率 a图内存中有四个程序,串行执行,因为这里只有一个程序计数器。 当有了多道程序技术之后就得到...
  • 程序(进程)在cpu中的执行过程

    万次阅读 2020-05-20 22:14:53
    进程 程序 程序编译好后,存于某个地方(外存), 当程序被要求运行时,做的事情如下: 1.把可执行程序相关数据代码等加载到内存的相应段? 2.等待cpu调度到此程序,也即是获取cpu的使用权 3.运行balabala.....
  • 操作系统fork()进程

    万次阅读 多人点赞 2019-03-01 11:57:11
    1、fork()是创建进程函数。 2、c程序一开始,就会产生 一个进程,当这个进程执行到fork()的时候,会创建一个子进程。 3、此时父进程和子进程是共存的,它们俩会一起向下执行c程序的代码。 4、需要注意!!!子...
  • 进程和线程的主要区别(总结)

    万次阅读 多人点赞 2018-06-13 10:11:52
    根本区别:进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位在开销方面:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类...
  • 操作系统——面试知识点精华

    万次阅读 2015-08-19 20:30:53
    僵尸进程和孤儿进程 引用地址:http://www.cnblogs.com/Anker/p/3271773.html 基本概念: 孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程...
  • 根据进程名杀死进程 -kill进程

    万次阅读 2012-06-28 14:17:20
    前两天一个老师给我出了一个linux操作上的问题,现在知道进程名怎样杀死这个进程。或许很多人都会和我一样说用 #pkill 进程名  或是 #killall 进程名 的确这个两个命令都能做到这些,而且我们平时一般知道进程...
  • 实际应用中可能有这样的场景:给定一个进程名称特征串,查找所有匹配该进程名称的进程的详细信息。 解决的办法是: (1) 先用pgrep [str] 命令进行模糊匹配,找到匹配该特征串的进程ID; (2) 其次根据进程ID显示指定...
  • adb命令--之查看进程及Kill进程

    万次阅读 2017-05-10 21:33:47
    Android adb 命令查看程序进程
  • Linux中查看进程状态信息

    万次阅读 2020-03-02 10:06:28
    Linux中查看进程状态信息 一、常用命令总结 ps -l 列出与本次登录有关的进程信息; ps -aux 查询内存中进程信息; ps -aux | grep *** 查询***进程的详细信息; top 查看内存...
  • kill 命令杀死父进程和所有子进程

    万次阅读 2016-02-15 11:39:00
    当一个进程有很多个子进程时: ps -ef | grep nginx 使用kill -TERM 8771 命令可以杀死所有的进程
1 2 3 4 5 ... 20
收藏数 2,213,402
精华内容 885,360
关键字:

进程