Unix_Linux操作系统-笔记Day1(库)

Day1


课程介绍

UNIX/linux环境C语言,借助学习操作系统的接口的方法来学习,理解操作系统的运行机制以及一些网络协议。

C/C++,数据结构的算法 与平台无关,重点是算法逻辑

UNIX/Linux/Android/IOS 平台相关,系统接口。

嵌入式/驱动/移植/ 硬件相关,硬件接口

环境介绍

内存管理

文件操作

文件管理

信号处理

进程管理

网络通信

线程同步


UNIX操作系统

C语言编写的操作系统

特点:多用户,多任务,支持多种处理器架构,高安全性,高可靠性,高稳定性。

既可以构建大型关键业务的商用服务器,因为可以构建面向移动终端,手持设备的系统。

三大衍生版本

System V:银行,电信在使用的服务器系统

Berkley:MacOS iOS带界面

Hybrid:Minix,Linux


Linux操作系统

类UNIX操作系统,免费开源,它指的是系统的内核(隶属于GNU工程),凡是使用这中内核的操作系统都叫Linux系统(发行版)。

手机,平板,路由器,视频游戏控制台,PC,大型计算机,超级计算机。

企鹅 —— 开源。

Minix操作系统是一个微型的类UNIX系统,免费开源,而Linux之父就是在参照这款系统,才写出了第一个版本的Linux代码。

GNU工程是自由软件基金会所创立的一个开源组织,基本原则就是共享,主旨是发展出一个有别于商业UNIX的免费且完整的类UNIX系统——GNU Not UNIX。目前Linux内核由它进行维护,所以Linux也叫GNU Linux。

GPL通用公共许可证:
允许对某些成果重用,修改,复制,对所有人都是自由的,但不能声明做了原始工作,或声明由他人所。

POSIX标准:Portable Operating System Interface,统一的系统编程接口规范,它规定了操作系统以接口形式提供的功能的名字,参数,返回值,它保障了应用程序源码级的可移植性。

A主版本号 B次版本号 C补丁版本号 D构建次数 E描述次数

特点 :

  • 多用户,多任务
  • 遵循GNU/GPL具有开放性
  • 丰富的网络功能
  • 可靠的系统安全
  • 良好的可移植性

GNU编译器

  1. 支持众多编程语言,平台
  2. 构建过程(C代码是如何变成可执行文件的)
  • 预处理:把程序员所编译的C代码翻译成标准的C代码

    gcc -E code.c -o code.i

  • 汇编:把预处理后的C代码翻译成汇编代码

    gcc -S code.i

  • 编译:把汇编代码翻译成二进制指令

    gcc -c code.s -o code.o

  • 链接:把若干个目标文件合并成一个可执行文件

    gcc code.o

  1. 查看版本gcc -v

  2. 文件后缀

    .h 头文件

    .gch 头文件的编译结果,一般不要保留

    .c 源文件

    .i 预处理文件

    .s 汇编文件

    .o 目标文件

    .a 静态库文件

    .so 共享库文件

  3. 参数

    -E 预处理

    -S 汇编

    -c 编译(只生成目标文件)

    -o 指定编译结果的名字

    -Wall 产生尽可能多的警告

    -Werror 警告当成错误

    -x 指定编译语言

    -g 生成调试信息

    -On 优化等级

    -D 编译时定义宏

    -l 链接里加库

    -I 指定头文件的查找路径,配置环境变量

    可在~/.bashrc里添加

    export C_INCLUDE_PATH=$C_INCLUDE_PATH:NEW_PATH

    • C_INCLUDE_PATH 旧路径保留
    • NEW_PATH 用户定义的新路径

    改完后 source ~/.bashrc

    注意:如果要删除环境变量,需要在~/.bashrc文件中删除环境变量后,退出终端重新打开

  4. 预处理指令
    #include 文件包含

    #define 定义宏常量或函数

    #undef 删除宏

    #if

    #ifndef

    #ifdef

    #elif

    #endif

    # 把标识符转换成字符串

    ## 把两个标识符合并成一个新的标识符

    #error 在编译期间产生错误

    #warning 在编译期间产生警告

    #pragma

    #pragma GCC dependency 用于监控文件,防止所依赖的文件修改后而不知道 +"file"

    #pragma GCC poison 禁止一个标识符如 #pragma GCC poison goto

    #pragma pack(n) 设置结构,联合的补齐对齐的字节数,只能往下调(<4)而且是2的较小次

    #line

考题
头文件的作用是什么,编写那些内容

  1. 说明对应的.c文件的内容有哪些(声明函数,全局变量)

  2. 定义结构,联合,枚举,宏

  3. 类型重定义

虽然函数可以隐式声明,但并不一定准确,而且非常有可能造成严重错误

头文件找不到怎么办

#include <> / #include “” 的区别


库就是代码的集合,我们把不需要升级更新维护的代码打包合并在一起,方便使用,也可以对源代码进行保密

  • 静态库:在使用时把被调用的代码复制到调用模块中,之后执行时,就不需要静态库了

    特点: 执行速度块,但占用空间大,当库中的内容发生变化时需要重新编译,不能轻易修改库中的内容

  • 共享库:只是在调用模块中嵌入调试代码在库的相对位置地址,当程序执行时,共享库的程序一起加载到内存,当执行到调用共享库中代码的指令时跳转到共享中执行,执行完后在跳转回来

    特点: 占用空间小,方便更新(变化后不需要再次编译),相对静态库执行效率更低

    静态库的扩展名为 .a 共享库(动态库),的扩展名为 .so


静态库

  1. 创建静态库

    编写源代码 vi .c/.h

    编译源代码 gcc -c xxx.c ->xxx.o

    打包生成静态库 ar -r libxxxx.a x1.o x2.o ...

     gcc -c add.c
     gcc -c sub.c
     gcc -c mut.c
     gcc -c avg.c
     ar -r libmath.a *.o
    

    ar 命令的一些参数:

    -r 把目标文件添加到静态库中,已存在的更新

    -q 将目标文件追加到静态库的末尾 ar -q libmath.a add.o

    -d 从静态库中删除目标文件 ar -d libmath.a add.o

    -t 显示静态库中有哪些目标文件 ar -t libmath.a

    -x 把静态库拆分成目标文件 ar -x libmath.a

  2. 调用静态库

    • 直接调用 gcc main.c libmath.a 调用者和库在同一路径下

    • 设置环境变量 export LIBRARY_PATH=$LIBRARY_PATH:./math/ && source ~/.bashrc

      编译时要指定库名-lmath->libmath.a

      gcc main.c -I./math -lmath

    • 设置编译参数: -L路径

      gcc main.c -L路径 -lmath

  3. 运行

    在编译时已经把被调函数的二进制复制到可执行文件中了,再执行时不在需要静态库文件了


共享库

  1. 创建共享库

    编写源代码 vi .c/.h

    编译出位置无关的目标文件: PIC:Position Independent Code

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

    gcc -c -fpic add.c
    gcc -c -fpic sub.c
    gcc -c -fpic mut.c
    gcc -c -fpic avg.c
    

    链接生成共享库:

    gcc -shared x1.o x2.o x3.o

    gcc -shared *.o -o libmath.so
    
  2. 调试共享库

    • 直接调用 gcc main.c libmath.so 调用者和库在同一路径下

    • 设置环境变量 export LIBRARY_PATH=$LIBRARY_PATH:./math/ && source ~/.bashrc

      编译时要指定库名-lmath->libmath.so

      gcc main.c -I./math -lmath

    • 设置编译参数: -L路径

      gcc main.c -L路径 -lmath

  3. 运行

    在使用共享库时,调用者只是记录了代码在库中的位置,因此在执行时需要共享库同时被加载

    操作系统会根据LD_LIBRARY_PATH环境变量的设置来加载共享库

    export LD_LIBRARY_PATH=$LIBRARY_PATH:./math/ && source ~/.bashrc


动态加载共享库

#include <dlfcn.h>

  1. 加载共享库

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

    filename:共享库的库名,路径

    flagRTLD_LAZY使用时才加载 RTLD_NOW立即加载

    return:共享库的句柄(类似文件指针)

  2. 获取标识符地址

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

    symbol:标识符的名子

    return:标识符在共享库中的位置(地址可以解应用,或跳转过去)

  3. 卸载共享库

    int dlclose(void *handle);

    return:成功->0:失败->-1

  4. 获取错误信息

    char *dlerror(void);

    return:会把使用共享库过程中的错误以字符串的形式返回

//dltest.c
#include <stdio.h>
#include <dlfcn.h>

int main(){
    //加载共享库
    void* handle = dlopen("libmath.so",RTLD_NOW);
    if(NULL == hanlde){
        puts(dlerror());
        return -1;
    }
    //获取标识符在共享库中的位置
    float (*avg_ptr)(float,float) = dlsym(handle,"avg");
    if(NULL == avg_ptr){
        puts(dlerror);
        return -1;
    }
    printf("%f\n",avg_ptr(3.14,2.18));
    dlclose(handle);
}
//>>>编译
gcc dltest.c -ldl

辅助工具

nm:查看目标文件,可执行文件,静态库,共享库中的符号列表

ldd:查看可执行程序所依赖的共享库有哪些

strip:减肥,去除掉目标文件,可执行文件,静态库和共享库中的符号列表,调试信息

objdump:显示二进制模块的反汇编信息

作业

把链表,栈,队列,有序二叉树,查找,排序,封装成算法共享库

把之前做项目常用的函数封装成工具共享库libtools.so

ATH添加一个路径(/home/zhizhen/lib)

homework

``int unsetenv(const char *name);``

从环境变量表中删除name

``int clearenv(void);``

清空环境变量表
  • 系统提供的环境变量的数据记录在一块特殊的存储空间,而在程序中自己添加的环境变量需要自己准备存储空间

  • 每个程序只能得到该表的副本,修改操作只对自己有效

练习5:从文件中读取一个程序的配置信息

ServerIP = 192.168.0.1

Port = 8899

MaxSize = 100

ContinueSec = 3

LogPath = /…

DataPath = /…

练习6:给LIBRARY_PATH添加一个路径(/home/zhizhen/lib)
homework

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值