目录
可移植操作系统接口(英语:Portable Operating System Interface,缩写为POSIX)。
POSIX是为要在各种UNIX操作系统上运行软件,而定义的一系列互相关联的OS API标准的总称。
发布者为电气与电子工程师协会(Institute of Electrical and Electronics Engineers),简称IEEE。这个协会老牛了【该组织在太空、计算机、电信、生物医学、电力及消费性电子产品等领域中都是主要的权威】!
其正式称呼为IEEE Std 1003,而国际标准名称为ISO/IEC 9945。此标准源于一个大约开始于1985年的项目。POSIX这个名称是由理查德·斯托曼(RMS)应IEEE的要求而提议的一个易于记忆的名称。它基本上是Portable Operating System Interface(可移植操作系统接口)的缩写,而X则表明其对Unix API的传承。
IEEE,总部位于美国纽约,是一个国际性的电子技术与信息科学工程师的协会,也是目前全球最大的非营利性专业技术学会。IEEE致力于电气、电子、计算机工程和与科学有关的领域的开发和研究,在太空、计算机、电信、生物医学、电力及消费性电子产品等领域已制定了1300多个行业标准,现已发展成为具有较大影响力的国际学术组织
标准线上地址: http://www.unix.org/version3/online.html 注册后可以在线阅读或者下载。
POSIX是Unix的标准。
1974年,贝尔实验室正式对外发布Unix。因为涉及到反垄断等各种原因,加上早期的Unix不够完善,于是贝尔实验室以慷慨的条件向学校提供源代码,所以Unix在大专院校里获得了很多支持并得以持续发展。
于是出现了好些独立开发的与Unix基本兼容但又不完全兼容的OS,通称Unix-like OS。
包括:

20世纪80年代中期,Unix厂商试图通过加入新的、往往不兼容的特性来使它们的程序与众不同。
局面非常混乱,麻烦也就随之而来了。
为了提高兼容性和应用程序的可移植性,阻止这种趋势, IEEE(电气和电子工程师协会)开始努力标准化Unix的开发,后来由 Richard Stallman命名为“Posix”。
这套标准涵盖了很多方面,比如Unix系统调用的C语言接口、shell程序和工具、线程及网络编程。
有了这个规范,你就可以调用通用的API了,Linux提供的POSIX系统调用在Unix上也能执行,因此学习Linux的底层接口最好就是理解POSIX标准。
首先就是大名鼎鼎的Unix和Linux了,除此之外还有苹果的操作系统也是Unix-based的。
Windows从WinNT开始就有兼容POSIX的考虑。这是因为当年在要求严格的领域,Unix地位比Windows高。为了把Unix用户拉到Windows阵营,被迫支持POSIX。现在Win10对 Linux/POSIX 支持好。

Linux下提供两种方式支持可移植性:
系统调用(system call)和库函数调用(Library functions)。
(1)系统调用
系统调用是通向操作系统本身的接口,是面向底层硬件的。
通过系统调用,可以使得用户态运行的进程与硬件设备(如CPU、磁盘、打印机等)进行交互,是操作系统留给应用程序的一个接口。
(2)库函数(符合POSIX标准)
库函数(Library function)是把函数放到库里,供别人使用的一种方式。
方法是把一些常用到的函数编完放到一个文件里,供不同的人进行调用。一般放在.lib文件中。
库函数调用则是面向应用开发的,库函数可分为两类,
(由于版权原因,库函数的源代码一般是不可见的,但在头文件中你可以看到它对外的接口)。
glibc 是 Linux 下使用的开源的标准 C 库,它是 GNU 发布的 libc 库,即运行时库。这些基本函数都是被标准化了的,而且这些函数通常都是用汇编直接实现的。
glibc 为程序员提供丰富的 API(Application Programming Interface),这些API都是遵循POSIX标准的,API的函数名,返回值,参数类型等都必须按照POSIX标准来定义。
POSIX兼容也就指定这些接口函数兼容,但是并不管API具体如何实现。
2.2 系统调用与库函数的关系


如上图所示:

那么目标代码和启动代码是怎么生成的呢? 答案是编译器。
编程语言编写的程序首先要被编译器编译成目标代码(0、1代码),然后在目标代码的前面插入启动代码,最终生成了一个完整的程序。
要注意的是,程序中为访问特定设备(如显示器)或者操作系统(如windows xp 的API)的特殊功能而专门编写的部分通常是不能移植的。
综上所述,一个编程语言的可移植性取决于
移植是基于操作系统的。
(1)二进制代码:
我们需要注意一点:基于各种操作系统平台不同,应用程序在二进制代码级别是不能直接移植的。
(2)OS API源代码
我们只能在源代码层去思考可移植问题,在API层面上由于各个操作系统的命名规范、系统调用等自身原因,在OS API层面上实现可移植也是不大可能的。
(3)C语言函数库
在各个平台下,我们默认C标准库中的函数都是一样的,这样基本可以实现可移植。
但是对于C库本身而言,在各种操作系统平台下其内部实现是完全不同的,也就是说C库封装了操作系统API在其内部的实现细节。
因此,C语言提供了我们在代码级的可移植性,即这种可移植是通过C语言这个中间层来完成的。
例如在我们的代码中下功夫。以下代码可以帮助我们实现各平台之间的可移植:
- #ifdef _WINDOWS_
- CreateThread(); //windows下线程的创建
- #else
- Pthread_create(); //Linux下线程的创建
- #endif
对于头文件,也使用同样的预编译宏来实现。如:
- #ifndef _WINDOWS_
- #include
- #else
- #include
- #endif
这样就可以实现代码的可移植了。在编译的时候只要通过#define就可以选择在那个平台下完成程序的编译。有c语言库实现对不同操作系统平台的屏蔽。
综上所述,我们都是将C,C++等各种语言库当作中间层,以实现其一定程度上的可移植。如今,语言的跨平台的程序都是以这样的方式实现的。但是在不同的平台下,仍需要重新编译。
如下图是Linux系统调用的大概流程。
当应用程序调用printf()函数时,printf函数会调用C库中的printf,继而调用C库中的write,C库最后调用内核的write()。
而另一些则不会使用系统调用,比如strlen, strcat, memcpy等。

printf函数执行过程中,程序运行状态切换如下:
用户态–>系统调用–>内核态–>返回用户态
printf函数、glibc库和系统调用在系统中关系图如下:

glibc和libc都是Linux下的C函数库:
libc是Linux下的ANSI C函数库,
glibc是Linux下的GUN C函数库。
glibc是遵循POSIX标准的C语言函数库,因此,我们可以通过glibc来理解POSIX接口的主要功能。
glibc是GNU发布的libc库,即c运行库。glibc是linux系统中最底层的api,几乎其它任何运行库都会依赖于glibc。
glibc除了封装linux操作系统所提供的系统服务外,它本身也提供了许多其它一些必要其他功能服务的实现。
由于glibc囊括了几乎所有的 UNIX 通行的标准,可以想见其内容包罗万象。
glibc是一种按照LGPL许可协议发布的,自由的,公开源代码的,方便从网络下载的C的编译程序。GNU C运行期库,是一种C函数库,是程序运行时使用到的一些API集合,它们一般是已预先编译好,以二进制代码形式存在Linux类系统中,GNU C运行期库通常作为GNU C编译程序的一个部分发布。
glibc最初是自由软件基金会(FSF)为其GNU操作系统所写,但当前最主要的应用是配合Linux内核,成为GNU/Linux操作系统一个重要的组成部分。
(1)基本计算
(2)网络与文件
(3)POSIX标准定义的XSI扩展头文件(26项)
(4)POSIX标准定义的可选头文件(8项)