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编译器
- 支持众多编程语言,平台
- 构建过程(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
-
查看版本
gcc -v
-
文件后缀
.h
头文件.gch
头文件的编译结果,一般不要保留.c
源文件.i
预处理文件.s
汇编文件.o
目标文件.a
静态库文件.so
共享库文件 -
参数
-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
文件中删除环境变量后,退出终端重新打开 -
预处理指令
#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
考题
头文件的作用是什么,编写那些内容
说明对应的.c文件的内容有哪些(声明函数,全局变量)
定义结构,联合,枚举,宏
类型重定义
虽然函数可以隐式声明,但并不一定准确,而且非常有可能造成严重错误
头文件找不到怎么办
#include <> / #include “” 的区别
库
库就是代码的集合,我们把不需要升级更新维护的代码打包合并在一起,方便使用,也可以对源代码进行保密
-
静态库:在使用时把被调用的代码复制到调用模块中,之后执行时,就不需要静态库了
特点: 执行速度块,但占用空间大,当库中的内容发生变化时需要重新编译,不能轻易修改库中的内容
-
共享库:只是在调用模块中嵌入调试代码在库的相对位置地址,当程序执行时,共享库的程序一起加载到内存,当执行到调用共享库中代码的指令时跳转到共享中执行,执行完后在跳转回来
特点: 占用空间小,方便更新(变化后不需要再次编译),相对静态库执行效率更低
静态库的扩展名为
.a
共享库(动态库),的扩展名为.so
静态库
-
创建静态库
编写源代码
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
-
调用静态库
-
直接调用
gcc main.c libmath.a
调用者和库在同一路径下 -
设置环境变量
export LIBRARY_PATH=$LIBRARY_PATH:./math/
&&source ~/.bashrc
编译时要指定库名
-lmath
->libmath.agcc main.c -I./math -lmath
-
设置编译参数:
-L路径
gcc main.c -L路径 -lmath
-
-
运行
在编译时已经把被调函数的二进制复制到可执行文件中了,再执行时不在需要静态库文件了
共享库
-
创建共享库
编写源代码
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
-
调试共享库
-
直接调用
gcc main.c libmath.so
调用者和库在同一路径下 -
设置环境变量
export LIBRARY_PATH=$LIBRARY_PATH:./math/
&&source ~/.bashrc
编译时要指定库名
-lmath
->libmath.sogcc main.c -I./math -lmath
-
设置编译参数:
-L路径
gcc main.c -L路径 -lmath
-
-
运行
在使用共享库时,调用者只是记录了代码在库中的位置,因此在执行时需要共享库同时被加载
操作系统会根据
LD_LIBRARY_PATH
环境变量的设置来加载共享库export LD_LIBRARY_PATH=$LIBRARY_PATH:./math/
&&source ~/.bashrc
动态加载共享库
#include <dlfcn.h>
-
加载共享库
void *dlopen(const char *filename, int flag);
filename
:共享库的库名,路径flag
:RTLD_LAZY
使用时才加载RTLD_NOW
立即加载return
:共享库的句柄(类似文件指针) -
获取标识符地址
void *dlsym(void *handle, const char *symbol);
symbol
:标识符的名子return
:标识符在共享库中的位置(地址可以解应用,或跳转过去) -
卸载共享库
int dlclose(void *handle);
return
:成功->0:失败->-1 -
获取错误信息
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)
``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