动静态库原理和制作
个人主页:小则又沐风个人专栏:数据结构竞赛专栏C语言CLinux座右铭悟已往之不谏知来者之可追目录前言软链接硬链接静态库动态库动静态库的比较前言什么是库?来打一个比方:张三是非常擅长语文,李四非常擅长数学,你是一个学计算机的学生,现在老师需要你提交一个作业作业的要求就是需要利用你的语文和数学的知识储备来完成一个项目.如果这个项目你自己编写的话,你当然写的不会有张三在语文中写的好,在数学上你写的一定不会比李四写的好,但是你是一个学习计算机的学生,这难不倒你....你联系了张三和李四让他们分别把他们擅长的部分做好发给你,你做的就是他们擅长的东西组合起来,然后加上你自己的思想这样你产出的产品就是高质量的了.但是你的舍友也想这样做,他说你能不能把张三和李四的东西发给我一份???但是你拥有这个资源的消息很快的就传开了,你不想一会上传给一个人,一会上传一下,你还有自己的生活.所以你就把张三和李四的成果打包上传到了网上并告诉别人:张三和李四的成品就在这里你们下载到自己的电脑就可以了这个成品就是库那么库实现了把别人已经实现了相对完美的代码让你直接使用了,你不再需要自己实现了.我们在日常使用的时候有没有使用库呢???那可是多了去了: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 size0;//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-size0) { write(fp-fdnm,fp-outbuffer,fp-size); fsync(fp-fdnm); fp-size0; } } 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-size0) { 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)然后我们生成动态库的指令也是gccgcc -shared -o lib生成的库文件的名字.so 依赖的.o文件shared:表⽰⽣成共享库格式现在这个动态库文件准备好了现在就是编译的环节了gcc mian.cc -o code -L. -lmystdio然后我们就得到了一个可执行的文件了但是我们运行起来这个文件的时候会发生报错具体的原因是在执行文件的时候找不到相关的动态库文件那么我们刚才编译的时候做的是什么???这里显示我们的动态库not found这是因为动态库的特点就是在运行的时候进行的链接,所以动态库不仅仅需要编译的时候知道动态库,在运行的时候也是需要的,但是在运行的时候查找动态库不是在我们的当前工作目录下查找的一般是在/usr/lib、/usr/local/lib、/lib64中查找的所以我们的解决方案一个就是把我们的动态库文件拷贝到这个会查找的路径下这些将会查找的路径是配置在我们的环境变量中的所以还有一种解决方案就是在我们的环境变量中的查找路径添加我们库文件许所处的路径所以我们把我们的查找路径临时修改当前路径这样我们的程序就可以正常运行了动静态库的比较来用一个例子来列举到动静态的特点假设现在我们的源文件运行到了一个库文件的方法了,静态库的做法就是把静态库中的代码复制到这个地方然后运行起来,而动态库就是告诉你这个方法的地址你自己区这个地址中执行动态库的优点可执行程序体积小库更新后无需重新编译替换.so 文件即可多个程序共享库代码节省资源静态库的优点可执行程序独立运行不依赖外部库运行时无需加载库启动速度快