当前位置: 首页 > news >正文

自己做的网站打开速度慢江西省网站开发

自己做的网站打开速度慢,江西省网站开发,台州做网站哪家公司好,网站建设启动大会前言 在上篇博客当中#xff0c;对静态库是什么#xff0c;怎么使用#xff0c;简单实现自己的静态库#xff0c;这些做了描述#xff0c;具体请看上篇博客#xff1a; 本篇博客将会对 动态库是什么#xff0c;怎么使用#xff0c;简单实现自己的动态库#xff0c…前言 在上篇博客当中对静态库是什么怎么使用简单实现自己的静态库这些做了描述具体请看上篇博客   本篇博客将会对 动态库是什么怎么使用简单实现自己的动态库这些做描述。 动态库 动态库的创建 动态库的创建其实说和 静态库是非常类似的都是先想要把 源程序文件生成 .o 为后缀的文件也就是编译成功过的文件然后再 进行链接。 只是在链接过程当中链接方式不同。 在静态库当中我们使用的编译源文件的方式是直接使用 -c 选项的方式生产源程序的 .o 编译文件。 gcc -c $^ // -c 选项不在后续 $ 确认生成的目标文件名默认生成的 与源程序名相同的 .o 文件 但是在动态库当中我们在上述生成 .o 文件使用 -c 选项 之外还需要带上 -fPIC 其中 PIC 要大小选项这个  fPIC 代表的意思是 产生位置无关码。 gcc -fPIC -c xxx.c 而gcc 是默认 优先链接 动态库的也就是当 同一个动态库和静态库同时存在的时候gcc 会优先链接动态库吗除非是 当前只有 静态库没有动态库那么 gcc 没有办法只能使用静态库又或者是 用户强制要求要用某一个静态库。 所以静态库在安装的过程当中需要用户手动去安装但是对于 动态库gcc 就可以自己帮助我们实现一个 .so 文件。 利用gcc命令使用 -shared 选项生成一个动态库   gcc -shared -o libxxx.so *.o 上述就是利用在当前目录当中的所有后缀为 .o 的文件打包为一个 xxx 动态库动态库必须是 lib 开头 .o 结尾的文件名 上述的 -shared 选项就是生成一个 分享动态库。 静态库只是该源程序提供代码本质上也就是提供一些二进制数据所以静态库的作用其实就是把源程序需要的代码拷贝到源程序当中拷贝完之后源程序当中是如何进行执行的就和 这个静态库没关系了静态库是不用被加载到内存当中执行的。 而动态库不一样当源程序当中执行到 动态库当中的代码的时候是直接跳转到 动态库当中去执行所以注定了 动态库当中的代码是需要被加载到内存当中供 cpu 执行的。 从 两 .a 和 .so 文件的 默认权限你也可以看出动态库的文件权限当中是带 x 可执行的而 静态库不是。 动态库 静态库所以上述动态库我们直接执行就会报错   并不是 这个程序不能执行而是这个动态库不能单独执行他需要源程序来调用其中的代码来执行。 而动态库和静态库不是不能执行只是不能单独执行他们都是未来 链接出的 可执行程序当中代码的一部分。 现在我们给出几个源程序文件 // mylog.c #include mylog.hvoid Log(const char*info) {printf(Warning: %s\n, info); }//mylog.h #pragma once#include stdio.hvoid Log(const char*);//mymath.c #include mymath.hint myerrno 0;int add(int x, int y) {return x y; } int sub(int x, int y) {return x - y; } int mul(int x, int y) {return x * y; } int div(int x, int y) {if(y 0){myerrno 1;return -1;}return x / y; }//mymath.h #pragma once#include stdio.hextern int myerrno;int add(int x, int y); int sub(int x, int y); int mul(int x, int y); int div(int x, int y);//myprint.c #include myprint.hvoid Print() {printf(hello new world!\n);printf(hello new world!\n);printf(hello new world!\n);printf(hello new world!\n); }//myprint.h#pragma once#include stdio.hvoid Print(); 所以有了上述动态库创建和上篇博客当中 对于 静态库的 创建现在我们在makefile 当中写上对应 生成的目标文件就可以一键生成的 对应的 动态库 和 静态库了   dy-liblibmymethod.so #目标动态库文件的生成 static-liblibmymath.a # 目标静态库文件的生成.PHONY:all #同时生成多个目标文件 all: $(dy-lib) $(static-lib) all 这个文件依赖于 dy-lib 和 static-lib$(static-lib):mymath.o # 生成静态库把 .o 文件打包生成 libmymath.a文件ar -rc $ $^ mymath.o:mymath.c # 由源程序 生成 对应 .o 文件gcc -c $^ $(dy-lib):mylog.o myprint.o # 生成动态库把 .o 文件打包生成 libmymethod.so文件gcc -shared -o $ $^ mylog.o:mylog.c # 由源程序 生成 对应 .o 文件gcc -fPIC -c $^ myprint.o:myprint.c # 由源程序 生成 对应 .o 文件gcc -fPIC -c $^.PHONY:clean clean:rm -rf *.o *.a *.so mylib.PHONY:output # 用于发布的出来 的 生成的目标文件 output:mkdir -p mylib/includemkdir -p mylib/libcp *.h mylib/includecp *.a mylib/libcp *.so mylib/lib 先 make 把对应的 源程序文件 编译生成 .o 文件 下述就是上述生成之后的结果 把上述这些  .o 文件 打包到 各自的 动静态库 当中 此时就发布完成了   上述的这个 lib 文件夹当中的内容就是我们上述由 各个源程序文件生成的 各自的 .o 文件的动态库和 静态库的 。 此时直接使用这种 #includemylog.h 然后直接编译的话他就会提示找不到这个头文件所以我们还需要把 这个存储 动静态库 和 各自头文件的 mylib 文件夹拷贝到 系统默认路径 当中这种才能使用 这种 #includemylog.h 方式来引用头文件和使用其中的代码。 上述拷贝到 默认 路径当中其实就是库的安装这种方式使用最多的当然你也可以使用 gcc 命令当中的 -i  -L -l 三个选项来实现。 上述我们就创建了一个 动态库 和 一个静态库。 如何让可执行程序找到动态库LD_LIBRARY_PATH 环境变量 现在我们来用上述的 动态库来实现一个 可执行程序然后编译运行 在上述生成的 动态库 和 静态库的基础之上我们来使用上述的库来写一个程序看看能不能编译成功   //main.c#include mylog.h #include myprint.hint main() {Print();Log(hello log function);return 0; } 上述引用的两个头文件都是动态库当中头文件也就是说上述源程序当中只引入了 我们上述实现的 动态库。 但是我们发现虽然我们上述的 动静态库没有在 系统默认路径下安装但是我们还用了gcc 当中的三个指令来引入 头文件 和 库虽然成功生成了 可执行文件但是当我们运行这个可执行程序的时候却报错找不到我们上述实现的  动态库 但是当我们 file 命令 这个 a.out 可执行文件之时却告知我们 这个可执行文件是有 动态库链接的 但是在 ldd 命令当中显示这个 动态链接是 not found 的  但是我们上述在 gcc 命令当中不是已经对 对应的 头文件 和 库名称和库所在路径做了声明吗已经告诉编译器了头文件是什么什么库在哪里了。 是的你已经告诉了编译器了编译器已经知道了但是别忘了动态库是在加载到 内存当中进行调度执行的他不像静态库一样单独拷贝一份给对应的源程序当中拷贝完就不管了 动态库要加载到内存当中进行调度执行。 所以上述只是 编译器知道了这个动态库要被执行也只是编译器知道这个 库是什么在哪里但是系统并不知道。 所以系统要知道也就是 加载器 要知道。 所以首先你要明白的是动态库是一个单独的文件他和 可执行文件是两个文件我没在执行可执行文件之时是带上了 路径的就算没有带上路径要想成功运行必须在 PATH 环境变量当中存储的路径下有这个可执行文件才能够不带上路径执行。 所以我们要想执行一个 动态库就要让 系统找到这个动态库。 第一个方法就是把 这个 动态库拷贝到 C程序默认的系统路径当中这样系统就可以在 这个默认路径当中找到这个 动态库从而执行。 如上所示拷贝到 lib64 这个目录当中系统 就可以找到这个 动态库从而执行。 除了上述 拷贝 的方式还可以 ln 命令 在上述 lib64 当中创建软链接链接到 libmymethod.so 这个 动态库 所在的存储路径当中。 软链接建立结果 此时他直接就指向了 动态库的存储位置。 如上所示我们都没有重新对 a.out 重新编译但是上述使用 ldd 命令却已经可以看到链接 到 libmymethod.so 动态库的链接的结果了。 也可以运行了。 除了上述的 在 默认目录当中进行 拷贝软链接 的操作和 系统找命令的可执行程序的 PATH 环境变量一样上述的 在C当中和 默认 查找 库的也有一个环境变量 --- LD_LIBRARY_PATH 说得更详细一点LD_LIBRARY_PATH  环境变量当中存储的就是 系统用来搜索动态库的路径。  这个环境变量可能你的系统当中会没有但是如果你配置过 VIM 的话可能会有。 如果没有也没关系可以自己配置一下 在冒号后面跟上 动态库所在的路径就可以了 不需要加上 动态库文件名。  因为需要链接哪一个库在 gcc 当中 选项当中已经给出了。 此时我们再 ldd 命令查看 链接情况发现也是链接成功了的。  但是上述我们是修改了 环境变量但是我们修改的是 bash 的环境变量因为 当前我们所有的运行的命令都是bash 的为我们生成的子命令export 命令是一个内建命令因为它要修改 bash 的环境变量所以export 是不需要创建子进程而是由 bash 自己的来执行。 但是修改的终究是 bash 的环境变量bash 当中的环境变量是在 程序启动之时由对应的 环境变量生成脚本一层一层 加载添加出来的。 所以也就是说如果我们不修改 每一次开机系统脚本对 bahs 当中的环境变量的添加进行修改的话那么当我们关机之后再次启动脚本生成的还是之前的 那些环境变量。 所以要想根本解决上述 由 LD_LIBRARY_PATH 环境变量当中存储的 路径的话需要修改 生成的 bash 环境变量的脚本。 除了上述方式还有一个访问可以实现 在系统当中有一个目录当中存储的是 后缀为 .conf 的文件这些文件我们称之为 配置文件在这些文件当中存储的都是路径信息。 这个目录是   /etc/ld.so.conf.d 我们可以随便打开一个看看 所以如果像系统找到 对应 动态库的话就可以在   /etc/ld.so.conf.d 这个 路径下创建一个 后缀为 .conf  的文件文件名随便取在这个文件当中直接像上述一样存放 对应 动态库的存储位置注意此时 不需要带上 库名称 然后很重要的一步需要使用 ldconfig 命令 重新加载一下 上述路径下的配置文件。 上述这种 在 /etc/ld.so.conf.d 路径当中进行修改的操作只要我们不修改我们对于其中的配置文件那么这个修改就是永久有效的 其实只有 上述的第三种使用 LD_LIBPARY_PATH 环境变量这个操作如果不修改 bash 启动的脚本的话关机之后就无效了。 同样的如果我们在上述程序当中加上 我们在上篇博客当中实现的静态库的话只要我们gcc 编译链接成功了把静态库当中的代码已经拷贝到 可执行程序当中用于链接了而且此时我们运行程序是可以正常运行的结果也是正确的。 那么在之后不管这个静态库被移动到什么其他位置了不在之前链接的位置了或者更加夸张一点直接把静态库删除 我们上述生成的可制成程序一样说可以跑的因为静态库链接就是把静态库当中的代码直接拷贝到 对应源程序的当中成为 源程序的 一部分。 而不像 动态库链接链接成功之后动态库的位置是不能移动的因为编译链接成功之后不仅仅是编译器在编译之时需要找到这个动态库位置因为 动态库是要被加载到 内存当中进行执行的。 连接成功后执行可执行程序当 可执行程序执行到 需要动态库当中的代码之时 就需要直接跳转到 动态库 当中执行此时动态库需要被加载到内存当中配合 原可执行程序 进行 执行。 所以动态库在被加载之前还需要被 系统知道在什么位置存储的也就是 加载器需要知道 此动态库在什么位置存储的。 至此才能保证 动态库可以被加载到 内存当中进行运行。 如下所示 在上述代码当中mymath.h 就是上一篇博客当中实现的 静态库。  上图就在之前 gcc 链接动态库的基础之上加上 -lmymath.h 链接上静态库。  删除静态库并且在此执行程序 由上图你会发现当我们删除掉静态库没有重新编译链接 形成可执行文件但是在之前形成的 可执行文件 还是可以运行。没有出错。 当然不管是静态库 还是 动态库都是可以被多个 源程序所引用的。但是由静态库 链接生成 的 多个 可执行文件如果把此静态库删除掉这些个 可执行程序还是可以跑的 但是如果是 由 动态库 链接形成的多个可执行文件如果是把此动态库删除掉了那个由此动态库链接的所有 可执行程序就都不能跑了。 如上图所示我们把上述 main 和 mytest 两个可执行文件 需要的 libmymethod.so 动态库删除了发现就不能运行了。  所以动态库再被系统加载之后会被所有的 进程所共享 使用了动态链接的方式 形成 的 可执行文件都是需要系统加载到内存运行这个 动态库的。 而且这个动态库被加载到内存只需要加载一次因为一次也已经够所有 进程所使用了。这样的话在系统当中 就减少了重复的代码。 所以一个进程在磁盘外存上有自己独立的一份代码而在 内存当中又有 和其他 进程 有相同的 代码共享这些相同的代码。 所以我们把 动态库 又叫做 共享库。 那么一个系统当中肯定会加载很多个 动态库到内存当中操作系统如何管理这些海量的 库呢 我们说只要是加载到内存当中被操作系统所管理的都离不开 这 六字真言先描述再组织  先把 管理一个库所需要的所有属性都用一个 struct 结构体描述起来这叫做 先描述对象然后用某种数据结构把上述生成的 很多个 struct 结构体都链接起来这叫做 再组织。 动态库是如何做到被所有进程共享的重谈进程地址空间 如上所示在每一个进程的 地址空间当中每一个地址都是一个 虚拟地址通过 页表映射到 物理内存地址。 在磁盘当中每一个进程 独立的 可执行程序从磁盘当中被加载到 内存当中通过 页表来映射到 进程地址空间的 代码区当中。 而如果在 进程 独立的 可执行程序 当中发现比如是 printf函数并没有在 可执行程序当中实现但是在编译链接之时又有一个动态库当中有 printf函数的实现那么在运行到 printf函数之时就会 跳转到 共享区 当中去寻找 printf实现的虚拟地址通过页表映射到物理内存当中。 在执行完之后就会跳回 代码区当中继续执行 这个进程的 代码。 至此动态库当中的代码就被进程所使用同样的上述只是一个进程同样可以是多个进程。 那么动态库加载到内存当中的 代码数据就可以被 多个进程所使用了。 所以在页表当中建立映射之后从此往后进程在执行任何的代码不管是自己 可执行程序当中的代码还是 共享区当中的 动态库的共享代码都是可以在 进程地址空间当中进行 执行的。 此时对于动态库 和 自己可知程序当中的代码就都可以看做是一份代码了只不过在执行到 动态库当中的代码之时需要跳转到 动态库当中代码进行执行只是可能两份代码跳转的比较远罢了。 所以在操作系统是如何 跳转到共享区当中找到对应的 共享代码区执行的。其实就是上述所说的先描述在组织。 操作系统只需要管理好 先描述在组织 的数据结构就可以管理好其中的 对象而管理好一个一个的 存储 库 属性的 对象就可以管理好 一个一个库在内存当中的 使用情况比如 当前是否正在被使用大小占多少进程要使用的库有没有被加载到内存当中起始地址是什么········· 所以在上述 操作之后OS 对于 库的 加载情况就非常清楚了。 共享库当中的 errno 变量存储的问题 共享库当中的代码是共享的那么其中的数据是不是共享的呢 如果我们在一个 C 程序当中对 errno 这个 C库当中的全局变量进行了修改其他C 程序会不会受到影响 答案是不会的因为 共享区是在 栈 和 堆区当中的这也就意味着当 某一个进程对 errno 变量做了修改就会发生写时拷贝谁写谁就自己拷贝一份 自己存储 自己修改的数据。 这个写时拷贝的 出来的空间 在共享区当中存储同时在 C 管理 要输出到文件当中的数据也有一个 struct_file 结构体来管理在这个结构体当中就有 C 帮我们提供的 语言级别的缓冲区用户级缓冲区。 总结  静态库 只需要在 编译时期 可以找到这个 静态库在哪把这个静态库当中的数据拷贝到 对应源程序当中。 但是动态链接不一样如果要是用到 动态库的话动态库就需要再 内存当中被加载从而执行。而 静态库是不需要 加载到内存当中执行的它完成了 拷贝的工作就可以 下岗了在当前可执行程序的链接就不需要他了。 在上述说明的 四种 可执行程序链接 动态库 的方式的当中其实用得最多就是 拷贝 这种方式。因为这种方式最直接了当你会发现这种方式其实是最方便的。 第三方库链接操作例子【Linux拓展】ncurses库的安装和使用 {ncurses库的安装方法ncurses库的使用手册基于终端的贪吃蛇游戏}_芥末虾的博客-CSDN博客 上述的 ncurses库 是一个 基于 终端的 图形界面的库有兴趣的可是尝试链接这个第三方库。 上述的 ncurses 库是在Linux 下的如果是在windows 当中其实还有 easyx 库在windows 当中这些库会做的更酷炫一些。还有 QT。
http://wiki.neutronadmin.com/news/194659/

相关文章:

  • 建设小说网站风险分析网站维护升级
  • 公司建设网站费用吗新手 网站建设 书籍
  • 百度站长平台诊断苏州网站设计服务
  • php 手机网站cmsdw网站开发环境搭建
  • 湛洪波.jsp网站开发详解建设工程 法律 网站
  • 网站商城开发装修网站怎么做的
  • 企业网站设计步骤iis 网站显示建设中
  • 设计相关的网站网站的排版问题
  • 网站建设公司需要哪些网站创作
  • 电影网站怎么做优化如何做拦截网站
  • 聊城做网站找谁国外网站平台
  • 带做网站价位建设网站上申请劳务资质
  • 做钓鱼网站软件两个wordpress共享账户
  • 网站服务器和空间谁会制作网站
  • 广告设计制作公司网站o2o营销模式
  • 手机营销网站制作phpstudy
  • 海东商城网站建设自己做门户网站
  • myeclipse做网站更改名字最近国际新闻
  • 自己做的网站怎么发布上wordpress媒体库现实不全
  • 开发区经济建设网站门户网站的发展趋势
  • 建站公司的服务器简约手机网站源码
  • 虎丘网站建设如何做影视网站
  • 江苏建设厅老网站婚庆公司取名大全集
  • 代做通一样的网站小型企业做网站的价格
  • 沧州建设网站的公司深圳酒店vi设计公司
  • 网站建设好评语wordpress改成ajax
  • 霸州网站优化帮别人做ppt赚钱的网站
  • flash网站建设教程视频正规软件开发培训机构
  • 模板网站搭建网站建设基本模板介绍
  • 做c语言的题目的网站百度灰色关键词排名