Helper2416开发板学习③搭建/lib链接库

接着上一篇文章,上一篇文章将系统的/etc文件夹做了一个简单的搭建,不能说完整,但是至少能保证内核可以正常使用。好了,现在内核的运行环境搭建好了,内核也成功的起来了,接着我们也要为我们自己写的程序准备准备环境了,也就是搭建动态链接库。

这里需要了解静态编译和动态编译的概念。

先说说动态编译,动态编译就是编译器使用动态链接库进行链接编译,在实际开发过程中,各个模块之间会涉及到一些通用的功能,比如读写文件,查找、排序。为了减少代码的冗余,提高代码的质量,可以将这些通用的部分提取出来,做出公共的模块库也叫动态链接库。通过动态链接库可以实现多个模块之间共享公共的函数。这样我们自己编写的程序可以只包含自身功能程序,很多通用的库函数都可以使用动态链接库调用,这样用户程序可以很小,但是运行速度会相对较慢。

再说说静态编译,很显然静态编译和动态编译的原理相反,静态编译就是将所有函数都放到一个可执行文件中去,不依赖与任何链接库,自己就能搞定一切!我很喜欢这种风格,但是这样不太实际,最现实的一点就是如果每个应用程序都使用静态编译的话生成的可执行文件就会很大,这样会导致磁盘空间(nandflash、emmc等)占用较大,可执行文件加载速度也会变慢,并且会占用很多内存空间,要知道嵌入式系统中磁盘空间和内存空间都是比较有限的。所以静态编译不是经常使用。当然不是一定不会用到,第一篇文章里面编译busybox的时候对busybox进行静态编译,这样我们就不需要准备动态链接库就能直接使用busybox命令,否则如果不选定静态编译busybox是无法运行的,除非将busybox依赖的库文件都放到/lib文件夹中去。

我们可以做个试验,在根文件系统下创建一个简单的程序a.c:

#include "stdio.h"

void main()
{
        printf("tangquan,test\r\n");
}

使用交叉编译器进行动态编译:

tq@ubuntu:~/work/nfsroot/helper2416-rootfs$ /home/tq/work/arm-2014.05/bin/arm-none-linux-gnueabi-gcc a.c -o tar
tq@ubuntu:~/work/nfsroot/helper2416-rootfs$ ls
a.c  bin  dev  etc  home  lib  linuxrc  mnt  proc  sbin  sys  tar  tmp  usr  var

得到可执行文件tar,然后在开发板上运行:

/ # ./tar 
-/bin/sh: ./tar: not found

嗯?什么情况,没有找到tar文件?

/ # ls
a.c       etc       mnt       sys       tmp
bin       home      proc      tangquan  usr
dev       linuxrc   sbin      tar       var

很显然文件是存在的,出现这个错误的原因是因为该可执行文件所链接的库文件找不到,我们可以使用readelf命令看看可执行文件所需要链接的库文件:

tq@ubuntu:~/work/nfsroot/helper2416-rootfs$ /home/tq/work/arm-2014.05/bin/arm-none-linux-gnueabi-readelf -a tar | grep Shared
 0x00000001 (NEEDED)                     Shared library: [libgcc_s.so.1]
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]

也可以使用ldd命令查看,但是这个交叉编译器没有提供ldd命令,这里就不说了。很显然我们编译得到的可执行文件需要链接libgcc和libc两个库文件。

然后我们再对源文件进行一次静态编译:

tq@ubuntu:~/work/nfsroot/helper2416-rootfs$ /home/tq/work/arm-2014.05/bin/arm-none-linux-gnueabi-gcc a.c -o tar --static
tq@ubuntu:~/work/nfsroot/helper2416-rootfs$ ls -alh
total 688K
drwxrwxr-x 14 tq   tq   4.0K Sep 14 08:29 .
drwxrwxr-x  3 tq   tq   4.0K Sep  8 07:20 ..
-rw-rw-r--  1 tq   tq     66 Sep 13 08:13 a.c
-rw-------  1 root root 1.4K Sep 14 08:29 .ash_history
drwxr-xr-x  2 root root 4.0K Sep 13 08:07 bin
drwxrwxr-x  3 tq   tq   4.0K Sep 13 04:56 dev
drwxrwxr-x  4 tq   tq   4.0K Sep 13 07:37 etc
drwxrwxr-x  2 tq   tq   4.0K Sep  5 07:42 home
drwxrwxr-x  2 tq   tq   4.0K Sep 14 08:01 lib
lrwxrwxrwx  1 root root   11 Sep  6 08:10 linuxrc -> bin/busybox
drwxrwxr-x  2 tq   tq   4.0K Sep  5 07:42 mnt
drwxrwxr-x  2 tq   tq   4.0K Sep  5 07:42 proc
drwxr-xr-x  2 root root 4.0K Sep  6 08:10 sbin
drwxrwxr-x  2 tq   tq   4.0K Sep 13 04:46 sys
-rwxrwxr-x  1 tq   tq   621K Sep 14 08:30 tar
drwxrwxr-x  2 tq   tq   4.0K Sep  5 07:42 tmp
drwxr-xr-x  4 root root 4.0K Sep  6 08:10 usr
drwxrwxr-x  2 tq   tq   4.0K Sep  5 07:42 var

得到的tar文件的大小是621K,已经很大了,动态编译得到的可执行文件只有6.5K而已,要知道程序里面只是进行了一个简单的打印而已。而后我们在开发板上运行可执行文件:

/ # ./tar 
tangquan,test

成功运行,验证了上面的说法。

好了我们还是要使用动态链接库的,我们可以编译链接库的源码得到链接库,但是很麻烦了就,生成动态链接库的方法可以参考我之前的两篇文章:http://blog.csdn.net/tq384998430/article/details/72673736http://blog.csdn.net/tq384998430/article/details/72673290。我们不需要自己编译库源码,我们只要将交叉编译器中现成的库文件拷贝到根文件系统中去就行了:

tq@ubuntu:~/work$ cp arm-2014.05/arm-none-linux-gnueabi/libc/armv4t/lib/*  nfsroot/helper2416-rootfs/lib/  -a

注意需要加上“-a”选项,保证链接文件的正常链接指向。然后我们在一次进行动态编译得到可执行文件后在开发板上运行:

/ # ./tar 
tangquan,test

成功运行,说明程序链接到了我们做好的库。

后面我们需要其他的库的时候再进行添加即可。

上一篇:P4180 [BJWC2010]严格次小生成树


下一篇:python linux crontab计划任务设置