0%

《操作系统》Posix标准

Posix介绍

POSIX表示可移植操作系统接口(Portable Operating System Interface of UNIX,缩写为 POSIX ),POSIX标准定义了操作系统应该为应用程序提供的接口标准,是IEEE为要在各种UNIX操作系统上运行的软件而定义的一系列API标准的总称,其正式称呼为IEEE 1003,而国际标准名称为ISO/IEC 9945。

POSIX标准意在期望获得源代码级别的软件可移植性。换句话说,为一个POSIX兼容的操作系统编写的程序,应该可以在任何其它的POSIX操作系统(即使是来自另一个厂商)上编译执行。

Posix定义了一堆头文件,各大操作系统按照头文件中的声明去实现这些函数,从而达到C标准库的统一

Posix标准的来由

C语言诞生之后,操作系统百花齐放,各自有各自的实现特点,使用C语言编写程序的人越来越多

一开始基本都是直接通过系统调用来实现想要的功能,后来发现每个程序都有好多一样的代码,比如堆的初始化,每个程序启动时都要做这个事情

于是出现了C运行时,专门把每个程序必须做的事情放到一起形成一个包,起初只是代码放在一起形成一个包,后来出现了静态库的机制

就将C运行时打包成了静态库,链接器在链接的时候自动将运行时链接进去

于是各大操作系统纷纷被实现了适用于自己的C运行时(运行时中大量使用系统调用,所以C运行时的实现代码必定不一样)

这时,开发者已经不需要关注堆的初始化等等事情了,而专注于开发业务功能,负担减轻了很多

但是由于系统调用的差异,在Linux上实现的功能,比如写文件,在Windows上代码无法编译或者编译了运行报错。代码不可移植

这时候就有人想到了提供一个抽象层,将各大平台系统调用进行封装,屏蔽掉各大平台的差异。这个抽象层就是C标准库

各大平台上都实现一个统一接口的抽象层,那么基于抽象层实现的程序就可以在各大平台上做代码移植了

为了统一抽象层,Posix出现了,定义了统一接口,各大平台抽象层的实现应当遵守这个标准

Posix标准除了定义了C标准库以外,还定义了shell程序和工具、线程和网络编程等等内容

Linux出现了Glibc,Windows出现了MSVC CRT。动态库的机制出现后,他们也被编译成了动态库放到了各自的操作系统中提供运行环境

Posix为什么不统一系统调用号

Posix标准并没有规定所有操作系统采用一样的系统调用号,这样的话,就算规定了,恐怕也无法遵守,因为Posix出来前很多操作系统的系统调用号已经规定好了,已经形成了生态,改了的话等于自杀

所以目前各大操作系统对于同一个功能的系统调用号基本都不一样,甚至同一个操作系统在不同cpu架构下的系统调用号也不一样

cpu也是不断升级的,可能某个系统调用的功能arm cpu无法实现,而英特尔cpu却可以实现,于是安排调用号3,而arm cpu中调用号3给另一个功能了,所以cpu架构也会影响系统调用的一致性

假如Posix标准在所有操作系统出现之前就已经出现了,那么大可以规定所有的功能以及系统调用号,cpu实现不了的,那么系统调用号就空着

这样的话Posix就无需定义一堆头文件让各个操作系统去实现它了,因为已经从系统调用的更深层次进行统一了

那么直接通过系统调用编写的程序也可以具有代码层面的高可移植性了

Golang为什么不使用Posix接口

熟悉Golang运行时的朋友应该清楚,其中使用了大量的系统调用,因为系统调用的差异性,Golang运行时不得不针对各个操作系统以及各个cpu架构去单独实现系统调用,这就大大增加了Golang运行时的复杂度

为什么 Golang运行时 不调用Posix接口而选择使用系统调用呢,这样就不用这么大工作量了?

是的,如果使用Posix接口,运行时确实会瘦身很多,但是如何使用呢。只能使用cgo了,Posix接口标准是针对C运行库的,操作系统对Posix的实现都是C的实现,最后编译成C的静态库或者动态库提供给开发者调用

cgo对性能影响非常大

C需要Posix标准来做约束,Golang为什么不需要呢?

因为C语言的抽象层不是一个团队在做,而是多个团队在做自己平台的抽象层,这样的话如果没有一个约束,他们实现的就不一样,没有提供可移植性的意义

而Golang则是一个团队在做,各个平台的抽象层甚至放在了一个repo中,完全不必担心各个平台的实现不一致

假如另一个团队针对Linux又实现了一个不一样的Golang标准库(通过使用系统调用完全可以做到),那恐怕是没有人会使用这个库了,因为这不是官方团队做的

Golang团队目前已经实现了抽象层编译成各大平台的静态库,但是动态库只支持linux_amd64

Golang团队正在努力实现各大平台的动态库

可以看看这篇文章:《十万个为什么》Go可执行文件为什么这么大

Golang、Glibc支持的平台

注意:平台包含了操作系统以及CPU架构

Golang Glibc
linux/arm linux/arm
linux/arm64 linux/aarch64
linux/riscv64 linux/riscv/rv64
linux/386 linux/i386
linux/amd64 linux/x86_64/64
linux/s390x linux/s390/s390-32或linux/s390/s390-64
linux/mips linux/mips/mips32
linux/mips64 linux/mips/mips64
linux/mipsle
linux/mips64le
linux/ppc64 linux/powerpc/powerpc64
linux/ppc64le
darwin/386
darwin/amd64
darwin/arm
darwin/arm64
dragonfly/amd64
freebsd/386
freebsd/amd64
freebsd/arm
freebsd/arm64
netbsd/386
netbsd/amd64
netbsd/arm
netbsd/arm64
openbsd/386
openbsd/amd64
openbsd/arm
openbsd/arm64
plan9
solaris/amd64
windows/386
windows/amd64

参考文档

Posix内容

所有Posix接口




微信关注我,及时接收最新技术文章