zoukankan      html  css  js  c++  java
  • 进程基础

    什么是进程?

    进程的概念:程序的一个执行实例,正在执行的程序。简单来说,比如你打开了一个APP这就是一个进程,在Linux系统下,在命令行一个ls的命令也是一个进程。从内核的角度来说,进程是担当分配系统资源(CPU时间,内存)的实体。

    怎么描述进程

    进程的所有信息都放在一个叫做进程控制块的数据结构中,称它为PCB。Linux操作系统下的PCB称为task_struct。
    每一个进程都有一个task_struct,这个结构体用来描述一个进程,里面存放着进程的各种信息。进程的PCB用一个双向链表连接,当有进程创建,就在链表上添加一个task_struct,同样当一个进程销毁,就删除一个task_struct。那task_struct中的的具体内容又都包含哪些呢?

    task_struct

    1. 标识符:用来描述进程,每一个进程都有一个唯一的标识符,进程pid;
    2. 状态:任务状态,退出代码,退出信号等。
    3. 优先级:这么多进程,系统怎么知道先执行哪一个呢?所以当然要有优先级了,就是当前进程相对与其它进程的优先级。
    4. 程序计数器:程序中即将被执行的下一条指令的地址。
    5. 内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。
    6. 上下文数据:进程执行时处理器的寄存器中的数据。
    7. I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的 。
    8. 记账信息:包括处理器时间的总和,使用得时钟数总和,时间限制,记账号等。

    进程调度算法

    1. 时间片轮转调度算法(RR):给每个进程固定的执行时间,根据进程到达的先后顺序让进程在单位时间片内执行,执行完成后便调度下一个进程执行,时间片轮转调度不考虑进程等待时间和执行时间,属于抢占式调度。优点是兼顾长短作业;缺点是平均等待时间较长,上下文切换较费时。适用于分时系统。
    2. 先来先服务调度算法(FCFS):根据进程到达的先后顺序执行进程,不考虑等待时间和执行时间,会产生饥饿现象。属于非抢占式调度,优点是公平,实现简单;缺点是不利于短作业。
    3. 优先级调度算法(HPF):在进程等待队列中选择优先级最高的来执行。
    4. 多级反馈队列调度算法:将时间片轮转与优先级调度相结合,把进程按优先级分成不同的队列,先按优先级调度,优先级相同的,按时间片轮转。优点是兼顾长短作业,有较好的响应时间,可行性强,适用于各种作业环境。
    5. 高响应比优先调度算法:根据“响应比=(进程执行时间+进程等待时间)/ 进程执行时间”这个公式得到的响应比来进行调度。高响应比优先算法在等待时间相同的情况下,作业执行的时间越短,响应比越高,满足段任务优先,同时响应比会随着等待时间增加而变大,优先级会提高,能够避免饥饿现象。优点是兼顾长短作业,缺点是计算响应比开销大,适用于批处理系统。

    进程状态

    如字面意思,就是进程的某种状态,我们要想了解进程就要知道进程的不同状态。
    进程有五种状态:R,S,D,T,t,X,Z,下面具体介绍
    1. R运行状态(Running):运行状态不一定就是在运行中,也有可能是在运行队列里。
    2. S睡眠状态(Sleeping):进程正在等待事件的完成。也叫做可中断睡眠(interruptible sleep)。也就是说睡面可以在某些特定的情况下终止。
    3. D磁盘休眠状态(Disk sleep):有时候也叫做不可中断睡眠状态(uninterruptible sleep),在这个状态下的进程通常都会等待I/O的结束
    4. T停止状态(stopped):可以通过发送SIGSTOP信号给进程来停止T进程。这个被暂停的进程可以通过发送SIGCONT信号让进程继续执行。
    5. X死亡状态(dead):这是 内核运行里的do_exit()函数返回的状态。这个状态只是一个返回状态,你不在任务列表里面看到这个状态。

    僵尸进程(Zombies)

    僵死状态:这是一个人比较特殊的状态。当进程退出并且父进程(使用wait()系统调用)没有读取到子进程退出的返回代码时就会产生僵(死)尸进程。僵尸进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。所以,你想如果有很多很多僵尸进程的话,那也就意味着这些进程都会一直占用着内存。必定会导致内存泄漏了。所以说只要子进程退出,父进程还在运行,但是父进程没有读取子进程的状态,那么子进程将会进入Z状态。
    下面简单实现一下僵尸进程

       #include<stdio.h>
       #include<unistd.h>
       #include<stdlib.h>
       #include<errno.h>
       int main()
      {
          pid_t pid = getpid();
          pid_t id = fork();
           if(id<0)
          {
              perror("fork");
              return -1;
          }
          else if(id>0)
          {//father
              printf("father pid is:%d,return pid is:%d
    ",getpid(),id);
              sleep(10);
          }
          else if(id==0)
          {                                                                                                                             
              printf("child pid is:%d
    ",getpid());
              exit(3);//子进程退出
          }
      }
    

    运行结果如下图
    这里写图片描述
    我们知道进程是由PCB维护的,那如果Z状态一直不退出,PCB一直都要维护。那如果父进程创建了很多个子进程,就是不回收,就会造成资源的浪费。因为数据结构要占用内存。那么该如何避免呢?
    解决僵尸进程

    孤儿进程

    父进程提前退出,子进程就被称为“孤儿进程”。孤儿进程被1号进程领养。父亲不管儿子了,儿子当然就编程孤儿了啊。
    代码实现如下:

     #include<stdio.h>
     #include<unistd.h>
     #include<stdlib.h>
     #include<errno.h>
     int main()
     {                                                                                                                                 
         pid_t ret = fork();
         if(ret<0)
         {
            perror("fork");
            return -1;
         }
         if(ret==0)
         {
           printf("child pid is %d
    ",getpid());
           sleep(10);
         }
         if(ret>0)
         {
             printf("father is %d
    ",getpid());
             sleep(5);
             exit(0);
         }
      }
    

    运行结果如下
    这里写图片描述

  • 相关阅读:
    scoped中预处理器的解析问题
    uni-app中IOS离线打包报HBuilder has conflicting provisioning settings
    js 四则运算
    Chrome 的更改可能会破坏您的应用:为同网站 Cookie 更新做好准备
    银行数据仓库体系实践(20)--浅谈银行数据仓库发展趋势
    数据仓库十大主题;TeraData金融数据模型
    Linux环境下SVN的安装,创建用户以及对应用户的权限设置
    银行数据仓库体系实践(19)--数据应用之AI
    from flask.ext.wtf import Form提示No module named 'flask.ext'
    flask学习笔记2 路由
  • 原文地址:https://www.cnblogs.com/chan0311/p/9427320.html
Copyright © 2011-2022 走看看