静态链接库与动态链接库

以下内容源于C语言中文网相关内容的学习整理,如有侵权请告知删除。

一、库文件的简介

库文件,其等价为压缩包文件。该文件内部通常包含不止一个目标文件(也就是二进制文件),每个目标文件存储的代码,并非完整的程序,而是一个个实用的功能模块。例如,C 语言库文件提供有大量的函数(如 scanf()、printf()、strlen() 等),C++ 库文件不仅提供有使用的函数,还有大量事先设计好的类(如 string 字符串类)。库文件的产生,极大的提高了程序员的开发效率。因为很多功能根本不需要从 0 开发,直接调取包含该功能的库文件即可。并且,库文件的调用方法也很简单,以 C 语言中的 printf() 输出函数为例,程序中只需引入 <stdio.h> 头文件,即可调用 printf() 函数。

调用库文件为什么还要牵扯到头文件呢?首先,头文件和库文件并不是一码事,它们最大的区别在于:头文件只存储变量、函数或者类等这些功能模块的声明部分,库文件才负责存储各模块具体的实现部分。即所有的库文件都提供有相应的头文件作为调用它的接口,库文件是无法直接使用的,只能通过头文件间接调用。头文件和库文件相结合的访问机制,最大的好处在于,有时候我们只想让别人使用自己实现的功能,并不想公开实现功能的源码,就可以将其制作为库文件,这样用户获取到的是二进制文件,而头文件又只包含声明部分,这样就实现了“将源码隐藏起来”的目的,且不会影响用户使用。

二、静态链接库与动态链接库的简介

C或C++程序从源文件到生成可执行文件需经历 4 个阶段,分别为预处理、编译、汇编和链接。链接阶段所要完成的工作,是将同一项目中各源文件生成的目标文件和程序中用到的库文件整合为一个可执行文件。虽然库文件明确用于链接,但编译器提供了2种实现链接的方式,分别称为静态链接动态链接。采用静态链接方式实现链接操作的库文件称为静态链接库;采用动态链接方式实现链接操作的库文件称为动态链接库

在 Linux 发行版系统中,静态链接库文件的后缀名通常用 .a 表示,动态链接库的后缀名通常用 .so 表示;在 Windows 系统中,静态链接库文件的后缀名为 .lib,动态链接库的后缀名为 .dll。

GCC 编译器生成可执行文件时,默认情况下会优先使用动态链接库实现链接操作,除非当前系统环境中没有程序文件所需要的动态链接库,GCC 编译器才会选择相应的静态链接库。如果两种都没有(或者 GCC 编译器未找到),则链接失败。

在 Linux 发行版中,静态链接库和动态链接库通常存放在 /usr/bin 或者 /bin 目录下。

1、静态链接库

静态链接库实现链接操作的方式很简单,即程序文件中哪里用到了库文件中的功能模块,GCC 编译器就会将该模板代码直接复制到程序文件的适当位置,最终生成可执行文件。

使用静态库文件的优势是可移植性强,可独立运行,即生成的可执行文件不再需要任何静态库文件的支持就可以独立运行。劣势是代码冗余、可执行文件的体积大:如果程序文件中多次调用库中的同一功能模块,则该模块代码就会被复制多次,生成的可执行文件中会包含多段完全相同的代码,造成代码的冗余。和使用动态链接库生成的可执行文件相比,静态链接库生成的可执行文件的体积更大。

2、动态链接库

动态链接库,又称为共享链接库。采用动态链接库实现链接操作时,程序文件中哪里需要库文件的功能模块,GCC 编译器不会直接将该功能模块的代码拷贝到文件中,而是将功能模块的位置信息记录到文件中,直接生成可执行文件。

显然,这样生成的可执行文件是无法独立运行的。采用动态链接库生成的可执行文件运行时,GCC 编译器会将对应的动态链接库一同加载在内存中,由于可执行文件中事先记录了所需功能模块的位置信息,所以在现有动态链接库的支持下,也可以成功运行。

采用动态链接库的优势是生成的执行文件文件体积小,因为可执行文件中记录的是功能模块的地址,真正的实现代码会在程序运行时被载入内存,即便功能模块被调用多次,使用的都是同一份实现代码(这也是将动态链接库称为共享链接库的原因)。劣势是可移植性差,无法独立运行,必须借助相应的库文件。

三、静态链接库的创建与使用

1、静态链接库的创建

比如有如下项目。

demo项目├─ headers│     └─ test.h└─ sources├─ add.c├─ sub.c├─ div.c└─ main.c

为了隐藏加法、减法、除法的具体实现,可以将add.c、sub.c 以及 div.c 这 3 个源文件加工成静态链接库。并且根据实际需要,我们可以将它们集体压缩到一个静态链接库中,也可以各自压缩成一个静态链接库。

将源文件打包为静态链接库的过程很简单,只需经历以下 2 个步骤:

(1)将所有指定的源文件,都编译成相应的目标文件。

[root@bogon demo]# gcc -c sub.c add.c div.c
[root@bogon demo]# ls
add.c  add.o  div.c  div.o  main.c  sub.c  sub.o  test.h

(2)使用 ar 压缩指令,将生成的目标文件打包成静态链接库。该指令的基本格式如下。

ar rcs 静态链接库名称 目标文件1 目标文件2 ...

需要注意的是,静态链接库不能随意起名,需遵循“libxxx.a”这样的命名规则,其中xxx 指我们为该库起的名字,比如 Linux 系统自带的一些静态链接库名称为 libc.a、libgcc.a、libm.a,它们的名称分别为 c、gcc 和 m。

[root@bogon demo]# ar rcs libmymath.a add.o sub.o div.o
[root@bogon demo]# ls
add.c  add.o  div.c  div.o  libmymath.a  main.c  sub.c  sub.o  test.h

2、静态链接库的使用

静态链接库的使用很简单,就是在程序的链接阶段,将静态链接库目标文件一起执行链接操作,从而生成可执行文件。

以 demo 项目为例,首先我们将 main.c 文件编译为目标文件:

[root@bogon demo]# gcc -c main.c
[root@bogon demo]# ls
add.c  div.c  libmymath.a  main.o  sub.c
test.h  add.o  div.o  main.c  sub.o

在此基础上,我们可以直接执行如下命令,即可完成链接操作,默认生成可执行文件a.out(或者利用-o选项生成其他命名文件)。-static 选项表示强制 GCC 编译器使用静态链接库。

[root@bogon demo]# gcc -static main.o libmymath.a
[root@bogon demo]# ls
add.c  a.out  div.o        main.c  sub.c  test.h
add.o  div.c  libmymath.a  main.o  sub.o

注意,如果 GCC 编译器提示无法找到 libmymath.a(因为上面这种写法只会在当前目录查找libmymath.a静态链接库),还可以使用如下方式完成链接操作。其中 -L 选项用于向 GCC 编译器指明静态链接库的存储位置; -l(小写的 L)选项用于指明所需静态链接库的名称,注意这里的名称指的是 xxx 部分,且建议将 -l 和 xxx 直接连用(即 -lxxx),中间不需有空格。

[root@bogon demo]# gcc main.o -static -L /root/demo/ -lmymath
[root@bogon demo]# ls
add.c  a.out  div.o        main.c  sub.c  test.h
add.o  div.c  libmymath.a  main.o  sub.o

四、动态链接库的创建与使用

1、动态链接库的创建

使用源文件创建动态链接库,其基本格式如下。其中,-shared 选项用于生成动态链接库;-fpic(还可写成 -fPIC)选项的功能是,令 GCC 编译器生成动态链接库(多个目标文件的压缩包)时,表示各目标文件中函数、类等功能模块的地址使用相对地址,而非绝对地址。这样,无论将来链接库被加载到内存的什么位置,都可以正常使用。另外,动态链接库的命令规则和静态链接库完全相同,只不过在 Linux 发行版系统中其后缀名用 .so 表示。

gcc -fpic -shared 源文件名... -o 动态链接库名

例如将add.c、sub.c 和 div.c 这 3 个源文件生成一个动态链接库:

[root@bogon demo]# ls
add.c  div.c  main.c  sub.c  test.h
[root@bogon demo]# gcc -fpic -shared add.c sub.c div.c -o libmymath.so
[root@bogon demo]# ls
add.c  div.c  libmymath.so  main.c  sub.c  test.h

2、动态链接库的隐式调用

动态链接库的使用场景,就是与项目中其它源文件或目标文件一起参与链接生成可执行文件。以 demo 项目为例,前面我们将 add.c、sub.c 和 div.c 打包到了 libmymath.so 动态链接库中,此时该项目中仅剩 main.c 源程序文件,因此执行 demo 项目也就演变成了将 main.c 和 libmymath.so 进行链接,进而生成可执行文件。

执行如下指令,即意味着隐式调用动态链接库(隐式调用,意思是将动态链接库和其它源程序文件或者目标文件一起参与链接),生成可执行文件main.exe。

[root@bogon demo]# gcc main.c  libmymath.so -o main.exe
[root@bogon demo]# ls
add.c  div.c  libmymath.so  main.c  main.exe  sub.c  test.h

 main.exe 通常无法直接执行,因为执行过程中无法找到 libmymath.so 这个动态链接库。

[root@bogon demo]# ./main.exe
./a.out: error while loading shared libraries: libd.so: cannot open shared object file: No such file or directory

通过执行ldd main.exe指令,可以查看当前文件在执行时需要用到的所有动态链接库,以及各个库文件的存储位置。可以看到main.exe 文件的执行需要 4 个动态链接库的支持,其中就包括 libmymath.so,但该文件无法找到,因此 main.exe 执行会失败。

[root@bogon demo]# ldd main.exe
linux-vdso.so.1 =>  (0x00007fff423ff000)
libmymath.so => not found
libc.so.6 => /lib64/libc.so.6 (0x00000037e2c00000)
/lib64/ld-linux-x86-64.so.2 (0x00000037e2800000)

运行由动态链接库生成的可执行文件时,必须确保程序在运行时可以找到这个动态链接库。常用的解决方案有以下几种。

(1)将链接库文件移动到标准库目录下(例如 /usr/lib、/usr/lib64、/lib、/lib64);

(2)在终端输入export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:xxx,其中 xxx 为动态链接库文件的绝对存储路径(此方式仅在当前终端有效,关闭终端后无效);

(3)修改~/.bashrc 或~/.bash_profile 文件,即在文件最后一行添加export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:xxx(xxx 为动态库文件的绝对存储路径)。保存之后,执行source .bashrc指令(此方式仅对当前登陆用户有效)。

3、动态链接库的显式调用

显式调用动态链接库的过程,类似于使用 malloc() 和 free()(C++ 中使用 new 和 delete)管理动态内存空间,需要时就申请,不需要时就将占用的资源释放。显式调用,意思是在编写代码时,利用某些函数申请调用库函数以及最后关闭与释放库函数资源。由此可见,显式调用动态链接库对内存的使用更加合理。显式调用动态链接库,更常应用于一些大型项目中。

和隐式调用动态链接库不同,在 C/C++ 程序中显式调用动态链接库时,无需引入和动态链接库相关的头文件。但与此同时,程序中需要引入另一个头文件,即#include <dlfcn.h>,因为要显式调用动态链接库,需要使用该头文件提供的一些函数。

(1)类似于读写文件前必须先打开文件,要想显式调用某个动态链接库提供的资源,首先要做的就是打开该库文件。打开库文件,其本质就是将库文件装载到内存中,为后续使用做准备。打开动态库文件需要借助 dlopen() 函数,其语法格式为:void *dlopen (const char *filename, int flag);

  • filename 参数用于表明目标库文件的存储位置和库名;如果用户提供的是以 / 开头,即以绝对路径表示的文件名,则函数会前往该路径下查找库文件;反之,如果用户仅提供文件名,则该函数会依次前往 LD_LIBRARY_PATH 环境变量指定的目录、/etc/ld.so.cache 文件中指定的录、/usr/lib、/usr/lib64、/lib、/lib64 等默认搜索路径中查找。
  • flag 参数的值有 2 种。RTLD_NOW:将库文件中所有的资源都载入内存。RTLD_LAZY:暂时不降库文件中的资源载入内存,使用时才载入。

(2)借助 dlsym() 函数可以获得指定函数在内存中的位置,其语法格式为:void *dlsym(void *handle, char *symbol);

  • hanle 参数表示指向已打开库文件的指针;symbol 参数用于指定目标函数的函数名。
  • 如果 dlsym() 函数成功找到指定函数,会返回一个指向该函数的指针;反之如果查找失败,函数会返回 NULL。

(3)和 dlopen() 相对地,借助 dlclose() 函数可以关闭已打开的动态链接库。该函数的语法格式如下:int dlclose (void *handle);

  • 其中,handle 表示已打开的库文件指针。当函数返回 0 时,表示函数操作成功;反之,函数执行失败。
  • 注意,调用 dlclose() 函数并不一定会将目标库彻底释放,它只会是目标库的引用计数减 1,当引用计数减为 0 时,库文件所占用的资源才会被彻底释放。

(4)dlerror() 函数可以获得最近一次 dlopen()、dlsym() 或者 dlclose() 函数操作失败的错误信息。该函数的语法格式如下:const char *dlerror(void);可以看到,该函数不需要传递任何参数。同时,如果函数返回 NULL,则表明最近一次操作执行成功。

[root@bogon demo]# cat main.c
#include <stdio.h>
#include <dlfcn.h>
int main()
{int m,n;//打开库文件void* handler = dlopen("libmymath.so",RTLD_LAZY);if(dlerror() != NULL){printf("%s",dlerror());}//获取库文件中的 add() 函数int(*add)(int,int)=dlsym(handler,"add");if(dlerror()!=NULL){printf("%s",dlerror());}//获取库文件中的 sub() 函数int(*sub)(int,int)=dlsym(handler,"sub");if(dlerror()!=NULL){printf("%s",dlerror());}//获取库文件中的 div() 函数int(*div)(int,int)=dlsym(handler,"div");if(dlerror()!=NULL){printf("%s",dlerror());}//使用库文件中的函数实现相关功能printf("Input two numbers: ");scanf("%d %d", &m, &n);printf("%d+%d=%d\n", m, n, add(m, n));printf("%d-%d=%d\n", m, n, sub(m, n));printf("%d÷%d=%d\n", m, n, div(m, n));//关闭库文件dlclose(handler); return 0;
}

分析main.c 主程序,发现其中并没有引入 test.h 头文件,因为显式调用动态链接库时不需要它。在使用库文件中相关函数之前,先调用 dlopen() 函数打开库文件,然后通过 dlsym() 函数找到相关函数,最后调用 dlclose() 函数关闭库文件。

编好程序之后,通过执行如下指令,即可生成相应的可执行文件main.exe。注意,这里需要添加 -ldl 选项,因为该程序中用到了<dlfcn.h>头文件,对应的动态库文件是libdl.so,gcc 命令在编译 main.c 时必须用-ldl指明这个库文件。

[root@bogon demo]# gcc main.c -ldl -o main.exe
[root@bogon demo]# ls
add.c  div.c  libmymath.so  main.c  main.exe  sub.c  test.h

五、GCC找不到库文件的解决方法

1、GCC生成可执行文件时找不到库文件

程序链接阶段指明所用库文件的方式有 2 种。假设当前 mian.c 文件需要借助 libmymath.a 才能完成链接,则完成链接操作的 gcc 指令有以下 2 种写法。

[root@bogon demo]# gcc -static main.c libmymath.a -o main.exe
[root@bogon demo]# gcc -static main.c -lmymath -o main.exe

第一种写法完成链接操作时,GCC 编译器只会在当前目录中查找 libmymath.a 静态链接库。如果使用第一种方法完成链接操作,但 GCC 编译器提示找不到所需库文件,表明所用库文件并未存储在当前路径下,解决方案就是手动找到库文件并将其移至当前路径,然后重新执行链接操作。

第二种写法(使用 -l(小写的 L)选项指明要查找的静态库的文件名),则 GCC 编译器会按照如下顺序,依次到指定目录中查找所需库文件。

(1)如果 gcc 指令使用 -L 选项指定了查找路径,则 GCC 编译器会优先选择去该路径下查找所需要的库文件;

(2)再到 Linux 系统中 LIBRARY_PATH 环境变量指定的路径中搜索需要的库文件;

(3)最后到 GCC 编译器默认的搜索路径(比如/lib、/lib64、/usr/lib、/usr/lib64、/usr/local/lib、/usr/local/lib64 等,不同系统环境略有差异)中查找。

如果使用的是第二种方法,也遇到了 GCC 编译器提示未找到所需库文件,表明库文件的存储路径不对,解决方案有以下 3 种:

(1)手动找到该库文件,并在 gcc 指令中用 -L 选项明确指明其存储路径。比如 libmymath.a 静态库文件存储在 /usr 目录下,则完成链接操作的 gcc 指令应为gcc -static main.c -L/usr -lmymath -o main.exe

(2)将库文件的存储路径添加到 LIBRARY_PATH 环境变量中。仍以库文件存储在 /usr 目录下,则通过执行export LIBRARY_PATH=$LIBRARY_PATH:/usr指令,即可将 /usr 目录添加到该环境变量中(此方式仅在当前命令行窗口中有效);

(3)将库文件移动到 GCC 编译器默认的搜索路径中。

2、GCC运行可执行文件时找不到动态库文件

 当 GCC 编译器运行可执行文件时,会按照如下的路径顺序搜索所需的动态库文件。

(1)如果在生成可执行文件时,用户使用了-Wl,-rpath=dir(其中 dir 表示要查找的具体路径,如果查找路径有多个,中间用 : 冒号分隔)选项指定动态库的搜索路径,则运行该文件时 GCC 会首先到指定的路径中查找所需的库文件;

(2)GCC 编译器会前往 LD_LIBRARY_PATH 环境变量指明的路径中查找所需的动态库文件;

(3)GCC 编译器会前往 /ect/ld.so.conf 文件中指定的搜索路径查找动态库文件;

(4)GCC 编译器会前往默认的搜索路径中(例如 /lib、/lib64、/usr/lib、/usr/lib64 等)中查找所需的动态库文件。

注意,可执行文件的当前存储路径,并不在默认的搜索路径范围内,因此即便将动态库文件和可执行文件放在同一目录下,GCC 编译器也可能提示“找不到动态库”。

因此,对于 GCC 运行可执行文件时提示找不到动态库文件的问题,常用的解决方法如下。

(1)将动态库文件的存储路径,添加到 LD_LIBRARY_PATH 环境变量中。假设动态库文件存储在 /usr 目录中,执行export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr指令,即可实现此目的(此方式仅在当前命令行窗口中有效);

(2)修改动态库文件的存储路径,即将其移动至 GCC 编译器默认的搜索路径中。

(3)修改~/.bashrc 或 ~/.bash_profile 文件,即在文件最后一行添加export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:xxx(xxx 为动态库文件的绝对存储路径)。保存之后,执行 source .bashrc 指令(此方式仅对当前登陆用户有效)。

值得一提的是,GCC 编译器提供有 ldd 指令,借助该指令,我们可以明确知道某个可执行文件需要哪些动态库文件做支撑、这些动态库文件是否已经找到、各个动态库文件的具体存储路径等信息。注意,如果某个动态库文件未找到,则 => 后面会显示 not found,表明 GCC 编译器无法找到该动态库,此时该可执行文件将无法执行。

以main.exe 可执行文件为例,执行如下 ldd 指令:

[root@bogon demo]# ldd main.exe
linux-vdso.so.1 =>  (0x00007fff06fb3000)
libmymath.so => /lib64/libmymath.so (0x00007f65b2a62000)
libc.so.6 => /lib64/libc.so.6 (0x00000037e2c00000)
/lib64/ld-linux-x86-64.so.2 (0x00000037e2800000)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/460875.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C库函数qsort七种使用方法示例

这篇文章是 一楼那个学长写的 C库函数qsort七种使用方法示例 七种qsort排序方法<本文中排序都是采用的从小到大排序> 一、对int类型数组排序C代码 int num[100]; Sample: int cmp ( const void *a , const void *b ) { return *(int *)a – *(int *)b; } q…

成都电讯学院研发的计算机,成都电讯工程学院

[拼音]&#xff1a;chengdu dianxun gongcheng xueyuan[外文]&#xff1a;Chengdu Institute of Telecommunication中国一所以培养电子科学技术人才为主的多科性理工科高等学校。1956年9月创建于四川成都。建院初仅设4个专业。1984年&#xff0c;学校设12个系(26个专业)&#x…

Linux系统以源码方式安装软件的方法

以下内容源于网络资源的整理&#xff0c;如有侵权请告知删除。 Linux系统中安装软件的三种方法_馨若梦的博客-CSDN博客_linux怎么安装软件 Linux下源码编译安装详解_Zebul博的博客-CSDN博客_编译安装 Linux源码包的一般安装步骤_Kaiattrib的博客-CSDN博客_linux源码包安装步…

重庆邮电大学计算机科学与技术培养方案,重庆邮电大学计算机科学与技术学院.doc...

重庆邮电大学计算机科学与技术学院.doc重庆邮电大学计算机科学与技术学院2005——2006学年第二学期中期教学检查汇报材料2006年是我校发展史上具有里程碑意义的一年&#xff0c;学校正式更名为重庆邮电大学。为了适应大学的发展要求&#xff0c;适应教育现代化、信息产业化以及…

hdu4565之矩阵快速幂

So Easy! Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 813 Accepted Submission(s): 226 Problem Description A sequence S n is defined as: Where a, b, n, m are positive integers.┌x┐is the ceil …

Red Hat Enterprise Linux Server release 7.0双系统安装

2019独角兽企业重金招聘Python工程师标准>>> Red Hat Enterprise Linux Server release 7.0双系统安装 1.RedHat 公司的企业版7.0已经发布了。下面介绍一下在7.0下装双系统的步骤。 安装前系统&#xff1a;WIN7 要安装的第二个系统:RedHat Enterprise 7.0 请注意&am…

make clean与make distclean的区别

make clean&#xff1a;仅仅清除之前编译的可执行文件及配置文件。 make distclean&#xff1a;清除所有生成的文件&#xff0c;比如将由configure生成的文件全部删除掉&#xff0c;包括Makefile。 Makefile在符合GNU Makefile惯例的Makefile中&#xff0c;包含了一些基本的预…

win2008启动计算机应用配置,[计算机软件及应用]WIN2008_NAP服务器配置详解.doc

[计算机软件及应用]WIN2008_NAP服务器配置详解NAP server setting安装win 2008 操作系统&#xff0c;安装好后修改computer name为TLD4NAP服务器配置 一1,添加角色添加 Active Directory域服务2,安装Active Directory域服务路径&#xff1a;开始->”dcpromo”输入域名3,安装…

ruby 数据sql操作

ActiveRecord ActiveRecord 是 Rails 的 ORM 元件&#xff0c;負責與資料庫溝通&#xff0c;讓我們可以用物件導向的語法操作資料庫。在”打造 CRUD 應用程式”一章中提到的對應概念如下&#xff1a; 將資料庫表格(table) 對應到一個類別(classe)類別方法就是操作表格(table)將…

Android的按钮单击事件及监听器的实现方式

2019独角兽企业重金招聘Python工程师标准>>> 第一种&#xff1a;匿名内部类作为事件监听器类 大部分时候&#xff0c;事件处理器都没有什么利用价值&#xff08;可利用代码通常都被抽象成了业务逻辑方法&#xff09;&#xff0c;因此大部分事件监听器只是临时使用一…

Sublime text在Linux下的安装与配置

以下内容源于网络资源的整理&#xff0c;如有侵权请告知删除。文章内容主要整理源&#xff1a;C语言中文网&#xff1a;C语言程序设计门户网站(入门教程、编程软件)。 一、安装Sublime text 安装方法有两种&#xff1a;利用软件包管理工具安装&#xff0c;利用下载好的软件包进…

计算机统考分数短信显示合格,今年起全省八年级网考信息技术 成绩不合格不能升高中...

4月11日&#xff0c;省教育厅正式公布我省初中信息技术学业水平考试实施办法&#xff0c;明确从2019年起全面实施初中信息技术学业水平考试&#xff0c;考试对象为八年级(初二)学生&#xff0c;考试时间为每年5月下旬。今年首次参加信息技术学业水平考试的学生为2017年秋季入学…

在Spring中使用JTA事务管理

2019独角兽企业重金招聘Python工程师标准>>> Spring 通过AOP技术可以让我们在脱离EJB的情况下享受声明式事务的丰盛大餐&#xff0c;脱离Java EE应用服务器使用声明式事务的道路已经畅通无阻。但是很大部分人都还认为脱离Java EE应用服务器就无法使用JTA事务&#x…

Window7无法访问 Window server 2008 R2文件服务器的共享

最近碰到奇怪的问题&#xff0c;原来的R2文件服务器一直都正常&#xff0c;突然win7系统不能访问此服务器的共享了&#xff0c;Ping和远程都可以&#xff0c;而且XP系统也可以访问其共享&#xff0c;就是Win7不行&#xff0c;表现为&#xff1a;按IP访问好久没反应&#xff0c;…

第一季7:海思的根文件系统的概览与制作

一、根文件系统理论 关于根文件系统的原理&#xff0c;可以参看以下博客。 根文件系统的原理 使用BusyBox制作根文件系统的理论分析 二、海思的根文件系统 1、海思的根文件系统体现在Hi3518E_SDK_V1.0.3.0\package\rootfs_uclibc目录。 而根文件系统大部分工作由etc/init.d/…

破坏计算机系统既遂的标准,破坏计算机信息系统罪的量刑标准是什么

只有当我们知道了破坏计算机系统罪的定义我们才知道这个罪有多严重&#xff0c;如果触犯会受到怎样的处罚。所以破坏计算机信息系统罪实际意义是&#xff1a;某些人通过对计算机信息系统中正储存的数据&#xff0c;正在处理的数据以及正在传输的数据和针对相关的应用程序进行恶…

关于shell脚本编程一些有用资源的小结

系统维护管理过程中&#xff0c;编写一些能减轻管理负担的shell脚本是个明智的做法&#xff0c;一些例程性的事务&#xff0c;shell脚本会比手动操作高效的多。我有时也要编写一些&#xff0c;总结了一些学习及参考的shell资料&#xff0c;实用好用为主&#xff0c;大家看看有没…

五.几何对象和空间参考

几何对象是ArcGIS Engine中最基本的也是最常用的对象&#xff0c;我们所说的空间对象&#xff08;点&#xff0c;线&#xff0c;面&#xff09;都是几何对象&#xff0c;我们在删除&#xff0c;创建和进行地理分析的时候&#xff0c;就是处理一个包含几个对象的矢量图形。 Geom…

第一季8:完整版(即包含mpp)根文件系统的制作

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 一、概述 mpp是海思编写的与视频编解码有关的驱动、库等内容。我们需要部署这些内容&#xff0c;也就是把这些内容放在合适的目录位置。 二、mpp的目录结构 mpp目录位于Hi3518E_SDK_V1.0.3.0\pack…

计算机三级会保研加分吗,366所高校有保研资格,除了对成绩有要求外,还有哪些要求?...

文&#xff5c;冷丝栏目&#xff5c;考研录取我国本科院校有1000余所&#xff0c;具有保研资格的高校有366所&#xff0c;这些高校也是在不同年份按照不同批次获得保研资格。(本文文末附录全部高校名单)推免制度最初的目的上为了提高招生工作的质量&#xff0c;并且加大培养拔尖…