L08_CPU管理的直观想法

CPU的工作原理:

  • 取指令
  • 执行指令

因此最直观的想法是,设置好取指指针指向的初值就好了,接下来一步步指向 :::danger 但是这种单线程的操作方式会造成CPU和内存的资源严重浪费 :::

Why采用多线程

不同操作耗时不同,对于CPU而言进行运算的速度是非常快的,但是读写磁盘、IO口输出受限于硬件条件,远远慢于CPU运算

  1. int main(int argc, char* argv[])
  2. {
  3. int i , to, *fp, sum = 0;
  4. to = atoi(argv[1]);
  5. for(i=1; i<=to; i++)
  6. {
  7. sum = sum + i;
  8. fprintf(fp,“%d”, sum);
  9. }
  10. }

:::danger fprintf 和 普通语句 运行时间比5.7 * 10^5 : 1 等fprintf —— 浪费时间 :::

多线程操作

🍚Part_03_多进程图谱 - 图1 :::info 可以有效提高CPU和外设利用率 ::: 在一个程序运行的过程中,修改PC指针,指向另一个待执行的程序;

  • 不仅仅需要修改寄存器PC,还有其他信息需要存储
  • 定制了一种存放信息的结构:Process Control Block(PCB)

image.png

进程的概念

进程是进行(执行)中的程序

  • 进程有开始、有结束,程序没有
  • 进程会走走停停,走停对程序无意义
  • 进程需要记录ax,bx,…,程序不用

    L09_多进程图像

    :::info

  • 用户启动计算机实际上是启动了一个进程

  • 用户管理计算机实际上是管理一堆进程
  • 多个进程的交替是操作系统的核心,交替通过队列操作+调度+切换完成 :::

    进程贯穿计算机工作的全部过程

  • main中的fork()创建了第1个进程

    • init执行了shell(Windows桌面)
  • shell再启动其他进程

    1. int main(int argc, char * argv[]) {
    2. while(1) {
    3. scanf(“%s”, cmd);
    4. if(!fork()) {
    5. exec(cmd);
    6. }
    7. wait();
    8. }

    如何组织多进程

    PCB+状态+队列 :::info

  • 利用PCB来存放进程的寄存器信息,地址信息等

  • 利用状态来区分进程
  • 将PCB组织成一定的数据结构(队列) :::

进程调度的方式比较复杂,常见/基础的有

  • FIFO 先入先出
  • Priority 有优先级的,e.g.,例如重要的任务or快速的任务先进行

    进程的切换过程

  • 先保存当前的PCB

  • 将指针指向下一个PCB

进程间相互影响

内存管理

🍚Part_03_多进程图谱 - 图3

  • 两个进程同时对一个内存地址进行操作,则会出现问题
  • 解决方式:对于不同进程,设定不同的映射表,把给出的地址当作映射表的地址,然后映射到真实的地址中,这样可以使得不同进程所用到的内存分离

image.png

多进程合作

多进程进行合作时,可能会因为进程间的切换而出现错误结果
🍚Part_03_多进程图谱 - 图5
程序本身是想让生产者进行完后,消费者conter才—,但是一种可能的调度会如下所示

  1. P.register = counter;
  2. P.register = P.register + 1;
  3. //
  4. C.register = counter;
  5. C.register = C.register - 1;
  6. // 这时出现错误
  7. counter = P.register;
  8. counter = C.register;

:::info 防止这种情况出现的机制是上锁or同步
🍚Part_03_多进程图谱 - 图6 :::

Summary 如何形成多进程图像

  • 读写PCB,OS中最重要的结构,贯穿始终
  • 要操作寄存器完成切换(L10,L11,L12)
  • 要写调度程序(L13,L14)
  • 要有进程同步与合作(L16,L17)
  • 要有地址映射(L20)