嵌入式-UC(Unix系统高级编程)-2

UC学了有一阵子了,打算把笔记整理一下,发到网上,方便以后随时复盘,也供给大家拿去学习交流,希望不要收藏吃灰,要坚持学习,通过自己的努力,为这世界中你喜欢的方向添砖加瓦。

一、库

先说两个概念引入:

对于初学者,一般会把程序中所有功能全部实现于一个单一的源文件内部。这会导致编译时间长,不易于维护和升级,不易于协作开发,这属于单一模型。

将程序中的不同功能模块划分到不同的源文件中。缩短编译时间,易于维护和升级,易于协作开发,这属于分离模型。

1.静态库

静态库的本质就是将多个目标文件打包成一个文件

链接静态库就是将库中被调用的代码复制到调用模块中。

使用静态库的程序通常会占用较大的空间库中代码一旦修改,所有使用该库的程序必须重新链接 

使用静态库的程序在运行时无需依赖库,其执行效率高

静态库的命名形式:libxxx.a

构建静态库:ar -r libxxx.a  x.o y.o z.o

使用静态库:法一:gcc ... -lxxx -L<库路径>  

法二:export LIBRARY_PATH=<库路径>

2.动态库

动态库和静态库最大的不同就是,链接动态库并不需要将库中被调用的代码复制到调用模块中,相反被嵌入到调用模块中的仅仅是被调用代码在动态库中的相对地址

如果动态库中的代码同时为多个进程所用,动态库的实例在整个内存空间中仅需一份,因此动态库也叫共享库或共享对象(Shared Object, so)。

使用动态库的模块所占空间较小,即使修改了库中的代码,只要接口保持不变,无需重新链接。

使用动态库的代码在运行时需要依赖库,执行效率略低

动态库的命名形式:libxxx.so

构建动态库:

gcc -c -fpic xxx.c -> xxx.o

一般在创建.so动态链接库的时候,都要加上-fPIC参数。 -fPIC 作用于编译阶段,告诉编译器产生与位置无关代码 (Position-Independent Code),则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行。(即使不加 fPIC 也可以生成 .so 文件,但是对于源文件有要求,例如因为不加 fPIC 编译的 so 必须要在加载到用户程序的地址空间时重定向所有表目,所以在它里面不能引用其它地方的代码)

打包命令:gcc -shared -o libxxx.so x.o y.o z.o

使用动态库:法一:gcc ... -lxxx -L<库路径>  

法二:export LIBRARY_PATH=<库路径>

gcc ... -lxxx

与静态库的使用有所不同的一点:运行时所调用的动态库必须位于LD_LIBRARY_PATH环境变量所表示的路径中。

gcc缺省(即不做任何说明时)链接共享库,可通过-static选项强制链接静态库。

3.动态加载动态库

#include <dlfcn.h>  这个头文件不属于标准c里的头文件,是属于系统提供的

-ldl : dl是动态加载库的意思,即链接动态加载库,说明使用的是系统提供的针对动态库的动态加载函数集

void* dlopen(const char* filename, int flag);

成功返回动态库的句柄,失败返回NULL。

句柄:相当于一个线索,让系统内核找到对应的动态库,但是他不直接指向动态库,他只是指向一个数据块,这个数据块里存储着和动态库有关的信息,这样的数据块就叫做句柄。(Handle)只需要得到这个块的地址就可以操作。

filename - 动态库路径,若只给文件名,则根据LD_LIBRARY_PATH环境变量搜索动态库

flag - 加载方式,可取以下值:

RTLD_LAZY - 延迟加载,使用动态中的符号时才加载

RTLD_NOW - 立即加载

该函数所返回的动态库句柄唯一地标识了系统内核所维护的动态库对象,将作为后续函数调用的参数。

void* dlsym(void* handle, const char* symbol);

成功返回函数地址,失败返回NULL。

handle - 动态库句柄

symbol - 符号(函数或全局变量)名

该函数所返回的函数指针是void*类型,需要强制类型转换为实际的函数指针类型才能调用。

int dlclose(void* handle);

成功返回0,失败返回非零。

handle - 动态库句柄

char* dlerror(void);

之前若有错误发生则返回错误信息字符串,否则返回NULL。

二、辅助工具

1.查看符号表:nm

列出目标文件(.o)、可执行文件、静态库文件(.a)或动态库文件(.so)中的符号 

 注意:没有c,是因为c是局部变量,只有等这个程序运行起来,才会在栈中分配内存空间,局部变量不在可执行文件中。

2.显示二进制模块的反汇编信息:objdump -S xx

3.删除目标文件(.o)、可执行文件、静态库文件(.a)或动态库文件(.so)中的符号表和调试信息:strip   (可以用来隐藏一些信息或者减少空间)

三、错误号和错误信息

1.通过函数的返回值表达错误

例如:返回整数的函数:通过返回合法值域以外的值表示错误

int age (char const* name){

... 

return 1000;

}

例如:返回指针的函数:通过返回NULL指针表示错误

例如:不需要通过返回值输出信息的函数:返回0表示成功,返回-1表示失败。

int delete(char const* filename) {

    ...

    return 0;

    ...

    return -1;

}

2.通过错误号和错误信息表示产生错误的具体原因

#include <errno.h>

全局变量:errno,整数,标识最近一次系统调用的错误

#include <string.h>

char* strerror(int errnum); // 根据错误号返回错误信息

#include <stdio.h>

void perror(const char* s); // 打印最近错误的错误信息

printf函数的%m标记被替换为最近错误的错误信息

例如:

 

虽然所有的错误号都不是0,但是因为在函数执行成功的情况下错误号全局变量errno不会被清0,因此不能用errno是否为0作为函数成功失败的判断条件,是否出错还是应该根据函数的返回值来决定

返回值 = 函数调用(...);

if (返回值表示函数调用失败) {

    根据errno判断发生了什么错误

    针对不同的错误提供不同的处理

}

 

 四、环境变量

   每个进程都有一张独立的环境变量表,其中的每个条目都是一个形如“键=值”形式的环境变量。

语法 : env

所谓环境变量表就是一个以NULL指针结束的字符指针数组,其中的每个元素都是一个字符指针,指向一个以空字符结尾的字符串,该字符串就是形如”键=值”形式的环境变量

根据环境变量名获取其值

char* getenv(char const* name);

成功返回变量名匹配的变量值,失败返回NULL。

name - 环境变量名,即等号左边的部分

添加或修改环境变量

int putenv(char* string);

成功返回0,失败返回-1。

string - 形如“键=值”形式的环境变量字符串

若其键已存在,则修改其值,若其键不存在,则添加新变量

但是不会影响父进程的环境变量。

添加或修改环境变量

int setenv(const char* name, const char* value,

    int overwrite);

成功返回0,失败返回-1。

name - 环境变量名,即等号左边的部分

value - 环境变量值,即等号右边的部分

overwrite - 当name参数所表示的环境变量名已存在,此参数取0则保持该变量的原值不变,若此参数取非0,则将该变量的值修改为value。

删除环境变量

int unsetenv(const char* name);

成功返回0,失败返回-1。

name - 环境变量名,即等号左边的部分

清空环境变量

int clearenv(void);

成功返回0,失败返回-1。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: uC/OS-II是一种常见的实时操作系统,特别适用于嵌入式系统应用。以下是一些嵌入式系统中使用uC/OS-II的常见应用: 1. 通信设备:uC/OS-II可以帮助控制通信设备的操作,包括传输数据、管理缓冲区和处理错误。 2. 汽车电子系统:现代汽车中有许多电子设备需要管理,包括引擎控制、车载娱乐系统和车载导航系统uC/OS-II可以帮助管理这些设备,使它们能够协同工作。 3. 工业自动化:在工业自动化应用中,uC/OS-II可以协调多个任务,从而提高系统的吞吐量和响应速度。这种操作系统可以管理复杂的工业过程,并提供实时控制和监控。 4. 医疗设备:在医疗设备中,uC/OS-II可以管理多个任务和处理程序,从而确保设备能够及时、准确地响应患者的需要。 5. 智能家居:智能家居设备需要管理多个任务,包括控制照明、温度和安全系统uC/OS-II可以帮助这些设备实现实时响应和协调。 总的来说,uC/OS-II在嵌入式系统中的应用非常广泛,可以帮助嵌入式系统实现实时响应、多任务管理和复杂操作。 ### 回答2: uC/OS-II是一个广泛应用于嵌入式系统的实时操作系统(RTOS)。 嵌入式系统是一种特殊的计算机系统,通常是嵌入到其他设备中的计算机系统嵌入式系统广泛应用于各种领域,如汽车、航空航天、医疗、家电、通讯等。而uC/OS-II作为嵌入式系统的操作系统,具有以下应用: 首先,uC/OS-II提供了实时任务调度和管理功能。嵌入式系统通常需要同时处理多个任务,如控制、通信、显示等。而uC/OS-II能够根据任务的优先级进行实时调度,确保高优先级任务能够及时响应,保证系统的实时性能。 其次,uC/OS-II提供了多任务之间的通信和同步机制。在嵌入式系统中,不同任务之间需要进行信息交换和共享资源。uC/OS-II提供了消息队列、信号量、互斥量等机制,确保不同任务之间的协同工作。 此外,uC/OS-II提供了中断管理和时钟服务功能。嵌入式系统通常需要对各种硬件设备进行中断处理,如按键、定时器、通信设备等。uC/OS-II能够及时响应中断事件,并进行相应的处理。同时,它还提供了时钟服务,用于定时触发定时器、任务延时等功能。 最后,uC/OS-II还具备可移植性和可扩展性。它可以运行在不同的硬件平台上,支持多种处理器架构。此外,它还提供了丰富的组件和功能模块,可以方便地进行系统定制和扩展。 综上所述,uC/OS-II作为嵌入式系统中的操作系统,具有广泛的应用。它能够提供实时任务调度和管理、任务之间的通信和同步、中断管理和时钟服务等功能,使得嵌入式系统能够高效可靠地运行。 ### 回答3: 嵌入式系统uC/OS-II是一个非常流行和广泛应用的实时操作系统嵌入式系统是指专门设计用于特定应用领域的计算机系统,例如汽车电子、医疗器械和工业自动化等。这些系统通常具有实时性、可靠性和高效性的需求。而uC/OS-II就是为满足这些需求而开发的一款实时操作系统。 在嵌入式系统中,uC/OS-II可以应用于各种各样的领域。首先,它可以用于控制和监控系统嵌入式系统需要对外部环境进行实时的监测和控制,以保证系统的正常运行。通过使用uC/OS-II,可以轻松实现传感器数据的采集和实时控制,从而实现自动化控制系统。 其次,uC/OS-II也是无人机和机器人控制系统的理想选择。无人机和机器人通常需要高效的任务调度和实时响应能力。uC/OS-II提供了灵活的任务管理和实时调度机制,可以帮助开发人员快速构建高性能的无人机和机器人控制系统。 此外,uC/OS-II还适用于网络通信系统。现代嵌入式系统通常需要与外部系统进行通信,以实现数据传输和远程控制。通过使用uC/OS-II提供的网络通信功能,可以轻松实现与外部设备的数据交互和通信连接。 总的来说,uC/OS-II在嵌入式系统中的应用非常广泛。它可以支持实时控制、任务调度、网络通信和数据交互等功能,满足各种不同领域嵌入式系统的需求。同时,uC/OS-II还具有可移植性和可扩展性,使得开发人员可以更加灵活地进行系统设计和开发。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值