静态库
- 程序编译一般需经预处理、编译、汇编和链接几个步骤
- 静态库是指在我们的应用中,有一些公共代码是需要反复使用的,就把这些代码编译为“库”文件
- 在链接步骤中,链接器将从库文件取得所需的代码,复制到生成的可执行文件中的这种库
- 静态库特点是可执行文件中包含了库代码的一份完整拷贝
- 缺点就是被多次使用就会有多份冗余拷贝
练习打包静态库
编写简单的 add sub mul div 函数, 编译生成 .o 文件

利用命令生成静态库
ar -rc libmymath.a add.o sub.o mul.o div.o
其中 mymath 是我们的静态库名称
- 编译, 运行程序
gcc main.c -L . -l mymath
- -L 选项是指定库的路径
- -l 选项是指定库名
此时, 即使删掉我们的静态库文件, 程序依然可以运行

动态库
- 动态库又称动态链接库, 英文为DLL,是Dynamic Link Library 的缩写形式
- DLL是一个包含可由多个程序同时使用的代码和数据的库,DLL不是可执行文件。
- 动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。
- 函数的可执行代码位于一个 DLL 中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。
- DLL 还有助于共享数据和资源。多个应用程序可同时访问内存中单个DLL 副本的内容。
- Windows下动态库为.dll后缀,在linux在为.so后缀。
生成动态库
- fPIC : 生产与位置无关码
gcc -fPIC -c add.c sub.c chengfa.c div.c
ps:乘法这里我用mul.c会报错, 改成chengfa.c就好了, 还不知道为什么
- shared : 表示生成共享库格式
gcc -shared -o libmymath.so add.o sub.o chengfa.o div.o
- 编译运行
gcc main.c -o -L . -l mymath
运行动态库
- 拷贝 .so 文件到系统共享库目录下, 一般为 /usr/lib
- 更改 LD_LIBRARY_PATH
export LD_LIBRARY_PATH=.
gcc main.c -l mymath
ifconfig

myshell
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
int main()
{
while(1)
{
printf("[myshell]$ ");
fflush(stdout);
char buf[1024];
ssize_t ret = read(0, buf, (sizeof(buf)) - 1);
if(ret > 0)
{
buf[ret - 1] = 0;
}
char *_argv[32];
char *start = buf;
char *file = NULL;
int pipe_flag = 0;// 管道标识符
int add_redirect_flag = 0; //追加重定向标识符
int redirect_flag = 0; //输出重定向标识符
_argv[0] = buf;
int i = 1;
while(*start)
{
if(*start == ' ')
{
*start = 0;
start++;
//管道实现:当检测到有管道符存在时将命令分为两个数组,管道符以前为一个数组,管道符以后为一个数组
//然后将管道符处赋值为NULL,开辟子进程,让子进程执行前边的命令,将执行结果写入/tmp/myshell文件中
//然后父进程等待子进程结束,父进程时打开/tmp/myshell文件,将文件符复制为标准输入,然后执行后面命令。
if(*start == '|')
{
char *pipe_ch = start;
start++;
pipe_flag = 1;
if(*start == ' ')
{
*start = 0;
start++;
}
}
if(*start == '>')
{
start++;
if(*start == ' ')
{
*start = 0;
start++;
}
if(*start == '>')
{
add_redirect_flag = 1;//表示有一个追加重定向
start++;
if(*start == ' ')
{
*start = 0;
start++;
}
}
file = start;
redirect_flag = 1; //表示有一个输出重定向
break;
}
else
{
_argv[i++] = start;
}
}
else
{
start++;
}
}
_argv[i] = NULL;
pid_t id = fork();
if(id == 0)
{
//子进程
if(redirect_flag)
{
//有重定向, 关闭标准输出
close(1);
if(add_redirect_flag)// 追加重定向
{
int ret = open(file, O_WRONLY | O_CREAT | O_APPEND, 0644);
execvp(_argv[0], _argv);
close(ret);
}
else
{
//输出重定向
int ret = open(file, O_WRONLY | O_CREAT, 0644);
ftruncate(ret, 0); //此函数把ret标识的文件大小置为0, 即先清空文件, 再写入
execvp(_argv[0], _argv);
close(ret);
}
}
else
{
execvp(_argv[0], _argv);
}
}
else
{
pid_t ret = wait(NULL);
if(ret < 0)
{
perror("wait");
return -1;
}
}
if(strcmp(buf, "exit") == 0)
{
break;
}
}
return 0;
}

本文详细介绍了静态库和动态库的概念及应用场景,包括两者的编译与链接过程,并通过实例演示了如何创建和使用这两种类型的库文件。
4027

被折叠的 条评论
为什么被折叠?



