Linux开发者越来越多,并且一直有好多人整不明白POSIX是哪些。本文就带着你们来了解一下究竟哪些是POSIX,了解他的历史和重要性。
一、什么是posix?1.概念
POSIX:可移植操作系统插口(PortableOperatingSystemInterfaceofUNIX,简写为POSIX),
2.发布者-IEEE
发布者为电气与电子工程师商会(InstituteofElectricalandElectronicsEngineers),简称IEEE。这个商会老牛了【该组织在太空、计算机、电信、生物医学、电力及消费性电子产品等领域中都是主要的权威】!
POSIX是IEEE为要在各类UNIX操作系统上运行的软件而定义的一系列API标准的统称,其即将尊称为IEEE1003,而国际标准名称为ISO/IEC9945。
POSIX.1早已被国际标准化组织(InternationalStandardsOrganization,ISO)所接受,被命名为ISO/IEC9945-1:1990标准。
IEEE,总部坐落加拿大多伦多,是一个国际性的电子技术与信息科学工程师的商会,也是目前全球最大的非营利性专业技术学会。IEEE旨在于电气、电子、计算机工程和与科学有关的领域的开发和研究,在太空、计算机、电信、生物医学、电力及消费性电子产品等领域已拟定了1300多个行业标准,现已发展成为具有较大影响力的国际学术组织
3.POSIX标准下载
主页:
好多人据说了POSIX标准,但标准具体长哪些样,在那里下载到,则不清楚。如今我开放下来,供相关人员使用。
SingleUNIXSpecificationV3,IEEEStd1003.1,2004Edition
标准线上地址:注册后可以在线阅读或则下载。
IEEE和OpenGroup的POSIX认证:
相关页面:
二、POSIX历史1.起源
POSIX是Unix的标准。
1974年,贝尔实验室即将对外发布Unix。由于涉及到反垄断等各类诱因,加上初期的Unix不够健全,于是贝尔实验室以慷慨的条件向校区提供源代码,所以Unix在本科高校里获得了好多支持并得以持续发展。
于是出现了好些独立开发的与Unix基本兼容但又不完全兼容的OS,通称Unix-likeOS。
包括:
日本加洲学院伯克利校区的Unix4.xBSD(BerkeleySoftwareDistribution)。贝尔实验室发布的自己的版本,称为SystemVUnix。其他厂商的版本,例如SunMicrosystems的Solaris系统,则是从这种原始的BSD和SystemV版本中衍生而至。
20世纪80年代中期,Unix厂商企图通过加入新的、往往不兼容的特点来使它们的程序与众不同。
局面十分混乱,麻烦也就急剧而至了。
为了提升兼容性和应用程序的可移植性,制止这些趋势,IEEE(电气和电子工程师商会)开始努力标准化Unix的开发,后来由RichardStallman命名为“Posix”。
这套标准囊括了好多方面,例如Unix系统调用的C语言插口、shell程序和工具、线程及网路编程。
2.谁遵守这个标准呢?
首先就是大名鼎鼎的Unix和Linux了,
除此之外还有苹果的操作系统也是Unix-based的。
有了这个规范,你就可以调用通用的API了,Linux提供的POSIX系统调用在Unix上也能执行,因而学习Linux的底层插口最好就是理解POSIX标准。
Windows从WinNT开始就有兼容POSIX的考虑。这是由于当初在要求严格的领域,Unix地位比Windows高。为了把Unix用户拉到Windows阵营,被迫支持POSIX。
如今Win10对Linux/POSIX支持好,则是由于Linux早已统治了廉价服务器市场。为了提升Windows的竞争力搞的。
所以一切都是以市场为主导。
3.支持POSIX-Linux成功的最重要一个诱因
Linux之所以才能成功,有好多诱因,并且支持POSIX标准无疑是它才能快速发展的最重要的一个诱因。
POSIX标准的制订最后投票敲定阶段大约是1991~1993年间,而此时正是Linux刚才起步的时侯,这个UNIX标准为Linux提供了极为重要的信息,致使Linux才能在标准的指导下进行开发,并才能与绝大多数UNIX操作系统兼容。
在最初的Linux内核源码(0.01版、0.11版)中就早已为Linux系统与POSIX标准的兼容做好了打算工作。
在Linux0.01版内核/include/unistd.h文件中就早已定义了几个有关POSIX标准要求的符号常数,并且Linus在注释中已写道:“OK,这似乎是个玩笑,但我正在着手研究它呢”。
正是因为Linux支持POSIX标准,无数可以在unix上运行的程序都相继的移植到Linux上,而此时unix由于版权问题,官司打的不可开交,致使Linux后来者居上。
时也命也!
下边是祖师爷Linus当初申请POSIX标准的短信:
来自:torvalds@klaava.Helsinki.Fi(林纳斯·托瓦兹)
讨论组:comp.os.minix
主题:Gcc-1.40和一个有关POSIX的问题
信息名称: 1991 Jul 3, 100050.9886@klaava.Helsinki.Fi
日期: 1991年7月3日, 格林威治时间10: 00: 50
各位网友好!
由于我现在正在MINIX系统下做一个项目, 对POSIX标准很感兴趣。 有谁能向我提供
一个(最好) 是机器可读形式的最新的POSIX规则? 能有FTP地址就更好了。
而Linus也在《只是为了好玩》中述说了POSIX的重要性:
POSIX标准是一个可以适用于数以百计的UNIX系统呼叫中的任意一个的一套冗长规则, 计算机要执行任务(从读、 写、 开机和关机开始) 就需要这个标准。
POSIX则是指一个UNIX的标准体系, 或一个由来自不同公司的代表所组成的一个组织, 希望按照一个共同的标准进行运作。 对于程序员开发的在该操作系统下的新应用软件或开发应用软件的新版本而言, 标准是极其重要的。 从POSIX这样的系统呼叫(system call) , 尤其是重要的呼叫(call) 中, 我可以获得一个操作系统应该具有哪些功能的一个单子; 然后我就可以通过自己的方式在自己的系统中实现每一个功能。 通过编写出这些标准, 我的系统软件的源代码将可以被别人使用, 以开发新的应用软件。
当时我并不知道我本可以直接从POSIX公司买到这些规则的软盘, 但这无所谓。 哪怕我能买得起, 什么东西运到芬兰, 往往会需要很长的时间。 我不愿等上那么久, 因此我四处搜求一个能从FTP地址上直接下载的版本。
没有人给我提供能找到POSI标准的来源。 于是我开始了计划B。
我从学校找到运行sun器(sun server)的sun微系统版的UNIX手册。 该手册中有一个完全可以凑合使用的系统呼叫的基本版本。 从用户手册中能看出系统呼叫的主要功能, 以及为完成这些功能所需要完成的步骤。 但是, 从中看不出具体的方法, 而只是标明了最终的结果。 于是我便着手从安德鲁·塔南鲍姆的书中和别的材料中收集一些系统呼叫。
最终有人给我寄来了那几卷厚厚的POSIX标准。
相关视频推荐
tcp/ip合同栈与网路API的关联
5个方面剖析linux内核构架,让你对内核不再陌生
C++后台开发进阶必读合辑,全网最详尽讲解前端开发技术
学习地址:c/c++linux服务器开发/后台构架师
须要C/C++Linux服务器构架师学习资料加qun812855908获取(资料包括C/C++linux 安装,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,解释器,DPDK,ffmpeg等)linux操作系统界面,免费分享
三、可移植性
聊到POSIX,那我们就不得不谈谈究竟哪些是可移植性,在讲可移植性之前,我们先来了解库函数和系统调用的区别。
Linux下对文件操作有两种形式:系统调用(systemcall)和库函数调用(Libraryfunctions)。
1.系统调用
系统调用是通向操作系统本身的插口,是面向底层硬件的。通过系统调用,可以促使用户态运行的进程与硬件设备(如CPU、磁盘、打印机等)进行交互,是操作系统留给应用程序的一个插口。
2.库函数
库函数(Libraryfunction)是把函数放在库里,供他人使用的一种方法。
方式是把一些常用到的函数编完放在一个文件里,供不同的人进行调用。通常置于.lib文件中。
库函数调用则是面向应用开发的,库函数可分为两类,
一类是C语言标准规定的库函数,一类是编译器特定的库函数。
(因为版权缘由,库函数的源代码通常是不可见的,但在头文件中你可以看见它对外的插口)。
glibc是Linux下使用的开源的标准C库,它是GNU发布的libc库,即运行时库。这种基本函数都是被标准化了的,并且这种函数一般都是用汇编直接实现的。
glibc为程序员提供丰富的API(ApplicationProgrammingInterface),这种API都是秉持POSIX标准的,API的函数名,返回值,参数类型等都必须依照POSIX标准来定义。
POSIX兼容也就指定那些插口函数兼容,并且并不管API具体怎么实现。
3.库函数API和系统调用的区别
如上图所示:
系统调用是为了便捷使用操作系统的插口,而库函数则是为了人们编程的便捷。
库函数调用与系统无关,不同的系统,调用库函数,库函数会调用不同的底层函数实现,因而可移植性好。
4.程序的可移植性及其本质
这么目标代码和启动代码是如何生成的呢?答案是编译器。
编程语言编撰的程序首先要被编译器编译成目标代码(0、1代码),之后在目标代码的后面插入启动代码,最终生成了一个完整的程序。
要注意的是,程序中为访问特定设备(如显示器)或则操作系统(如windowsxp的API)的特殊功能而专门编撰的部份一般是不能移植的。
综上所述,一个编程语言的可移植性取决于
不同平台编译器的数目对特殊硬件或操作系统的依赖性
移植是基于操作系统的。并且这个时侯,我们须要注意一点:基于各类操作系统平台不同,应用程序在二级制级别是不能直接移植的。
我们只能在代码层去思索可移植问题,在API层面上因为各个操作系统的命名规范、系统调用等自身缘由,在API层面上实现可移植也是不大可能的。
在各个平台下,我们默认C标准库中的函数都是一样的unix操作系统免费下载,这样基本可以实现可移植。并且对于C库本身而言,在各类操作系统平台下其内部实现是完全不同的,也就是说C库封装了操作系统API在其内部的实现细节。
因而,C语言提供了我们在代码级的可移植性,即这些可移植是通过C语言这个中间层来完成的。
比如在我们的代码中下工夫。以下代码可以帮助我们实现各平台之间的可移植:
#ifdef _WINDOWS_
CreateThread(); //windows下线程的创建
#else
Pthread_create(); //Linux下线程的创建
#endif
对于头文件,也使用同样的预编译宏来实现。如:
#ifndef _WINDOWS_
#include
#else
#include
#endif
这样就可以实现代码的可移植了。在编译的时侯只要通过#define就可以选择在哪个平台下完成程序的编译。
综上所述,我们都是将C,C++等各类语言当成中间层,以实现其一定程度上的可移植。现在,语言的跨平台的程序都是以这样的形式实现的。并且在不同的平台下,仍须要重新编译。
5.系统开支
使用系统调用会影响系统的性能,在执行调用时的从用户态切换到内核态,再返回用户态会有系统开支。
为了降低开支,因而须要降低系统调用的次数,而且让每次系统调用尽可能的完成多的任务。
硬件也会限制对底层系统调用一次所能写的数据块的大小。
为了给设备和文件提供更高层的插口,Linux系统提供了一系列的标准函数库。
使用标准库函数,可以高效的写任意宽度的数据块unix操作系统免费下载,库函数在数据满足数据块宽度要求时安排执行底层系统调用。
通常地,操作系统为了考虑实现的难度和管理的便捷,它只提供一少部份的系统调用,这种系统调用通常都是由C和汇编混和编撰实现的,其插口用C来定义,而具体的实现则是汇编,这样的益处就是执行效率高,但是,极大的便捷了下层调用。
随着系统提供的这种库函数把系统调用进行封装或则组合,可以实现更多的功能,这样的库函数就能实现一些对内核来说比较复杂的操作。
例如,read()函数依据参数,直接能够读文件,而背后隐藏的诸如文件在硬碟的那个扇区,那个磁道,加载到显存的那个位置等等这种操作,程序员是何必关心的,这种操作上面自然也包含了系统调用。
而对于第三方的库,它虽然和系统库一样,只是它直接借助系统调用的可能性要小一些,而是借助系统提供的API插口来实现功能(API的插口是开放的)。
四、举例
如右图是Linux系统调用的大约流程。
当应用程序调用printf()函数时,printf函数会调用C库中的printf,从而调用C库中的write,C库最后调用内核的write()。
而另一些则不会使用系统调用,例如strlen,strcat,memcpy等。
printf函数执行过程中,程序运行状态切换如下:
用户态–>系统调用–>内核态–>返回用户态
printf函数、glibc库和系统调用在系统中关系图如下:
实例代码如下:
1 #include
2
3
4 int main(int argc, char **argv)
5 {
6 printf("yikoulinux");
7 return 0;
8 }
编译执行
root@ubuntu:/home/peng/test# gcc 123.c -o run
root@ubuntu:/home/peng/test# strace ./run
如执行结果可知:我们的程序其实只有一个printf函数,并且在执行过程中,我们前后调用了execve、access、open、fstat、mmap、brk、write等系统调用。其中write系统调用会把字符串:yikoulinux通过设备文件1,发送到驱动,该设备节点对应终端stdout。
【注意】运行程序前加上strace,可以追踪到函数库调用过程