goroutine 相关知识2

os & runtime & 虚拟化

  • app 如何在 os上运行起来?
  • os 如何为 app 提供服务?
  • 哪些是 os 提供?哪些由语言 runtime 提供?

OS

系统调用

除内存/文件/进程/外设管理等内部模块以外,os 还提供许多接口 给应用程序使用,就是所谓的 系统调用

DOS 时代系统调用就通过软中断形式提供,著名的 INT 21

  • 系统功能号送到寄存器 AH
  • 入口參数送到指定的寄存器
  • INT 21H 调用
  • 依据出口參数分析功能调用运行情况

Hello.asm

msg db 'hello world!',0Dh,0Ah,'$'
org 100h
mov dx,msg
mov ah,9
int 21h
mov ah,4Ch
int 21h

int 21H 调用

AH功能入口参数出口参数
4CH返回 DOS
1键盘输入一个字符到ALfqAL=字符
2输出DL寄存器的字符到显示器DL(存一个字符)
9输出一个以$ 结尾的字符串到显示器DS:字符串段地址DX:字符串首地址
0AH从键盘输入一个字符串到指定缓冲区DS:缓冲区段地址DX:缓冲区首地址缓冲区对应位置

D:\dev\c\BuildTools\VC\Tools\MSVC\14.10.25017\bin\HostX64\x64\nasm hello.asm -o hello.com

dosbox-0.74.conf

MOUNT C D:\tmp
set PATH=$PATH$;D:\tmp

x86 ring

通过特权级(privilege level),os和CPU一起合谋限制 用户模式的应用程序

特权级共 4个,0(最高权 控制中断、修改页表、访问设备)到3(最低),x86 只用到 0 和 3

3 种主要资源受到保护:

  • 内存
  • I/O端口
  • 特殊机器指令

任一时刻,CPU 都只在一个特定特权级下运行

用户模式代码不调用内核情况下,几乎不能与外部世界交互(不能打开文件,发网络数据包,屏幕打印、分配内存)

要做受控操作(访问磁盘,写文件 ...)就要 系统调用(函数)

CPU 运行级别从 ring3 到 ring0 切换,并跳到OS对应的内核代码位置执行,这样内核就为你完成了设备访问,完成之后再从 ring0 返回 ring3( 用户态和内核态的切换 )


一个进程泄漏的内存会在进程结束后被统统回收,打开的文件也会被自动关闭

所有的控制着内存或打开的文件等的数据结构全都不能被用户代码直接使用

Windows 95/98容易死机原因之:

系统一些重要数据结构,出于兼容目的被设计成 可由用户直接访问。当时可能是一个很好的折中,代价也很大


快速系统调用

这做法到奔腾 2(P6) 前都没变,windows 通过 INT 2E、Linux 是 INT 80 提供系统调用,只不过后来的寄存器比以前大一些,可能再多一层跳转表查询

后来 Intel 和 AMD 提供了效率更高的 SYSENTER/SYSEXIT SYSCALL/SYSRET 代替之前中断方式,略过耗时的特权级别检查及寄存器压栈出栈的操作,直接从 RING 3 代码段到 RING 0 代码段的转换

通过引入新的寄存器组 (Model-Specific Register(MSR)) 存放所需信息,进而实现快速跳转


系统调用就是 os 和 app 之间沟通的协议,超出此协议的功能,需 app 去实现

举例

  • 内存管理

os 只提供进程级别的内存段的管理

  • Windows virtualmemory 系列
  • Linux 的 brk

os 不在乎应用如何为新建对象分配内存,或 gc,这些都需要 app 自己去实现

如果超出此协议的功能无法自己实现,那就说该操作系统不支持该功能

例 Linux 2.6 前不支持多线程,无论如何在程序里模拟,都无法做出多个可以同时运行的并符合 POSIX 1003.1c 语义标准的调度单元

运行时

可是我们写程序并不需要调中断或SYSCALL,os提供了一层封装

  • Windows

NTDLL.DLL(常说的Native API)

不但不需要直接调INT 2E 或 SYSCALL,准确的说是不能直接去调用,因为Windows并没有公开其调用规范,直接去调用无法保证未来的兼容性

  • Linux

没此问题,系统调用列表都公开(400个左右),且Linus非常看重兼容性,不会去做任何更改,glibc 里甚至专门提供了syscall来方便用户直接用编号调用

Linux上还是对部分系统调用做一层封装,VDSO (早期叫linux-gate.so)

  • 解决glibc和内核间不同版本兼容性
  • 提高某些调用效率(如__NR_ gettimeofday)

可是我们写程序也很少直接调用NTDLL或者VDSO,而是通过更上一层的封装

这一层处理了参数准备和返回值格式转换、以及出错处理和错误代码转换,这就是我们所使用语言的 运行库

  • C 语言,Linux 上是 glibc,Windows 上是 kernel32(或调用msvcrt)
  • Java 是 JRE,这些 “其他语言” 的运行库通常最终还是调用glibc或kernel32
  • .NET 是 CLR

“运行库” 其实不止包括用于和编译后的目标执行程序进行链接的库文件,也包括了脚本语言或字节码解释型语言的运行环境

运行时功能

  • 系统调用的封装
  • 不需要操作系统支持的功能
  • 操作系统支持的功能提供更易用更高级的封装

不需要操作系统支持的功能

  • 字符串处理
  • 数学计算
  • 常用数据结构容器等

易用高级封装例

  • 带缓存和格式的IO
  • 线程池等

所以说“某某语言新增了某某功能”的时候,通常是这么几种可能:

  • 支持新的语义/语法,便于描述和解决问题。如Java泛型、Annotation、lambda
  • 提供了新工具或类库,减少了们开发代码量。如Python 2.7 argparse
  • 对系统调用有了更良好更全面的封装,做到以前在这个语言环境里做不到或很难做到的事情。如Java NIO

Go提供了更方便更清晰的语义和支持,提高了开发的效率

虚拟化

虚拟化难题

vmware/virtualbox的宿主系统叫 hostos,里面跑的系统叫guest os

host os工作在ring0,guest os就不能也在ring0了,但是它不知道这一点

以前执行什么指令,现在还是执行什么指令,没权限啊,玩不转!

虚拟机管理程序(VMM)

VMM 在ring0上,一般以驱动程序的形式体现(得驱动的了设备)

guest os 执行特权指令时,会触发异常(CPU机制,没权限的指令,触发异常),VMM捕获,在异常里面做翻译,模拟,返回到guest os 内,guest os 认为自己的特权指令工作正常,继续运行

但这个性能损耗非常的大,原来简单的一条指令,却要通过复杂的异常处理过程

  • 半虚拟化

让guest os 知道自己是在虚拟机上跑的,工作在非ring0状态,它原先在物理机上执行的一些特权指令,就会修改成其他方式,这种方式是可以和VMM约定好的

相当于通过改代码把os移植到一种新的架构上来

像XEN这种半虚拟化技术,guest os都是有一个专门的定制内核版本,和x86、mips、arm这些内核版本等价

就不会有捕获异常、翻译、模拟的过程了,性能损耗非常低

这也是为什么XEN只支持虚拟化Linux,无法虚拟化windows原因,微软不改代码啊

  • 硬件辅助的全虚拟化

CPU 厂商开始支持虚拟化

Intel-VT 技术,VMX root operation 和 VMX non-root operation两种模式,都支持Ring 0 ~ Ring 3

VMM运行在VMX root operation下,guest OS运行在VMX non-root operation

全虚拟化不需要修改guest os

现在XEN也支持硬件辅助的全虚拟化

KVM、VMARE这些一直都是全虚拟化

转载于:https://my.oschina.net/zhangthe9/blog/3021324

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
作为Go语言初学者,以下是一些重要的知识点和建议,可以帮助你开始学习和使用Go语言: 1. 安装和设置Go环境:首先,确保在计算机上安装了Go语言的最新版本,并设置好相关的环境变量。可以从官方网站(https://golang.org)下载安装程序并按照说明进行安装。 2. 了解基本语法和数据类型:学习Go语言的基本语法,包括变量声明、函数定义、条件语句、循环语句等。掌握Go语言的基本数据类型,如整型、浮点型、字符串、布尔型等。 3. 学习函数和包:函数是Go语言的基本构建块之一。了解如何定义和调用函数,并理解函数的参数和返回值。此外,了解如何使用包(package)来组织和重用代码。 4. 并发编程:Go语言内置了强大的并发编程支持。学习使用goroutine和channel进行并发编程,以实现高效的并发处理和协作。 5. 错误处理:Go语言鼓励使用显式的错误处理机制。学习使用错误类型和错误处理函数来处理可能发生的错误,并避免潜在的错误。 6. 标准库和第三方库:探索Go语言的标准库,了解如何使用其中的功能和工具。此外,也要了解常用的第三方库,它们提供了许多有用的功能和工具,可以加快开发速度。 7. 学习常用的工具和技术:Go语言有许多强大的工具和技术可用于开发。学习使用Go工具链(如go build、go run、go test等),以及版本管理工具(如git)和构建工具(如Makefile)等。 8. 实践和项目:通过实践和参与项目,将所学的知识应用到实际中。可以尝试解决一些小型的编程问题,或者参与开源项目,以提高自己的编程能力和经验。 9. 阅读文档和教程:Go语言有丰富的文档和教程资源可供学习。阅读官方文档、博客文章、书籍和在线教程,可以帮助你更深入地理解和掌握Go语言的知识和技巧。 10. 加入社区和交流:加入Go语言的社区,与其他开发者交流和分享经验。参加本地的Go语言用户组、在线论坛或社交媒体群组,可以获取更多资源、解答问题,并与其他Go开发者建立联系。 记住,持续学习和实践是掌握任何编程语言的关键。通过不断地编写代码、阅读文档和参与项目,你将逐渐掌握和提高Go语言的技能。祝你在学习Go语言的过程中取得成功!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值