用状态机的视角思考

74 阅读2分钟

状态机这个想法来自jyy(ics.nju.edu.cn/~jyy/)

我们使用Java这种面向对象(更好的组织,维护代码)的编程语言来描述现实生活中存在的状态

class Person {
    private int age;
}

image.png

使用Java描述的状态机,包含一个名称为age的属性

JVM又维护着这个状态机

image-1.png

同时JVM也是一个状态机,被操作系统抽象为进程的方式管理着

现代操作系统需要运行各种各样的程序。为了管理这些程序的运行,操作系统提出了进程的抽象:每个进程都对应了一个运行中的程序。有了进程的抽象,应用程序在运行时仿佛独占了整个cpu(现代操作系统:原理与实现第五章76页)

image-2.png

Java中使用age++修改状态,此时使用Java描述的状态机发生了改变

class Person {
    private int age;

    public void configAge() {
        age++;
    }
}

此时JVM做了什么呢?因为JVM是无法直接读懂我们写的代码,所以我们需要使用JDK提供的工具javac将代码编译为byte code

class Person {
  private int age;

  Person();
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return


  public void configAge();
       0: aload_0
       1: dup
       2: getfield      #2                  // Field age:I
       5: iconst_1
       6: iadd
       7: putfield      #2                  // Field age:I
      10: return

}

JVM解释,执行指令相对应的行为,而这个行为在JVM中被CPP描述了,而CPP描述的这个行为又会被编译器(clang/gcc)编译为当前CPU可以读懂的汇编代码(x86/asm),且符合当前OS规定的文件类型(linux: elf

push    rbp
mov     rbp, rsp
mov     DWORD PTR [rbp-4], edi
add     DWORD PTR [rbp-4], 1

那此时OS呢?CPU作为一个通电后不断取指 -> 译码 -> 执行的机器,代码最终被CPU执行,OS要做的就是按照的CPU手册所描述的行为,为每个进程维护一组寄存器的状态。

pushq	%rbp
pushq	%rbx
pushq	%r12
pushq	%r13
pushq	%r14
pushq	%r15

/* switch stack */
movq	%rsp, TASK_threadsp(%rdi)
movq	TASK_threadsp(%rsi), %rsp

#ifdef CONFIG_STACKPROTECTOR
	movq	TASK_stack_canary(%rsi), %rbx
	movq	%rbx, PER_CPU_VAR(fixed_percpu_data) + FIXED_stack_canary
#endif

/* restore callee-saved registers */
popq	%r15
popq	%r14
popq	%r13
popq	%r12
popq	%rbx
popq	%rbp

context switch