UNIX-Linux操作系统环境介绍

UNIX-Linux系统环境介绍

  • UNIX操作系统
  • Linux操作系统
  • GNU编译器
  • 静态库
  • 共享库
  • 动态加载共享库
  • 辅助工具

UNIX操作系统

  • 丹尼斯.里奇、肯.汤姆逊于1971年左右,在美国贝尔实验室使用C语言开发了这款操作系统。特点是多用户、多任务,支持多种处理器架构,高安全性、高可靠性、高稳定性。既可以构建大型关键业务系统的商用服务器,也可以构建面向移动端的、手持设备等相关的嵌入式应用。
  • 三大衍生版本:
    1、System V:银行电信在使用的服务器系统
    2、Berkley:MacOS、iOS
    3、Hybrid:Minix、Linux

Linux操作系统

  • 类Unix系统,免费开源,它值得是系统的内核,凡是使用这种内核的操作系统都叫做Linux系统,严格来说是Linux内核,隶属于GNU工程。
  • GNU工程是自由软甲基金会所创立的一个开源组织,基本原则就是共享,主旨是发展出一个有别于商业Unix的免费且完整的类Unix系统——GNU Not UNIX。目前Linux内核由它进行维护,所以也叫GNU Linux。
  • GPL通用公共许可证:允许对某些成果及派生成果重用、修改、复制,对所有人都是自由的,但不能声明做了原始工作,或声明由他人所做。
  • POSIX标准:Portable Operating System Interface,统一的系统编程接口规范,它规定了操作系统以接口形式提供的功能的名字、参数、返回值,它保障了应用程序源码的可移植性,而Linux完全遵循了这个标准。

GNU编译器

1、支持众编程语言、平台
2、构建过程(C代码如何变成可执行文件)

预处理:把程序员编译的C代码翻译成标准C代码
汇编:把预处理后的C代码翻译成汇编代码
编译:把汇编代码翻译成二进制指令
链接:把若干个目标文件合并成一个可执行文件

3、gcc -v 查看版本
4、文件后缀

.h 头文件
.gch 头文件的编译结果,一般删除
.c 源文件
.i 预处理文件
.s 汇编文件
.o 目标文件
.a 静态文件
.so 共享库文件

5、参数

-static 优先使用静态库
-E 预处理
-S 汇编
-c 编译(生成目标文件)
-o 指定编译结果的名字
-Wall 产生尽可能多的警告
-Werror 把警告当作错误处理
-x 指定编译语言
-g 生成调试信息
-On 优化等级
-D 在编译时定义宏
-l 链接时添加库
-I 指定头文件的查找路径,配置环境变量
	1、打开 vim ~/.bashrc
	2、在文件末尾,添加一行export C_INCLUDE_PATH=$C_INCLUDE_PATH:NEW_PATH
	3、重新加载配置文件 source ~/.bashrc
	注意:如果要删除环境变量需要在~/.bashrc文件中删除环境变量后,退出终端重新打开。
	头文件的作用:
	1、说明对应.c文件中的内容有哪些(声明函数、全局变量)
	2、定义结构、联合、枚举、宏。
	3、类型重定义

6、预处理指令

#include 	文件包含,注意区分""和<>
#define 	宏常量和宏函数
#			把标识符转换成字符串
##			合并标识符
#undef		删除宏
#line		指定行号
#if			根据条件决定代码是否生成,可以尽量减小可执行文件的大小
#ifndef		头文件卫士,防止头文件被重复包含
#error		在编译期间产生错误
#warning	在编译期间产生警告
#pragma GCC dependency “demo.c”	用于监控文件,防止所依赖的文件,修改后而不知道
#pragma GCC poison goto	用于禁用某些标识符
#pragma pack(n)	设置结构、联合的补齐和对齐字节数 n必须是2的较小次方且比默认值小

  • 库就是目标文件的集合,我们把不需要升级更新维护的代码打包合并在一起,方便使用,也可以对源代码进行保密。
  • 静态库在使用时是把被调用的代码复制到调用模块中,然后再执行程序时,静态库就不需要了。
  • 静态库的执行速度快,但占用空间大,当苦衷的内容发生变化时,需要重新编译生成程序,不能轻易修改库中的内容。
  • 而共享库只是在调用模块中嵌入调用代码的在库的相对位置的地址,当执行程序时,共享库会和程序一起加载到内存中,当执行到调用库中代码的指令时跳转到共享库中执行,执行完毕后再跳转回来。
  • 共享库占用空间小,方便更新(共享库发生变化后,程序不需要再次编译),相对于静态库执行效率略低。
  • 静态库的扩展名为.a 共享库(动态库)的扩展名为.so

静态库

1、创建静态库

编写源代码:vi .c/.h
编译源代码:gcc -c xxx.c -> xxx.o
打包生成静态库:ar -r libxxx.a x1.o x2.o ...
ar的命令的一些参数:
	-r 把目标文件添加到静态库中,已经存在的更新,库文件不存在则创建
	-q	把目标文件追加到静态文件末尾	ar -q libmath.a add.o
	-d 从静态库中删除目标文件			ar -d libmath.a add.o
	-t	显示静态库中有哪些目标文件	ar -t libmath.a
	-x	把静态库拆分成目标文件

2、调用静态库
(1)直接调用:调用者要和库再同一路径下

gcc main.c libxxx.a

(2)设置环境变量:设置方法于C_INCLUDE_PATH类似

1、打开vim ~/.bashrc 文件
2、在文件末尾添加一行	export LIBRARY_PATH=$LIBRARY_PATH:库文件的路径
3、重新加载配置文件 source ~/.bashrc
4、编译时要指定库名	gcc main.c -lmath

(3)设置编译参数:-L路径

gcc main.c -L路径 -lmath

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

共享库

1、创建共享库

编写源代码:vi .c/.h
编译出位置无关的目标文件:gcc -c -fpic xxx.c -> xxx.o
链接生成共享库:gcc -shared x1.o x2.o x3.o... -o libxxx.so

2、调用共享库
(1)直接调用:调用者要和库再同一路径下

gcc main.c libxxx.so

(2)设置环境变量:设置方法于C_INCLUDE_PATH类似

1、打开vim ~/.bashrc 文件
2、在文件末尾添加一行	export LIBRARY_PATH=$LIBRARY_PATH:库文件的路径
3、重新加载配置文件 source ~/.bashrc
4、编译时要指定库名	gcc main.c -lmath

(3)设置编译参数:-L路径

gcc main.c -L路径 -lmath

3、运行
在使用共享库时,调用者只是记录了被调代码在库中的位置,因此在执行时需要共享库同时被加载。操作系统会根据LD_LIBRARY_PATH环境变量的设置来加载共享库。

动态加载共享库

头文件:#include
1、加载共享库

void *dlopen(const char *filename,int flag);
filename :共享库的库名,或路径
flag:
	RTLD_LAZY 使用时才加载
	RTLD_NOW	立即加载
返回值:共享库的句柄(类似文件指针)

2、获取标识符地址并使用

void *dlsym(char *handle,const char *symbol);
handle:共享库的句柄
symbol:标识符的名字
返回值:标识符在共享库中的位置(地址,可以解引用或跳转过去)

3、卸载共享库

int dlclose(void *handle);
handle:共享库的句柄
返回值:成功返回0,失败返回-1

4、获取错误信息

char *dlerror(void);
返回值:会把在使用共享库的过程中出现的错误,以字符串形式返回

辅助工具

nm:查看目标文件、可执行文件、静态库、共享库中的符号列表
ldd:查看可执行程序所依赖的共享库
strip:减肥,去除掉目标文件、可执行文件、静态库和共享库中的符号列表、调试信息。
objdump:显示二进制模块的反汇编信息。

你可能感兴趣的:(Linux学习)