
个人主页:小则又沐风
个人专栏:<数据结构>
<竞赛专栏>
<Linux>
座右铭
悟已往之不谏,知来者之可追
目录
前言
什么是库?
来打一个比方:
张三是非常擅长语文,李四非常擅长数学,你是一个学计算机的学生,现在老师需要你提交一个作业
作业的要求就是需要利用你的语文和数学的知识储备来完成一个项目.
如果这个项目你自己编写的话,你当然写的不会有张三在语文中写的好,在数学上你写的一定不会
比李四写的好,但是你是一个学习计算机的学生,这难不倒你....
你联系了张三和李四让他们分别把他们擅长的部分做好发给你,你做的就是他们擅长的东西组合起来,然后加上你自己的思想这样你产出的产品就是高质量的了.
但是你的舍友也想这样做,他说你能不能把张三和李四的东西发给我一份???
但是你拥有这个资源的消息很快的就传开了,你不想一会上传给一个人,一会上传一下,你还有自己的生活.所以你就把张三和李四的成果打包上传到了网上并告诉别人:张三和李四的成品就在这里你们下载到自己的电脑就可以了
这个成品就是库
那么库实现了把别人已经实现了相对完美的代码让你直接使用了,你不再需要自己实现了.
我们在日常使用的时候有没有使用库呢???
那可是多了去了:stdio.h string.h ......
这些都是我们使用的库
当然库也是分为静态库和动态库的
分开来讲解静态库和动态库
在讲解之前我们来了解一下什么是软硬链接
软链接
我们直接来看一下软链接的指令

我们先在工作的目录下创建出一个文件.我们将会对这个文件进行软链接的操作
ln -s 目标文件 生成的链接文件
ln -s text.txt text_soft.ln

可以看到的是在这个目录中出现了一个文件其中有一个箭头是指向建立软链接的文件的

查看这个文件的内容发现这个链接文件的内容是一样的.

当我们删除了源文件的之后这个软链接就会变成一个红色了
现在我们再去打开这个文件的时候就不被允许了

所以这个软链接有什么用呢???
我们在上级目录中创建一个可执行的文件

然后我们在当前的目录下建立一个软链接
![]()
然后我们就可以在当前目录下这样运行这个可执行文件了

这样我们依靠软链接建立起了一个快捷方式
硬链接

ln 源文件 目标文件
ln code.cc code2.cc
这样我们就给code.cc建立了一个硬链接了,我们可以发现的是这两个文件的inode是相同的.所以我们删除源文件的话是不是代表着code.cc不是真正的删除了

那么硬链接的作用就是给文件进行备份了
上面就是简单的讲解一下文件的软硬链接了
静态库
今天我们的演示代码是之前我们编写自己的文件操作的源文件.现在展示给大家
//my_file.h
#pragma once
#define SIZE 1024
#define FLUSH_NONE 0
#define FLUSH_LINE 1
#define FLUSH_FULL 2
struct IO_FILE
{
int fdnm;//fd
int size=0;//size;
char outbuffer[SIZE];
int flag;//刷新的方式
int cap;
};
typedef struct IO_FILE myfile;
myfile* myopen(const char* filename,const char *mode);
int mywrite(const char* ptr,int num, myfile* fp);
void myfllush(myfile*fp);
void myclose(myfile* fp);
//my_file.cc
#include "my_file.h"
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
myfile *myopen(const char *filename, const char *mode)
{
int fd = -1;
if (strcmp(mode, "r") == 0)
{
fd = open(filename, O_RDONLY);
}
else if (strcmp(mode, "w") == 0)
{
fd = open(filename, O_WRONLY | O_CREAT, 0666);
}
else if (strcmp(mode, "a") == 0)
{
fd = open(filename, O_WRONLY | O_APPEND | O_CREAT, 0666);
}
if (fd < 0)
{
return nullptr;
}
myfile *fp = (myfile *)malloc(sizeof(myfile));
if (fp == nullptr)
{
return nullptr;
}
fp->cap = SIZE;
fp->flag = FLUSH_LINE;
fp->fdnm = fd;
return fp;
}
void myfllush(myfile *fp)
{
if(fp->size>0)
{
write(fp->fdnm,fp->outbuffer,fp->size);
fsync(fp->fdnm);
fp->size=0;
}
}
int mywrite(const char *ptr, int num, myfile *fp)
{
memcpy(fp->outbuffer + fp->size, ptr, num);
fp->size += num;
if (fp->size > 0 && fp->flag == FLUSH_LINE && fp->outbuffer[fp->size - 1] == '\n')
{
myfllush(fp);
}
return num;
}
void myclose(myfile *fp)
{
if(fp->size>0)
{
myfllush(fp);
}
close(fp->fdnm);
}
//mian.cc
#include "my_file.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main()
{
myfile *fp = myopen("./log.txt", "a");
if(fp == NULL)
{
return 1;
}
int cnt = 10;
while(cnt)
{
printf("write %d\n", cnt);
char buffer[64];
snprintf(buffer, sizeof(buffer),"hello message, number is : %d", cnt);
cnt--;
mywrite(buffer, strlen(buffer), fp);
myfllush(fp);
sleep(1);
}
myclose(fp);
}
首先我们需要知道的是静态库的本质是什么?
静态库的本质就是一个个的.o文件,因为我们的mian.cc文件是依赖于这个my_file文件的,所以我们编译的时候需要带上她一起编译.但是为了把我们自己的文件操作的文件共享出来.我们就可以把这个.o文件打包成一个静态库了.
在我们平时使用的时候可以注意到的是,一般是给出头文件和库文件的,相当于头文件是说明书,库文件是方法.
我们现在简单的来实现一下
首先我们先创建出一个目录在这个目录中我们将会存储着头文件和静态库文件
然后把我们需要制作成库文件的源文件编译成.o文件
再将.o文件打包成静态库文件
ar -rc lib库文件的名字.a 依赖的.o文件
需要注意的是将要生成的库文件的名字的格式是一定是上述的格式
最后把mian.cc文件和库文件进行链接编译
mkdir mystio
cp *.h mystio
g++ -c my_file.cc
ar -rc libmystdio.a my_file.o
mv libmystdio.a ./mystdio
g++ mian.cc -L./mystdio -lmystdio -o code
最后的一个指令需要讲解一下-L是指明静态库文件的路径在我的工作目录下是./mystdio
-l是指明静态库文件的名字
但是我们可以发现的是这个名字和我们自己定制的名字是不一样的
这是因为我们需要的是库文件的有效的名字也就是去除lib和后缀的剩余的名字
以上我们就把静态库制作好了
别人想用我们的静态库的话只需要把这个库文件拉取到他的机器上就可以了
动态库
上面我们建立起来了一个静态库
现在就是建立动态库的时候了
首先建立动态库也是需要想相应的.o文件的,但是这时候的做法和刚才的有点不一样了
gcc -fPIC -c 源文件
这个-fPIC是产⽣位置⽆关码(position independent code)
然后我们生成动态库的指令也是gcc
gcc -shared -o lib生成的库文件的名字.so 依赖的.o文件
shared:表⽰⽣成共享库格式
现在这个动态库文件准备好了
现在就是编译的环节了
gcc mian.cc -o code -L. -lmystdio
然后我们就得到了一个可执行的文件了
但是我们运行起来这个文件的时候会发生报错

具体的原因是在执行文件的时候找不到相关的动态库文件
那么我们刚才编译的时候做的是什么???

这里显示我们的动态库not found
这是因为动态库的特点就是在运行的时候进行的链接,所以动态库不仅仅需要编译的时候知道动态库,在运行的时候也是需要的,但是在运行的时候查找动态库不是在我们的当前工作目录下查找的
一般是在/usr/lib、/usr/local/lib、/lib64中查找的
所以我们的解决方案一个就是把我们的动态库文件拷贝到这个会查找的路径下
这些将会查找的路径是配置在我们的环境变量中的
所以还有一种解决方案就是在我们的环境变量中的查找路径添加我们库文件许所处的路径
所以我们把我们的查找路径临时修改当前路径

这样我们的程序就可以正常运行了
动静态库的比较
来用一个例子来列举到动静态的特点
假设现在我们的源文件运行到了一个库文件的方法了,静态库的做法就是把静态库中的代码复制到这个地方然后运行起来,而动态库就是告诉你这个方法的地址你自己区这个地址中执行
动态库的优点
可执行程序体积小;库更新后无需重新编译(替换.so 文件即可);多个程序共享库代码,节省资源;
静态库的优点
可执行程序独立运行,不依赖外部库;运行时无需加载库,启动速度快
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/jiaomorning/article/details/162769801



