linux
openssl库的使用?
一、openssl库的使用?
开源代码的软件库,可以用来进行安全通信,防止信息被窃听。
二、linux下如何安装openssl包?
1.解压openssl-0.9.8k.tar.gz
2.从终端(命令行)进入解压出来的目录openssl-0.9.8k下,在命令行执行./config --prefix=/usr
3.执行make
4.执行sudo make install 安装完看看usr/include目录下有没有openssl文件夹,有就安装完成,可以直接引用里面的md5.h了
三、openssl库文件位置不对怎么解决?
不进行make install安装的话,就在你openssl的源码目录里,当然你config的时候需要指明shared,否则只有.a的,没有.so的。
如果config的时候,指定了prefix,那么就到你指定的目录去找,下面应该有个lib目录。
如果你的linux自带openssl的话,系统的lib目录下就有。libcrypto和libssl
四、linux常见依赖库?
查询Linux应用程序运行依赖哪些库
一法:
$(CROSS_COMPILE)ldd AppName
如:
arm_v5t_le-lld test
二法:
$(CROSS_COMPILE)objdump -x AppName |grep NEED
如:
arm_v5t_le-objdump -x test |grep NEED
三法:
$(CROSS_COMPILE)readelf -a AppName |grep "Shared library"
如:
arm_v5t_le-readelf -a test |grep "Shared library"
五、openssl使用详解?
OpenSSL 是一个开源项目,其组成主要包括一下三个组件:
openssl:多用途的命令行工具
libcrypto:加密算法库
libssl:加密模块应用库,实现了ssl及tls
openssl可以实现:秘钥证书管理、对称加密和非对称加密 。
1、对称加密
对称加密需要使用的标准命令为 enc ,用法如下:
openssl enc -ciphername [-in filename] [-out filename] [-pass arg] [-e] [-d] [-a/-base64]
[-A] [-k password] [-kfile filename] [-K key] [-iv IV] [-S salt] [-salt] [-nosalt] [-z] [-md]
[-p] [-P] [-bufsize number] [-nopad] [-debug] [-none] [-engine id]
常用选项有:
-in filename:指定要加密的文件存放路径
-out filename:指定加密后的文件存放路径
-salt:自动插入一个随机数作为文件内容加密,默认选项
-e:可以指明一种加密算法,若不指的话将使用默认加密算法
-d:解密,解密时也可以指定算法,若不指定则使用默认算法,但一定要与加密时的算法一致
-a/-base64:使用-base64位编码格式
示例:
加密:]# openssl enc -e -des3 -a -salt -in fstab -out jiami
解密:]# openssl enc -d -des3 -a -salt -in fstab -out jiami
2、单向加密
单向加密需要使用的标准命令为 dgst ,用法如下:
openssl dgst [-md5|-md4|-md2|-sha1|-sha|-mdc2|-ripemd160|-dss1] [-c] [-d] [-hex] [-binary]
[-out filename] [-sign filename] [-keyform arg] [-passin arg] [-verify filename] [-prverify
filename] [-signature filename] [-hmac key] [file...]
常用选项有:
[-md5|-md4|-md2|-sha1|-sha|-mdc2|-ripemd160|-dss1] :指定一种加密算法
-out filename:将加密的内容保存到指定文件中
示例如下:
单向加密除了 openssl dgst 工具还有: md5sum,sha1sum,sha224sum,sha256sum ,sha384sum,sha512sum
示例如下:
3、生成密码
生成密码需要使用的标准命令为 passwd ,用法如下:
openssl passwd [-crypt] [-1] [-apr1] [-salt string] [-in file] [-stdin] [-noverify] [-quiet] [-table] {password}
常用选项有:
-1:使用md5加密算法
-salt string:加入随机数,最多8位随机数
-in file:对输入的文件内容进行加密
-stdion:对标准输入的内容进行加密
示例如下:
4、生成随机数
生成随机数需要用到的标准命令为 rand ,用法如下:
openssl rand [-out file] [-rand file(s)] [-base64] [-hex] num
常用选项有:
-out file:将生成的随机数保存至指定文件中
-base64:使用base64 编码格式
-hex:使用16进制编码格式
示例如下:
5、生成秘钥对
首先需要先使用 genrsa 标准命令生成私钥,然后再使用 rsa 标准命令从私钥中提取公钥。
genrsa 的用法如下:
openssl genrsa [-out filename] [-passout arg] [-des] [-des3] [-idea] [-f4] [-3] [-rand file(s)] [-engine id] [numbits]
常用选项有:
-out filename:将生成的私钥保存至指定的文件中
-des|-des3|-idea:不同的加密算法
numbits:指定生成私钥的大小,默认是2048
一般情况下秘钥文件的权限一定要控制好,只能自己读写,因此可以使用 umask 命令设置生成的私钥权限,示例如下:
ras 的用法如下:
openssl rsa [-inform PEM|NET|DER] [-outform PEM|NET|DER] [-in filename] [-passin arg] [-out filename] [-passout arg]
[-sgckey] [-des] [-des3] [-idea] [-text] [-noout] [-modulus] [-check] [-pubin] [-pubout] [-engine id]
常用选项:
-in filename:指明私钥文件
-out filename:指明将提取出的公钥保存至指定文件中
-pubout:根据私钥提取出公钥
示例如下:
6、创建CA和申请证书
使用openssl工具创建CA证书和申请证书时,需要先查看配置文件,因为配置文件中对证书的名称和存放位置等相关信息都做了定义,具体可参考 /etc/pki/tls/openssl.cnf 文件。
(1)、创建自签证书
第一步:创建为 CA 提供所需的目录及文件
第二步:指明证书的开始编号
]# echo 01 >> serial
第三步:生成私钥,私钥的文件名与存放位置要与配置文件中的设置相匹配;
第四步:生成自签证书,自签证书的存放位置也要与配置文件中的设置相匹配,生成证书时需要填写相应的信息;
命令中用到的选项解释:
-new:表示生成一个新证书签署请求
-x509:专用于CA生成自签证书,如果不是自签证书则不需要此项
-key:生成请求时用到的私钥文件
-out:证书的保存路径
-days:证书的有效期限,单位是day(天),默认是365天
(2)颁发证书
在需要使用证书的主机上生成证书请求,以 httpd 服务为例,步骤如下:
第一步:在需要使用证书的主机上生成私钥,这个私钥文件的位置可以随意定
第二步:生成证书签署请求
第三步:将请求通过可靠方式发送给 CA 主机
第四步:CA 服务器拿到证书签署请求文件后颁发证书,这一步是在 CA 服务器上做的
查看证书信息的命令为:
(3)吊销证书
吊销证书的步骤也是在CA服务器上执行的,以刚才新建的 httpd.crt 证书为例,吊销步骤如下:
第一步:在客户机上获取要吊销证书的 serial 和 subject 信息
第二步:根据客户机提交的 serial 和 subject 信息,对比其余本机数据库 index.txt 中存储的是否一致
第三步:执行吊销操作
第四步:生成吊销证书的吊销编号 (第一次吊销证书时执行)
]# echo 01 > /etc/pki/CA/crlnumber
第五步:更新证书吊销列表
]# openssl ca -gencrl -out /etc/pki/CA/crl/ca.crl
查看 crl 文件命令:
]# openssl crl -in /etc/pki/CA/crl/ca.crl -noout -text
六、openssl如何使用?
以Nginx对OpenSSL的使用为入口,来分析OpenSSL的API的模型。OpenSSL是两个库,如果以握手为目的只会使用libssl.so这个库,但是如果有加密的需求,会使用libcrypto.so这个库。Nginx中对于OpenSSL的使用大部分是直接使用的libssl.so的接口API的,但是仍然会有少部分使用libcrypto.so。除了Nginx,本章还会分析一个s_server程序,通过这个程序的设计,能够对OpenSSL的内部架构有一个初探。
Nginx的Stream中SSL的实现
Nginx的Stream Proxy中有对于SSL的Terminator的支持。这个终端的意思是可以在Nginx层面把SSL解掉,然后把明文传输给后端。也就是说支持SSL的Nginx的Stream模块实际上是一个TLS的握手代理,将TLS信道在本地解了再发送到后端,所以整个过程是一个纯粹的握手过程,至于ALPN这种功能就需要后端与TLS的配合才可以,所以这种行为在stream 的SSL中是不能支持的。
这是一个Nginx的Stream SSL模块相关的函数列表,主要的Stream模块特有的功能也都就在这个列表里了。可以看到除去配置和模块的整体初始化函数,只剩下一个连接初始化,ssl的入口handler和握手的handler。显然握手的handler是入口handler的深入部分。鉴于Nginx的异步模型,可以很容易的想到是Nginx在收到一个连接的时候首先使用ssl_handler作为通用入口,在确定是SSL连接之后就会切换到handshaker_handler作为后续的握手handler函数。
但是Nginx在支持SSL的时候并不是这样的轻松,因为大量的SSL相关函数在ngx_event_openssl.c文件里,这个文件里的函数被HTTP模块和Stream模块或者其他需要SSL支持的模块共同使用。包括Session Cache等Nginx重新实现的OpenSSL功能。通过这个例子可以看到如果要自己实现一个SSL支持,我们需要两个东西,一个是SSL的用户端的接口封装库(ngx_event_openssl.c),一个是如何把封装库的逻辑嵌入到我们的代码流程的逻辑。Nginx作为一个强大的负载均衡设备,这一部分的接口嵌入应该是要追求的最小化实现的。也就是说Stream模块相关的代码越少越好(ngx_stream_ssl_module.c)。所以我们可以看到几乎就几个钩子函数的定义。
无论是Stream还是HTTP模式,整个TLS握手的核心函数都是ngx_ssl_handshake函数。我们看这个函数就能看到一个企业级的握手接口的使用案例。以下是一个简化版的函数流程:
以上是一个同步版本的大体逻辑,异步版本的就没有显示。可以看到主要的SSL握手的入口函数是SSL_do_handshake。如果握手正常,函数返回1之后,使用SSL_get_current_cipher或得到服务器根据客户端发来的密码学参数的列表选择得到的密码学套件。这里会返回服务器选择的那个,如果返回为空,那么就代表了服务器没有找到匹配的套件,连接就不能继续。SSL_CIPHER_description函数输入活的指针,返回一个字符串格式的套件的描述信息,Nginx这里使用了这个信息,最后一步就是查找当前的Session Cache中是否有可以复用的逻辑。这里只是一个查询,并不是就是复用的决定。因为是否复用是在连接建立之前由配置决定的,如果Nginx配置了不使用OpenSSL的Session Cache,这个查询就会一直返回0,表示没有被复用。而且这里查询的OpenSSL中是否有复用,并不代表Nginx内部是否有复用,Nginx内部还有一套自己的Session Cache实现,但是使用SSL_开头的API函数都是OpenSSL的接口。
这个简单的接口可以看出对OpenSSL的API的使用的一些端倪。OpenSSL提供的API非常多,我们写一个简单的示例程序仅仅会用到几个最简单的接口,例如SSL_new等。但是一个正式的项目,会用到很多细节的API接口。由于OpenSSL只会暴露他认为应该暴露的API函数出来给调用者使用,其他的函数调用者是用不到的,并且OpenSSL内部的结构体外部也是不能使用的,所以使用者所有的行为都是要基于API进行设计。
OpenSSL分为libcrypto.so和libssl.so两个库。在使用TLS握手的时候,主要的调用API都位于ssl.h文件中定义,都是SSL_开头的API。但是这并不意味着只能调用libssl.so的接口,高级的用户并不是想要使用OpenSSL的TLS握手功能,完全可以直接调用libcrypto.so里面的各种各样的密码学库。总的来说libssl.so是一个TLS握手库,而libcrypto.so是一个通用的密码学的库。只是libssl.so的握手使用的密码学是完全依赖libcryto.so中提供的。也就是因此,在使用TLS握手的时候,是基本上不会直接用到libcrypto.so中的API的。
s_server
openssl s_server是一个简单的SSL服务器,虽然说是简单,但是其中包含了大部分用户SSL编程需要考虑的东西。证书,密码,过期校验,密码学参数定制,随机数定制等等。这是一个功能性的程序,用于验证openssl内部的各项SSL握手服务器的功能是否能够正常使用,并不能用于直接服务于线上业务。
s_server程序启动的第一步是解析各种参数,在正常运作的时候,第一步是加载key。
我们看到OpenSSL内部调用的函数和在使用OpenSSL库接口的时候是不一样的,OpenSSL的子程序会调用一些内部的接口。比如这里使用了ENGINE_init,直接初始化了底层的引擎系统。ENGINE系统是OpenSSL为了适配下层不同的数据引擎设计的封装层。有对应的一系列API,所有的ENGINE子系统的API都是ENGINE_开头的。一个引擎代表了一种数据计算方式,比如内核的密码学套件可以有一个专门的OpenSSL引擎调用到内核的密码学代码,QAT硬件加速卡也会有一个专门的引擎,OpenSSL自己的例如RSA等加密算法的实现本身也是一个引擎。这里在加载key的时候直接初始化一个引擎,这个引擎在init之前还要先调用一个setup_engine函数,这个函数能够设置这个将要被初始化的引擎的样子。s_server之所以要自己用引擎的API接口是因为它支持从命令行输入引擎的参数,指定使用的引擎。
可以看到,如果指定了auto,就会加载所有默认的引擎。如果指定了特定ID的引擎,就只会加载特定的引擎。一个引擎下面是所有相关的密码学的实现,加载key就是一个密码学层面的操作,所以也要使用ENGINE提供的接口。事实上,最后都是分别调用了对应的ENGINE的具体实现,这中间都是通过方法表的指针的方式完成的。ENGINE定义的通用的接口还有很多,这里只是用到了加载密钥。
表内都是对不同的EVP_CIPHER和EVP_MD的接口的定义。
我们回到加载key的函数,继续阅读发现一个 key = bio_open_default(file, 'r', format); 这个key是一个BIO类型的指针,这个BIO类型的指针就是另外一个OpenSSL的子系统,所有的IO操作都会被封装到这个子系统之下。例如这里使用的文件IO,用于从文件中读取key的结果。BIO被设计为一个管道式的系统,类似于Shell脚本中见到的管道的效果。有两种类型的BIO,一种是source/sink类型的,就是我们最常见的读取文件或者Socket的方式。另外一种是管道BIO,就是两个BIO可以通过一个管道BIO连接起来,形成一个数据流。所以BIO的方式是一个很重量级的IO系统的实现,只是目前只是被OpenSSL内部使用的比较多。
继续向下阅读加载密钥的函数,会发现PEM_read_bio_PrivateKey函数,这一步就是实际的从一个文件中读取密钥了。我们现在已经有了代表文件读写的BIO,代表密码学在程序中的封装EVP,中间缺的桥梁就是文件中密钥存储的格式。这里的以PEM_开头的函数就代表了PEM格式的API。PEM是密码学的存储格式,PEM_开头的API就是解析或者生成这种格式的API,当然它需要从文件中读取,所以参数中也会有BIO的结构体,PEM模块使用BIO模块提供的文件服务按照定义的格式将密钥加载到内存。
OpenSSL的所有apps都会共享一些函数,这些函数的实现都在一个apps.c文件中,以上的加载密钥的函数也是其中的一个。s_server程序在调用完load_key之后会继续调用load_cert来加载证书。load_cert使用的子系统与load_key非常类似,类似的还有后面的load_crl函数,CRL(Certificate revocation lists)是CA吊销的证书列表,这项技术已经基本被OCSP淘汰。OpenSSL还提供一个随机数文件的功能,可以从文件中加载随机数。
s_server在加载完相关的密码学相关参数后,就会开始创建上下文,SSL_CTX_new函数的调用就代表了上下文的创建。这个上下文是后面所有SSL连接的母板,对SSL的配置设置都会体现在这个上下文的设置中。随后,s_server会开始设置OpenSSL服务器支持的TLS握手版本范围,分别调用SSL_CTX_set_min_proto_version和SSL_CTX_set_max_proto_version两个函数完成所有操作。
OpenSSL在共享TLS握手的Session时,需要生成一个Session ID,默认的情况,OpenSSL会在内部决定Session ID怎么生成。但是也提供了用户设置这个生成算法的API。s_server程序调用SSL_CTX_set_generate_session_id函数设置一个自己的回调函数,在这个回调函数中就可以完成Session ID的设置,从而取代掉OpenSSL自带的内部Session ID的生成器。OpenSSL在证书协商的时候还会允许外部的库使用者动态的修改采用的证书,这个机制是通过SSL_CTX_set_cert_cb来设置证书回调函数实现的。s_server也有这个函数的设置。程序走到这里,基本能看到OpenSSL的一个很大的特性,就是大部分的内部流程都会提供一个回调函数给使用者来注册,使用者可以按照自己的需求取代掉或者修改OpenSSL内部的功能。显然这个s_server程序是一个功能展示的程序,会用上大量的函数回调点。比如紧接着调用的SSL_CTX_set_info_callback函数就是在生成SSL的时候调用的,可以用于使用者获得状态。不但OpenSSL外部的机制可以在用户端设置,用户甚至可以设置加密算法的参数。例如s_server就会接下来根据用户是否提供DH参数来设置内部的参数。如果调用了SSL_CTX_set_dh_auto就意味着参数是使用内部的机制生成,这也是默认的行为。但是仍然可以提前提供,主要是为了性能的考虑,比如提前提供DH的大素数,DH算法在运算的过程中需要一个取模操作,这个取模是对一个大素数进行取模的,而这个大素数默认是在运行的时候动态生成的,但是我们可以提供这个素数,从而以牺牲一定的安全性为代价换来性能的提高。
s_server在设置完整个上下文之后,就会进入Socket监听和处理的模式。由于BIO框架包含了Socket的能力,所以这一步本质上就是调用BIO的接口。
这是一个典型的OpenSSL的Socket逻辑。BIO_sock_init这个函数在Linux下就是空函数,没有意义。BIO_lookup是一个通用的获取地址的方法,对于Socket就是IP:PORT的字符串,对于文件是文件的目录。BIO_socket意思就相当于在使用Socket变成的socket函数。BIO_listen也就自然对应listen函数,BIO_accept_ex和BIO_closesocket也是类似的意思。整个流程其实就与一个普通的Socket流程没有太大区别,只是BIO多了一层封装。因为OpenSSL是个跨平台的库,这层封装更多的意义在于用在跨平台的应用上的。
通过一个简单的s_server程序的分析可以看到整个OpenSSL的主要设计思路。它对外封装了不同的模块,例如ENGINE,EVP,BIO之类的封装。在大部分的流程上都提供了回调函数API,使用者可以用回调函数来修改OpenSSL原来的逻辑或者获得其他的信息。在使用OpenSSL的时候一般需要遵循类似的流程,就是创建上下文,然后配置上下文,然后运行服务。
七、linux怎么卸载boost库?
查看boost安装版本:
$dpkg-s/usr/include/boost/version.hpp
卸载boost:
$sudoapt-getautoremovepackage
(注:package为要卸载的boost的名称示例:sudoapt-getautoremovelibboost1.55-dev)
更新boost:
$sudoadd-apt-repositoryppa:boost-latest/ppa
$sudoapt-getupdate
八、linux怎么指定线程库?
大概的介绍一下Linux 的指定CPU运行,包括进程和线程。linux下的top命令是可以查看当前的cpu的运行状态,按1可以查看系统有多少个CPU,以及每个CPU的运行状态。 可是如何查看线程的CPU呢?
top -Hp pid,pid就是你当前程序的进程号,如果是多线程的话,是可以查看进程内所有线程的CPU和内存使用情况。
pstree可以查看主次线程,同样的pstree -p pid。可以查看进程的线程情况。
taskset这个其实才是重点,可以查看以及设置当前进程或线程运行的CPU(设置亲和力)。
taskset -pc pid,查看当前进程的cpu,当然有的时候不只是一个,taskset -pc cpu_num pid ,cpu_num就是设置的cpu。 这样的话基本的命令和操作其实大家都知道了,接下来就是在代码中完成这些操作,并通过命令去验证代码的成功率。 进程制定CPU运行:
[cpp] view plain copy #include #include #include #include #include #define __USE_GNU #include #include #include int main(int argc, char* argv[]) { //sysconf获取有几个CPU int num = sysconf(_SC_NPROCESSORS_CONF); int created_thread = 0; int myid; int i; int j = 0; //原理其实很简单,就是通过cpu_set_t进行位与操作 cpu_set_t mask; cpu_set_t get; if (argc != 2) { printf("usage : ./cpu num\n"); exit(1); } myid = atoi(argv[1])
; printf("system has %i processor(s). \n", num)
; //先进行清空,然后设置掩码 CPU_ZERO(&mask); CPU_SET(myid, &mask)
; //设置进程的亲和力 if (sched_setaffinity(0, sizeof(mask), &mask) == -1) { printf("warning: could not set CPU affinity, continuing...\n"); } while (1) { CPU_ZERO(&get); //获取当前进程的亲和力 if (sched_getaffinity(0, sizeof(get), &get) == -1) { printf("warning: cound not get cpu affinity, continuing...\n"); } for (i = 0; i < num; i++) { if (CPU_ISSET(i, &get)) { printf("this process %d is running processor : %d\n",getpid(), i); } } } return 0; } 进程设置CPU运行,其实只能是单线程。多线程设定CPU如下:
[cpp] view plain copy #define _GNU_SOURCE #include #include #include #include #include #include void *myfun(void *arg) { cpu_set_t mask; cpu_set_t get; char buf[256]; int i; int j; //同样的先去获取CPU的个数 int num = sysconf(_SC_NPROCESSORS_CONF); printf("system has %d processor(s)\n", num); for (i = 0; i < num; i++) { CPU_ZERO(&mask); CPU_SET(i, &mask); //这个其实和设置进程的亲和力基本是一样的 if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0) { fprintf(stderr, "set thread affinity failed\n"); } CPU_ZERO(&get); if (pthread_getaffinity_np(pthread_self(), sizeof(get), &get) < 0) { fprintf(stderr, "get thread affinity failed\n"); } for (j = 0; j < num; j++) { if (CPU_ISSET(j, &get)) { printf("thread %d is running in processor %d\n", (int)pthread_self(), j); } } j = 0; while (j++ < 100000000) { memset(buf, 0, sizeof(buf)); } } pthread_exit(NULL); } int main(int argc, char *argv[]) { pthread_t tid; if (pthread_create(&tid, NULL, (void *)myfun, NULL) != 0) { fprintf(stderr, "thread create failed\n"); return -1; } pthread_join(tid, NULL); return 0; }
九、linux动态库和静态库的区别?
动态链接库和静态链接库一般是编译集成一系列的接口(函数)
在程序源代码编译完成后通过编译器编译并通过链接器与这些库进行链接
动态链接库与静态链接库的区别在于链接器在进行链接时静态库会被直接编译进程序里
而动态链接库并不会,我们这里将这些链接库称作依赖(动态库和静态库)
程序的运行需要这些依赖,程序在静态链接后该程序本身便已包含该依赖
而动态链接后的程序本身本不包含该依赖,这些依赖需要执行者自行安装进操作系统(动态库、运行时库)
程序运行时会动态地加载这些库
linux上动态库一般的后缀后为.so
静态库一般的后缀为.a
由于静态链接会直接将库编译进程序里所以静态编译后的程序相较于动态链接所要大
这就是因为静态链接会将链接库编译进程序里的原因,所以占用就要大了
出于这种原因,静态库不易于维护与更新,如果链接库中有实现有bug等需要更新则需要更新整个程序,因为静态库被编译进程序中了
但动态库就没有这种情况了,因为动态库是程序运行时动态加载的,所以我们只需要更新动态库而不需要更新所有依赖该库的程序(软件)
另一方面,很多程序的开发都会使用到相同的链接库,也就是很多程序(软件)会有相同的依赖
如果将这些依赖全部静态编译的话将会造成存储资源占用过多而造成资源浪费
而使用动态库的方式这些程序(软件)则可以共享一个链接库,而不需要每个程序都带一个链接库,这样就大大地减少了存储资源占用空间
十、linux windows静态库和动态库的区别?
两者区别:
a,静态库的使用需要:
1包含一个对应的头文件告知编译器lib文件里面的具体内容
2设置lib文件允许编译器去查找已经编译好的二进制代码
b,动态库的使用:
程序运行时需要加载动态库,对动态库有依赖性,需要手动加入动态库
c,依赖性:
静态链接表示静态性,在编译链接之后,lib库中需要的资源已经在可执行程序中了,也就是静态存在,没有依赖性了
动态,就是实时性,在运行的时候载入需要的资源,那么必须在运行的时候提供需要的动态库,有依赖性,运行时候没有找到库就不能运行了
d,区别:
简单讲,静态库就是直接将需要的代码连接进可执行程序;动态库就是在需要调用其中的函数时,根据函数映射表找到该函数然后调入堆栈执行。
做成静态库可执行文件本身比较大,但不必附带动态库
做成动态库可执行文件本身比较小,但需要附带动态库
链接静态库,编译的可执行文件比较大,当然可以用strip命令精简一下(如:striplibtest.a),但还是要比链接动态库的可执行文件大。程序运行时间速度稍微快一点。
静态库是程序运行的时候已经调入内存,不管有没有调用,都会在内存里头。静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。
其在编译程序时若链接,程序运行时会在系统指定的路径下搜索,然后导入内存,程序一般执行时间稍微长一点,但编译的可执行文件比较小;动态库是程序运行的时候需要调用的时候才装入内存,不需要的时候是不会装入内存的。
动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。
动态链接库的特点与优势
首先让我们来看一下,把库函数推迟到程序运行时期载入的好处:
1.可以实现进程之间的资源共享。
什么概念呢?就是说,某个程序的在运行中要调用某个动态链接库函数的时候,操作系统首先会查看所有正在运行的程序,看在内存里是否已有此库函数的拷贝了。如果有,则让其共享那一个拷贝;只有没有才链接载入。这样的模式虽然会带来一些“动态链接”额外的开销,却大大的节省了系统的内存资源。c的标准库就是动态链接库,也就是说系统中所有运行的程序共享着同一个c标准库的代码段。
2.将一些程序升级变得简单。用户只需要升级动态链接库,而无需重新编译链接其他原有的代码就可以完成整个程序的升级。windows就是一个很好的例子。
3.甚至可以真正坐到链接载入完全由程序员在程序代码中控制。
程序员在编写程序的时候,可以明确的指明什么时候或者什么情况下,链接载入哪个动态链接库函数。你可以有一个相当大的软件,但每次运行的时候,由于不同的操作需求,只有一小部分程序被载入内存。所有的函数本着“有需求才调入”的原则,于是大大节省了系统资源。比如现在的软件通常都能打开若干种不同类型的文件,这些读写操作通常都用动态链接库来实现。在一次运行当中,一般只有一种类型的文件将会被打开。所以直到程序知道文件的类型以后再载入相应的读写函数,而不是一开始就将所有的读写函数都载入,然后才发觉在整个程序中根本没有用到它们。
静态库:在编译的时候加载生成目标文件,在运行时不用加载库,在运行时对库没有依赖性。
动态库:在目标文件运行时加载,手动加载,且对库有依赖性。
具体在开发中用到哪种库,我觉得还是根据实际的内存大小,rom大小,运行的速度等综合考虑。
热点信息
-
在Python中,要查看函数的用法,可以使用以下方法: 1. 使用内置函数help():在Python交互式环境中,可以直接输入help(函数名)来获取函数的帮助文档。例如,...
-
一、java 连接数据库 在当今信息时代,Java 是一种广泛应用的编程语言,尤其在与数据库进行交互的过程中发挥着重要作用。无论是在企业级应用开发还是...
-
一、idea连接mysql数据库 php connect_error) { die("连接失败: " . $conn->connect_error);}echo "成功连接到MySQL数据库!";// 关闭连接$conn->close();?> 二、idea连接mysql数据库连...
-
要在Python中安装modbus-tk库,您可以按照以下步骤进行操作: 1. 确保您已经安装了Python解释器。您可以从Python官方网站(https://www.python.org)下载和安装最新版本...