From 3241e245616b1436a38f6cf41d4a723fc4593b50 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Mon, 11 Jul 2022 00:55:03 -0400 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=AF=B9posix/xxx.h=E5=A4=B4?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=BD=BF=E7=94=A8=E5=9C=BA=E6=99=AF=E7=9A=84?= =?UTF-8?q?=E6=8F=8F=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../programming-manual/libc/introduction.md | 23 +++---------- .../programming-manual/libc/iso-ansi-c.md | 32 +++++++++++++------ 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/rt-thread-version/rt-thread-standard/programming-manual/libc/introduction.md b/rt-thread-version/rt-thread-standard/programming-manual/libc/introduction.md index 92f4671..f470523 100644 --- a/rt-thread-version/rt-thread-standard/programming-manual/libc/introduction.md +++ b/rt-thread-version/rt-thread-standard/programming-manual/libc/introduction.md @@ -4,25 +4,25 @@ RT-Thread 提供的 LIBC (C library, C库),包含编译器内置LIBC、编译 ![libc_structure](figures/libc_structure.png) -## 编译器配平层 +## 1 编译器配平层 编译器配平层负责对接编译器的底层桩函数以及平衡不同编译器内置C库函数的差异而设计,为上层 POSIX 层提供功能统一的接口,位于 [components/libc/compiler](https://github.com/RT-Thread/rt-thread/tree/master/components/libc/compilers) 文件目录下。之所以需要配平,是由于 GCC (newlib)、Keil-MDK、IAR、Visual Studio (WIN32) 四个编译工具链内置 LIBC 所提供的标准 C 库函数支持程度不一样,编译器配平层负责将四种不同的编译链所提供的标准 C 库平衡到相同的水平。编译器配平层无需用户手动干预,会在编译工程时,根据用户所使用的的编译平台和工具链自动进行配平。保证上层无需区分使用何种编译平台和工具链的 LIBC ,使用通用的头文件即可引用 LIBC 的相关函数。 -## ISO/ANSI C 标准 +## 2 ISO/ANSI C 标准 ANSI C、ISO C、Standard C是指美国国家标准协会(ANSI)和国际标准化组织(ISO)对C语言发布的标准。历史上,这个名字专门用于指代此标准的原始版本,也是支持最好的版本(称为C89或C90)。使用C的软件开发者被鼓励遵循标准的要求,因为它鼓励使用跨平台的代码。C的第一个标准是由ANSI发布的。虽然这份文档后来被国际标准化组织(ISO)采纳并且ISO发布的修订版亦被ANSI采纳,但名称ANSI C(而不是ISO C)仍被广泛使用。一些软件开发者使用名称ISO C,还有一些使用中立的名称Standard C。例如常说的C89 (ANSI X3.159-1989)、C99 (ISO/IEC 9899:1999)、C11 (ISO/IEC 9899:2011) 实际都是指该标准的不同版本。 该标准通常被编译器/工具链内置 LIBC 所支持,例如 Keil-MDK、IAR 等所提供的的内置 LIBC 都是满足该标准的。 -## POSIX 标准 +## 3 POSIX 标准 可移植操作系统接口(英语:Portable Operating System Interface,缩写为POSIX)是IEEE为要在各种UNIX操作系统上运行软件,而定义API的一系列互相关联的标准的总称,其正式称呼为IEEE Std 1003,而国际标准名称为ISO/IEC 9945。ISO/ANSI C 是 POSIX 的子集。 -### IEEE Std 1003.1 +### 3.1 IEEE Std 1003.1 针对LIBC,目前广泛使用的 POSIX 标准是 1003.1 标准,全称为IEEE Std 1003.1(缩写写法为 POSIX.1)。IEEE Std 1003.1-2001、IEEE Std 1003.1-2008 等为 POSIX.1 在不同时期更新发布的版本。 -### IEEE Std. 1003.13 +### 3.2 IEEE Std. 1003.13 该标准是 POSIX 针对实时规范 (reatime profiles)。该标准是由 IEEE Std 1003.1 筛选而来,因此是其子集。IEEE Std. 1003.13 定义了四个子集: @@ -32,16 +32,3 @@ ANSI C、ISO C、Standard C是指美国国家标准协会(ANSI)和国际标 - Multi-Purpose:具有实时性要求的大规模通用系统子集规范 —— PSE54 目前 RT-Thread 已经实现 PSE51 规范以及部分 PSE52 规范的内容。 - -### 注意事项 - -##### 不同编译平台的兼容 - -* 为保证跨不同编译器、不同工具链的兼容性,建议用户应用层代码: - * 使用 代替 - * 使用 代替 - * 使用 代替 - -有使用 的引用逻辑的,修改为 的方式来避免编译错误;其他两个也是类似的处理逻辑,拟合不同编译工具链的处理逻辑。 - -# diff --git a/rt-thread-version/rt-thread-standard/programming-manual/libc/iso-ansi-c.md b/rt-thread-version/rt-thread-standard/programming-manual/libc/iso-ansi-c.md index 0ba9219..cccd26e 100644 --- a/rt-thread-version/rt-thread-standard/programming-manual/libc/iso-ansi-c.md +++ b/rt-thread-version/rt-thread-standard/programming-manual/libc/iso-ansi-c.md @@ -1,12 +1,12 @@ # ISO/ANSI C 标准 -## 标准输出函数 (printf 家族) +## 1 标准输出函数 (printf 家族) -### printf 函数 +### 1.1 printf 函数 在 Keil 和 IAR 编译平台下,用户可以直接使用 printf 函数;在 GCC 下,需要额外使能 `RT_USING_POSIX_FS` 和 `RT_USING_POSIX_STDIO` 宏才能使用 printf 函数。 -### rt_kprintf 函数 与 printf 函数的使用选择 +### 1.2 rt_kprintf 函数 与 printf 函数的使用选择 如果不是特殊需求,建议使用 rt_kprintf 函数,因为 printf 是由编译平台内部提供的,其空间占用、以及内存使用情况我们无从得知,printf 函数要比 rt_kprintf 函数的 ROM 占用大很多。 @@ -18,7 +18,7 @@ 2. 如需 rt_kprintf 函数支持线程安全输出,可以安装 [rt_kprintf_threadsafe 软件包](https://github.com/mysterywolf/rt_kprintf_threadsafe)。 3. 上述两个软件包可以同时安装使用,以同时让 rt_kprintf 支持线程安全和浮点类型输出的能力。 -### 其他字符串格式化输出函数 (例如 snprintf 等) +### 1.3 其他字符串格式化输出函数 (例如 snprintf 等) 其他字符串格式化输出函数(例如 snprintf 等)都是可以直接使用的。 @@ -26,23 +26,23 @@ 同理,原生 rt_snprintf 等函数不支持浮点输出,用户可以通过安装 [rt_vsnprintf_full 软件包](https://github.com/mysterywolf/rt_vsnprintf_full) 来支持浮点数输出。 -## 内存相关函数 +## 2 内存相关函数 malloc 、realloc 、calloc 、free 内存分配函数可以直接使用,其已经被 rt_malloc 、rt_calloc 、rt_realloc 、rt_free 函数接管,二者无任何区别。 memcpy 、memset 等内存操作相关函数。这里需要注意的时,建议使用 rt_memcpy 以及 rt_memset 来代替 memcpy 和 memset ,虽然 rt_memxxx 函数要比C库的内存操作函数要慢一些,但是要更安全;除非您对拷贝速度非常在意,否则建议使用 rt_memxxx 函数。如果使用的是 Cortex-M 的 MCU,可以安装 [rt_memcpy_cm](https://github.com/mysterywolf/rt_memcpy_cm) 软件包来对 rt_memcpy 函数进行汇编加速,该软件包安全且高效。 -## 字符串相关函数 +## 3 字符串相关函数 strlen 等字符串相关函数为编译器C库内置函数,可以直接使用。 -## 系统函数 +## 4 系统函数 exit 、abort 函数,调用后相当于删除当前线程。 system 函数可以用于在 C 程序中内置执行一些 FinSH 命令。 -## 时间函数 +## 5 时间函数 所有 ANSI/ISO-C 规定的时间函数均可以使用,例如 time 、ctime 等函数。注意:部分涉及到获取当前时间的函数需要使能 RTC 设备才可以正常工作,如果没有使能 RTC 设备就调用这些函数,会在串口终端给出警告。 @@ -61,8 +61,22 @@ system 函数可以用于在 C 程序中内置执行一些 FinSH 命令。 2. 目前,时间相关函数不支持的是夏令时自动转换相关功能。夏令时在中国不使用,主要是欧美国家在使用。 -## kservice.c +## 6 kservice.c 在RT-Thread内核 (Kernel) 中有一个叫 kservice.c 的文件。该文件提供了RT-Thread自己实现的C库函数,例如 rt_strlen、rt_strcpy 等等。这些函数存在的意义在于让 RT-Thread 内核具备自持能力,即在不依赖任何C库的情况下,依然可以正常运行。此外,部分编译器内置的C库函数,如上所说,存在一些缺陷,kservice.c 文件中提供的函数更安全,且可控。如果认为,kservice.c 文件中提供的函数与编译器内置C库函数重复,可以通过配置,将 kservice.c 中的大多数函数重映射到编译器内置C库函数中,例如:在开启如下图所示的选项后,调用 rt_strlen 函数实际相当于直接调用编译器内置C库的 strlen 函数。 ![kservice](figures/kservice.png) + +## 7 标准库C头文件 +### 7.1 不同编译平台的兼容 + +为保证跨不同编译器、不同工具链的兼容性,建议用户应用层代码: + * 使用 `sys/time.h` 代替 `time.h` + * 使用 `sys/errno.h` 代替 `errno.h` + * 使用 `sys/signal.h` 代替 `signal.h` + +### 7.2 标准库C头文件的POSIX扩展函数声明 + +POSIX 在标准库C头文件的基础上又扩展了一些函数声明,例如在标准C头文件 `stdio.h` 中是没有 `getline` 函数的,该函数是POSIX.1-2008标准中出现在 `stdio.h` 文件中的。因此如果使用涉及到类似上述的POSIX扩展C库函数(如 `getline`),需要引用 `posix/stdio.h` 头文件,而非 `stdio.h` 头文件。其他C标准库头文件,诸如 `ctype.h`、`stdlib.h` 等也是同理。 + +这是由于Keil、IAR、WIN32编译器内置C库中的标准头文件只支持到ISO-ANSI C标准,并不支持POSIX扩展的函数声明,因此RT-Thread的编译器配平层中,采用这种方式来补足上述三个编译器,从而让上层代码方便地跨编译器平台运行。 -- Gitee