嵌入式C语言(十四)

简介: 嵌入式C语言(十四)

现代操作系统架构中,内核空间和用户空间之间增加了一个中间层,这就是系统调用层。

系统调用层主要有如下作用。

为用户空间程序提供一层硬件抽象接口。这能够让应用程序编程者从学习硬件设备底层编程中解放出来。例如,当需要读写一个文件时,应用程序编写者不用去关心磁盘类型和介质,以及文件存储在磁盘哪个扇区等底层硬件信息。

保证系统稳定和安全。应用程序要访问内核必须通过系统调用层,那么内核可以在系统调用层对应用程序的访问权限、用户类型和其他一些规则进行过滤,这样可以避免应用程序不正确地访问内核。

可移植性。可以让应用程序在不修改源代码的情况下,在不同的操作系统或者不同的硬件体系结构的系统中重新编译并且运行。

1 系统调用和POSIX标准

有的读者可能对应用编程接口(API)和系统调用之间的关系有点糊涂了。

一般来说,应用程序调用用户空间实现的应用编程接口来编程,而不是直接调用系统调用。

一个 API接口函数可以由一个系统调用实现,也可以由多个系统调用来实现,甚至完全不使用任何系统调用。

因此,一个API接口没有必要对应一个特定的系统调用。

在UNIX系统设计的早期就出现了操作系统的API接口层。

在UNIX的世界里,最通用的系统调用层接口是POSIX(Portable Operating System Interface of UNIX)标准。POSIX的诞生和UNIX的发展密不可分。

UNIX系统诞生于20世纪70年代的贝尔实验室,很多商业厂商基于UNIX发展自己的UNIX系统,但是标准不统一。后来IEEE制定了POSIX标准,但是需要注意的是,POSIX标准针对的是API而不是系统调用。

判断一个系统是否与POSIX兼容时,要看它是否提供一组合适的应用编程接口,而不是看它的系统调用是如何定义和实现的。

Linux操作系统的API接口通常是以C标准库的方式提供的,比如Linux中的libc库。

C库提供了POSIX的绝大部分的API的实现,同时也为内核提供的每个系统调用封装了相应的函数,并且系统调用和 C 库封装的函数名称通常是相同的。

例如,open 系统调用在 C库的函数也是open函数。

另外几个API函数可能调用封装了不同功能的同一个系统调用,例如,libc库函数中实现的malloc()、calloc()和free()等函数,这几个函数用来分配和释放虚拟内存(堆上的虚拟内存),它们都是利用brk系统调用来实现的。

大家都知道malloc是c中常用的内存操作函数,malloc动态的申请一块指定大小的内存,方便存放数据。而brk/sbrk则是实现malloc的底层函数,其中brk是系统调用。brk和sbrk主要的工作是实现虚拟内存到内存的映射。

每个进程可访问的虚拟内存空间为3G,但在程序编译时,不可能也没必要为程序分配这么大的空间,只分配并不大的数据段空间,程序中动态分配的空间就是从这一块分配的。如果这块空间不够,malloc函数族(realloc,calloc等)就调用sbrk函数将数据段的下界移动,sbrk函数在内核的管理下将虚拟地址空间映射到内存,供malloc函数使用。

sbrk不是系统调用,是C库函数。系统调用通常提供一种小功能,而库函数通常提供比较复杂的功能。sbrk/brk是从堆中分配空间,本质是移动一个位置,向后移就是分配空间,向前移就是释放空间,sbrk用相对的整数值确定位置,如果这个整数是正数,会从当前位置向后移若干字节,如果为负数就向前若干字节。在任何情况下,返回值永远是移动之前的位置。

从操作系统角度来看,进程分配内存有两种方式,分别由两个系统调用完成:brk和mmap(不考虑共享内存)。

brk是将数据段(.data)的最高地址指针_edata往高地址推;

mmap是在进程的虚拟地址空间中(堆和栈中间,称为文件映射区域的地方)找一块空闲的虚拟内存。

这两种方式分配的都是虚拟内存,没有分配物理内存。在第一次访问已分配的虚拟地址空间的时候,发生缺页中断,操作系统负责分配物理内存,然后建立虚拟内存和物理内存之间的映射关系。

在标准C库中,提供了malloc/free函数分配释放内存,这两个函数底层就是由brk,mmap,munmap这些系统调用实现的。

2 系统调用表

Linux系统为每一个系统调用赋予一个系统调用号。

当应用程序执行一个系统调用时,应用程序就可以知道执行和调用到哪个系统调用了,从而不会造成混乱。

系统调用号一旦分配之后就不会有任何变更,否则已经编译好的应用程序就不能运行了。

对于ARM32系统来说,其系统调用号定义在arch/arm/include/uapi/asm/unistd.h头文件中。

<arch/arm/include/uapi/asm/unistd.h>
/** This file contains the system call numbers.*/
#define __NR_restart_syscall    (__NR_SYSCALL_BASE+ 0)
#define __NR_exit      (__NR_SYSCALL_BASE+ 1)
#define __NR_fork      (__NR_SYSCALL_BASE+ 2)
#define __NR_read      (__NR_SYSCALL_BASE+ 3)
#define __NR_write      (__NR_SYSCALL_BASE+ 4)
#define __NR_open      (__NR_SYSCALL_BASE+ 5)
#define __NR_close      (__NR_SYSCALL_BASE+ 6)
/* 7 was sys_waitpid */
#define __NR_creat      (__NR_SYSCALL_BASE+ 8)
#define __NR_link      (__NR_SYSCALL_BASE+ 9)
#define __NR_unlink     (__NR_SYSCALL_BASE+ 10)
#define __NR_execve     (__NR_SYSCALL_BASE+ 11)
#define __NR_chdir      (__NR_SYSCALL_BASE+ 12)
#define __NR_time      (__NR_SYSCALL_BASE+ 13)
#define __NR_mknod      (__NR_SYSCALL_BASE+ 14)
目录
相关文章
|
22天前
|
机器学习/深度学习 算法 数据挖掘
C语言在机器学习中的应用及其重要性。C语言以其高效性、灵活性和可移植性,适合开发高性能的机器学习算法,尤其在底层算法实现、嵌入式系统和高性能计算中表现突出
本文探讨了C语言在机器学习中的应用及其重要性。C语言以其高效性、灵活性和可移植性,适合开发高性能的机器学习算法,尤其在底层算法实现、嵌入式系统和高性能计算中表现突出。文章还介绍了C语言在知名机器学习库中的作用,以及与Python等语言结合使用的案例,展望了其未来发展的挑战与机遇。
39 1
|
22天前
|
人工智能 安全 算法
基于C语言的嵌入式系统开发,涵盖嵌入式系统概述、C语言的优势、开发流程、关键技术、应用实例及面临的挑战与未来趋势。
本文深入探讨了基于C语言的嵌入式系统开发,涵盖嵌入式系统概述、C语言的优势、开发流程、关键技术、应用实例及面临的挑战与未来趋势。C语言因其高效、可移植、灵活及成熟度高等特点,在嵌入式系统开发中占据重要地位。文章还介绍了从系统需求分析到部署维护的完整开发流程,以及中断处理、内存管理等关键技术,并展望了嵌入式系统在物联网和人工智能领域的未来发展。
46 1
|
6月前
|
C语言
C语言实现2048小游戏---粤嵌GE6818嵌入式系统实训
C语言实现2048小游戏---粤嵌GE6818嵌入式系统实训
|
4月前
|
算法 IDE 程序员
C语言与嵌入式系统:嵌入式C编程基础。
C语言与嵌入式系统:嵌入式C编程基础。
92 0
|
6月前
|
存储 移动开发 C语言
技术心得记录:嵌入式开发中常用到的C语言库函数
技术心得记录:嵌入式开发中常用到的C语言库函数
64 1
|
6月前
|
C语言
C语言实现电子音乐相册---粤嵌GEC6818嵌入式系统实训
C语言实现电子音乐相册---粤嵌GEC6818嵌入式系统实训
|
6月前
|
安全 Linux 编译器
嵌入式C语言(十二)
嵌入式C语言(十二)
40 1
|
6月前
|
存储 算法 Linux
嵌入式C语言(十三)
嵌入式C语言(十三)
29 0
|
7月前
|
数据处理 调度 C语言
C语言:嵌入式硬件利器
C语言:嵌入式硬件利器
|
算法 Linux Android开发
本CSDN博主将与北京航天航空大学出版社合作出版&lt;嵌入式C语言技术实战开发&gt;一书
本书作者由以下成员合作编写:     杨源鑫,主编,毕业于广州科技贸易职业学院电子应用技术专业,在校期间一并考取了华南理工大学本科数字媒体艺术专业。2015年7月工作至今,任伟易达集团嵌入式系统工程师一职,主要从事单片机,linux,Android底层开发等相关的技术。
2984 0