UNIX系统介绍:
最早版本于1970年左右诞生于美国贝尔实验室,作者是丹尼斯·里奇、肯·汤普逊
最早的多用户、多任务、支持多种CPU架构
具备高安全性、高可靠性、高稳定性
在构建大型关键业务的商用服务器中进行使用,也能在嵌入式移动设备中架设
Minix是一种基于微内核架构的类UNIX计算机操作系统,并开源给大学教学研究使用,Linux是受其启发
Linux系统介绍:
Linux,全称GNU/Linux,由林纳斯·托瓦兹在1991年在校园网上发布了第一个Linux内核版本
是一个基于POSIX的多用户、多任务、支持多线程和多CPU的操作系统
Linux继承了UNIX以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统
相关知识:
Linux的标志:企鹅,因为企鹅是南极洲的标志性动物而当时南极没有被任何国家占领,是属于全人类的,符合Linux开源的风格
GNU组织:通用的非商业的类UNIX,目前全球最大的开源组织,负责维护和开发Linux的内核源
GPL通用许可证:任何在带有GPL证书的代码的基础上开发、修改出来的软件、代码也必须支持GPL许可证书,确保开源免费
POSIX:可移植操作系统接口规范,Linux完全遵循该规范,UNIX极少部分有所不同,但是也基本全部遵循
Linux内核版本和发行版本:
Linux只是表示内核是Linux,只要操作系统的内核是Linux,则可以称该系统属于Linux操作系统
完整的操作系统:内核+Shell+界面软件
其他公司是在Linux内核的基础上,设计制作出不同样子、特点的Linux发行版
例如:Ubuntu、RedHat、CentOS、debian、deepin
GNU编译工具gcc:
多样化:
支持多种编程语言、支持各种操作系统
gcc -v 可以查看是否安装了gcc以及版本信息
编译构建过程:
预处理: gcc -E code.c code.i
编译: gcc -S code.i ->codo.s
汇编: gcc -c code.s ->code.o
链接: gcc a.o b.o ... ->a.out
文件类型:
.c .h .i .s .o
.h.gch 如果存在会优先使用,应及时删除
gcc xx.h -c
.a 静态库文件
.so 共享库文件
编译参数:
-E -S -c -o
-std=gnu99 或者-std=c99(不建议)
-Wall -Werror
-L 指定库文件的查找路径
-I 指定头文件的加载路径
-l 根据库名指定要加载的库文件 -lm
-pedantic 配合使用 -ansi 这告诉编译器严格遵守ANSI标准,如果不符合会产生警告
预处理指令:(是否支持预处理指令有编译器决定)
#include <>/""
#define 定义宏常量、宏函数
#undef 删除宏
#ifdef/#ifndef/#if
#elif
#endif
#pragma pack(n) 设置对齐补齐的最大字节数
#pragma once 相当于头文件卫士
#pragma GCC dependency "文件名" 监控文件在上一次编译到这一次编译期间是否有修改,如果有会产生警告
#pragma GCC poison key 设置key标识符为有毒的 禁止出现该标识符
#error "提示信息" 提示错误 不会生成可执行文件
#warning "提示信息" 提示警告
#line n 设置行号为n,并且会影响后面的行号
一般都与条件编译配合使用
库:
gcc -c list_queue.c ->list_queue.o
库文件就是目标文件的集合,库文件可以被其他代码调用,把代码封装成库文件后方便使用、方便管理、安全性高、保密性强
静态库:xxx.a
就是把目标文件集合成一个以.a结尾的库文件,当调用静态库时,会把静态库中的使用到的二进制指令拷贝到可执行文件中
优点:运行速度比共享库快、可执行文件运行时不需要依赖静态库文件
缺点:可执行文件相对比较大,如果静态库内容发生改变,所有之前使用过该静态库的可执行文件到需要重新编译,耗时
共享库:xxx.so
本质上就是一个带入口的可执行文件,有执行权限
当调用共享库时,在使用共享库代码的地方形成一个入口,该入口记录了调用的代码在共享库中的位置,并且当执行可执行文件时,共享库会与可执行文件一起加载到内存中,当执行共享库的代码时,程序就会跳转到对应的共享库中执行,执行完后可能会跳转
优点:可执行文件相对较小,当共享库发生修改,可执行文件不需要重新编译,只需要重新运行即可
缺点:运行速度比静态库慢一些,可执行文件运行时,必须依赖共享库
制作、使用静态库:
制作:
1、编译出目标文件
gcc -c xxx.c
2、打包目标文件生成静态库文件
ar -r libxxx.a aa.o bb.o cc.o
注意:库文件名字格式必须是libxxx.a/libxxx.so
使用:
1、直接使用
gcc code.c libname.a
2、指定库文件的位置
-L 指定库的查找路径
-l 指定要加载的库名 -lxxx [库名是去掉lib和后缀]
gcc -code.c -L path -lname
3、通过修改环境变量来指定系统查找库文件的默认路径
打开系统的配置文件 vim ~/.bashrc
在文件末尾添加:
export LIBRARY_PATH=$LIBRARY_PATH:绝对路径
保存退出并重新加载:
source ~/.bashrc
使用静态库:
gcc code.c -lname
注意:如果是删除配置文件中的环境变量,需要重启终端后才能生效
制作、使用共享库:
制作:
1、编译出目标文件
gcc -fpic -c code.c
-fpic: 生成与位置无关的文件
2、打包目标文件生成共享库文件
gcc -fpic -shared a.o b.o c.o ... -o libname.so
使用:
注意:共享库要一起与可执行文件加载到内存中才能运行,但是加载执行共享库的路径与编译使用共享库路径是两种查找路径,因此还需要额外设置共享库的加载路径,一般设置环境变量LD_LIBRARY_PATH来实现
1、直接使用
gcc code.c libname.so
2、指定库文件的位置
-L 指定库的查找路径
-l 指定要加载的库名 -lxxx [库名是去掉lib和后缀]
gcc -code.c -L path -lname
3、通过修改环境变量来指定系统查找库文件的默认路径
打开系统的配置文件 vim ~/.bashrc
在文件末尾添加:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:绝对路径
保存退出并重新加载:
source ~/.bashrc
使用静态库:
gcc code.c -lname
注意:如果是删除配置文件中的环境变量,需要重启终端后才能生效
注意:当共享库和静态库文件同名且在同一个查找路径下,编译器编译时会优先使用共享库进行编译
可以增加 -static 指定优先查找使用同名的静态库文件
环境变量表:
每个程序执行时操作系统都会提供一张环境变量表,该表中记录了操作系统所有的环境变量,这些环境变量反映了当前操作系统的配置情况以及当前程序所处于的系统环境
注意:每个程序的环境变量表只是一张复制表,随便修改,不会对真正的环境变量有所影响
查看环境变量表:
命令:env
在程序中获取环境变量表:
声明:extern char** environ;
操作环境变量表的相关函数
char* getenv(const char* name);
功能:获取某个环境变量的值
nema:环境变量名
返回值:返回环境变量的值
int setenv(const char* name,const char* value,int overwrite);
功能:对环境变量表中的环境变量进行增加或修改
name:环境变量名
value:环境变量的值
overwrite:当环境变量存在时
为真会修改环境变量
为假则不会修改
返回值:0表示成功,-1表示失败
int putenv(char* string)
功能:以"name=value"格式修改或者增加环境变量
注意:如果存在则修改,不存在则新增
返回值:0表示成功,-1表示失败
int unsetenv(const char* name);
功能:删除某个环境变量
返回值:0表示成功,-1表示失败
int clearenv(void);
功能:清空环境变量表
错误处理:
1、通过函数返回值表示错误
a、合法值表示成功,非法值表示失败
例如:计算大小、长度、查找下标
b、返回值是指针类型
返回NULL/0xFFFFFFFF表示失败
其余都是成功
c、返回0成功,返回-1表示失败,一般都是系统函数
d、永远成功 printf
2、通过影响全局的错误编号变量 errno,定义在errno.h中
char* strerror(int errnum);
功能:返回错误编号对应的错误信息
注意:errno是一个全局变量,很容易被其他人修改,不能根据它的值判断是否产生错误