一文简述BSD,System V ,POSIX,SUS版本历史, 以及glibc移植的特性测试宏

背景

我们在开发过程中经常需要进行程序移植。由于不同硬件环境、操作系统和各类依赖库版本的差异,会出现各种兼容性问题。
对于glibc来讲,除了C语言标准之外,还包含了posix、systemV等特性。为此,glibc针对不同的标准有特定的宏定义,用于指定当前代码说遵循的标准和版本。这些宏定义被称为特性测试宏(feature test macro)。

1. 标准概述

1.1 C语言标准

主要包含C89(1989年最初的ANSI C版本)、C99(1999)、C11(2011)和C17(2017)。

1.2 BSD

BSD(伯克利软件发布版,Berkeley Software Distribution)最初是加州大学伯克利分校1979年发布的unix版本,包括了C shell,vi等功能. 由此演化成BSD的标准.

1.3 System V

AT&T1983年发布了unix系统System III,并于1989发布了System V.通过对其它厂商的使用授权使其逐渐成为很多unix功能实现的基础.

1.4 POSIX

POSIX先是称为IEEE标准,之后又被ISO采纳,因此POSIX.1为ISO/IEC 9945-1:1990. 之后陆续升级了命令与工作标准(POSIX.2)、测试方法标准(POSIX.3)、实时 API(POSIX.4)等.

1.5 F151-1和FIPS 151

FIPS 是Federal Information Processing Standard(联邦信息处理标准)于1989年发布。由于美国政府是计算机系统的“大买家”,大多数计算机厂商都会确保其UNIX系统符合FIPS 151-1版本的POSIX.1规范。 FIPS 151-2标准已在2000年被废弃。

1.6 X/Open和XPG3

X/Open公司是由多家国际计算机厂商所组成的联盟(The Open Group) ,基于POSIX的开放系统标准。包含XPG3(1989), XPG4(1992). 其接口成为XSI(X/Open System Interface).

之后经过AT&T公司等一些列转让, X/Open又将XPG4版本2“重新包装”为SUS(Single UNIX Specification)(即SUSv1)或称之为UNIX95。其内容包括:XPG4版本2,X/Open Curses规范第4号版本2,以及X/Opena联网服务(XNS)规范第4号。
SUS版本2(SUSv2,http://www.unix.org/version2/online.html)于1997年发布.

1.7 大一统 SUSv3

2001年, IEEE , The Open Group和ISO委员会共同成立奥斯汀公共标准工作组(Austin CSRG), 批准了POSIX 1003.1-2001,成为ISO/IEC 9945:2002,该标准取代了之前的POSIX版本,被称为 SUSv3. 包含了基本定义, 系统接口, shell和其他工具等内容, 成为POSIX的超集.
SUSv3规范可在线获得,网址是http://www.unix.org/version3/online.html。通过SUSv3认证的UNIX实现可被称为UNIX 03。

至此, ANSI C, POSIX, XPG等标准实现了统一. 并在2008年发布了 POSIX.1-2008/SUSv4,或者称为(2008,Austin CSRG)
在这里插入图片描述

2. 特性测试宏

由上述, 每个标准的内容和接口都有差异, 有的是新添的,也有的在新标准中已经被废弃了. 因此在移植过程中, 我们需要指定我们当前代码使用的具体标准. 指定方式就是在包含头文件之前,定义相关的特性测试宏. 比如:

 #define _XOPEN_SOURCE

或者添加编译选项:

gcc -D_POSIX_SOURCE hello.c

glibc具体支持的标准如下:

2.1 _POSIX_SOURCE

一经定义(不管任何值),头文件会遵从POSIX.1-1990和ISO C(1990)标准的定义。
该宏已被_POSIX_C_SOURCE取代。

2.2 _POSIX_C_SOURCE

若定义为1,效果与_POSIX_SOURCE相同。
若将其值定义为大于等于199309,遵从POSIX.1b(实时)。
大于等于199506,遵从对POSIX.1c(线程)。
等于200112,遵从对POSIX.1-2001(排除了XSI扩展)。(2.3.3版本之前,glibc头文件对_POSIX_C_SOURCE 200112不做解释。)
若将其值定义为200809,遵从POSIX.1-2008规范。(2.10版本之前,glibc头文件对_POSIX_C_SOURCE 200809不做解释。)

2.3 _BSD_SOURCE

一经定义(任何值),开启对BSD定义的支持。同时, 只要定义了该宏,便定义了_POSIX_C_SOURCE值为199506。
极少数的情况下,当标准之间发生冲突时,显式设置该宏会导致系统向BSD定义倾斜。

2.4 _SVID_SOURCE

一经定义(任何值),头文件遵从System V接口规范(SVID)的定义。

2.5 _GNU_SOURCE

一经定义(任何值),头文件除了指定前面所有标准的定义外,还会开启对各种GNU扩展定义的支持:
在调用GNU C编译器时, 不带任何特殊选项,即默认定义了_POSIX_SOURCE、_POSIX_C_SOURCE=200809(glibc版本为2.5-2.9时,其值为200112;glibc版本低于2.4时,其值为199506)、_BSD_SOURCE以及_SVID_SOURCE。
在对个别宏进行了定义,或以其标准模式之一去调用编译器时(比如, cc –ansi 或cc – std=c99),只会按需提供定义。不过,有一个例外:若未对_POSIX_C_SOURCE另行定义,也没有以标准模式之一去调用编译器,则_POSIX_C_SOURCE的值会被定义为200809(glibc版本为2.4-2.9时,其值为200112;glibc版本低于2.4时,其值为199506)。

2.6 _POSIX_C_SOURCE、_XOPEN_SOURCE以及POSIX.1/SUS

在POSIX.1-2001/SUSv3中,仅对_POSIX_C_SOURCE和_XOPEN_SOURCE特性测试宏进行了明确定义,应用程序要符合该标准,应分别将上述两宏的值定义为200112 和 600。这就是我们最常看到的定义了. 即:

-D_POSIX_C_SOURCE=200112  -D_XOPEN_SOURCE=600

SUSv3 明文规定将_XOPEN_SOURCE 设置为 600 时,就包含了将POSIX_C_SOURCE设置为200112时的所有特性。因此,为符合SUSv3(即XSI规范),应用程序只需要定义_XOPEN_SOURC, _POSIX_C_SOURCE可以省略.

将_POSIX_C_SOURCE值定义为200112,即表示应用程序符合POSIX.1-2001基本规范(即符合除XSI扩展规范以外的POSIX规范)。
将_XOPEN_SOURCE值定义为600,即表示应用程序符合SUSv3规范(即符合XSI规范基本规范加XSI扩展规范)。
如果需要声明 POSIX.1-2008/SUSv4,只是需要将上述两个特性测试宏的值分别定义为200809和700。即:

-D_POSIX_C_SOURCE=200809 -D_XOPEN_SOURCE=700

同样, _XOPEN_SOURCE=700包含了_POSIX_C_SOURCE=200809, 所以应用程序只需要定义_XOPEN_SOURC, _POSIX_C_SOURCE可以省略.

3. 代码移植报错implicit declaration of function处理

我们明明声明了对应的头文件,但是编译时就是要报错,说里面的某一些api没有声明. 以usleep为例, 分三步处理.

error:warning: implicit declaration of function ‘usleep’ ;disyou mean 'sleep'?[-Wimplicit-function-declaration]

3.1查看API手册

通过man xxx,来查看该函数对应的版本声明:

man usleep
...
       usleep():
           Since glibc 2.12:
               (_XOPEN_SOURCE >= 500) && ! (_POSIX_C_SOURCE >= 200809L)
                   || /* Glibc since 2.19: */ _DEFAULT_SOURCE
                   || /* Glibc <= 2.19: */ _BSD_SOURCE
           Before glibc 2.12:
               _BSD_SOURCE || _XOPEN_SOURCE >= 500

可以看到, 对于glibc 各个版本_XOPEN_SOURCE,_POSIX_C_SOURCE , _BSD_SOURCE等对应需要的标准声明.

3.2 glibc 版本确定

可以看到在上述宏使用时, 和glibc的版本有较大关系. 因此确定具体定义之前需要先知道当前环境的glibc版本.
直接运行libc的库就可以看到:

$ /lib/x86_64-linux-gnu/libc.so.6
...
version 2.27

或者通过ldd查看:

$ ldd --version
ldd (Ubuntu EGLIBC 2.27-3ubuntu1.4) 2.27
Copyright (C) 2018 Free Software Foundation, Inc.
... 

或者

getconf GNU_LIBC_VERSION
glibc 2.19

3.3 添加声明

头文件之前声明:

#define __DEFAULT_SOURCE

或者 编译选项声明:

gcc -D__DEFAULT_SOURCE ...

或者在其它构建工具声明,比如auto tool 中configure:

add_cflag -D__DEFAULT_SOURCE

总结

多man, 多搜索, 我们将收获更多知识 .

一文简述BSD,System V ,POSIX,SUS版本历史, 以及glibc移植的特性测试宏_susv3-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值