昨天,参加了一场笔试和面试。对于我这个初入软件,想要转行的名符其实的“菜鸟”来说,打击不少,几个月的“苦读”,原以为基本知识涉猎的差不多的我,迎来了一次真正的笔试与面试。两个小时的笔试,对于我来说,内容有些难度,涉及到一些数据结构的知识,也让只会看书,疏于“上机”的我感到一片茫然。毕竟,理念到实践的转换与成熟运用需要真枪实弹的练习,而我只是学会了“纸上谈兵”。具体的细节,待我把所有的相关的知识梳理好之后再发一篇博文。面试的大哥问了我关于.so文件的内容,我真心不太懂,回家的路上我一直在考虑这个问题。先把目前完全一无所知的知识及时补充一下。下面我把自己的理论与实践写出来,供大家批判。
参照了博文http://hi.baidu.com/buptwinnie/item/6031fdcfeecf752ca1b50aff,先表示感谢。
.so共享文件相对于linux来说,就如同.dll文件相对于windows。windows下的.dll文件编程,可以建立专门的.dll文件,将程序编写好导出,生成文件。然后在主文件中导入调用就可以实现,具体的细节也不是很了解。但对于linux 下的.so文件来说,情况有些不同。下面,我先把自己已经实现的过程贴出来。(环境:WINDOWS7下的32位ubuntu12.10 虚拟机)
- 先编写被调用的函数文件 add.c ,sub.c,operation.h
-
// operation.h #ifndef _OPERATION_H #define _OPERATION_H extern int add(int,int); extern int sub(int,int); #endif
//add.c #include "operation.h" int add(int x,int y) { return x+y; }
//sub.c #include "operation.h" int sub(int x,int y) { return x-y; }
- 生成共享库文件liboperation.so
gcc add.c sub.c -fPIC -shared -o liboperation.so
- 编写主文件test001.c ,在主函数main中调用共享库文件中的函数add(),sub()
//test001.c #include "operation.h" #include "stdio.h" int main() { int result=0; int a=add(3,5); int b=sub(8,6); result=add(a,b); printf("the result is : %d",result); }//不用”#include "operation.h"时,编译也可以成功
- 将主文件与共享库链接生成可运行文件 test001
gcc test001.c -L. -loperation -o test001
先说明一下几个参数的意思:
-fPIC :参照博客中的解释是此参数实现真实的文件共享,位置固定,所有调用该文件内函数的操作都指向同一个位置。而如果不加此参数,只是调用了副本。(关于这个参数的检验,是否涉及到同步的一些问题,是否需要信号量,临界区等??)
-shared:生成共享库文件
-L:编译链接生成可执行文件时,指定所需要链接的共享库文件.so所在的目录,一般是放在当前目录,所以参数为-L. 别忘了写上.符号表示当前目录。
-l: 编译链接时,编译器会主动将-l后面接的名字XXX前面加上lib,后面加上.so,构成libXXX.so,然后到-L参数所指定的目录寻找该共享库文件。
-o:指定所生成的文件名,在生成共享库时,生成库文件名,在生成可执行文件时,生成可执行文件名。
还有参数-l本例中没有用到
如果我们生成共享库文件与生成可执行文件时不在同一个目录下,那么在编译链接可执行文件时,往往要用-L来寻找共享库文件所在的目录。而如果生成共享库时需要用到的头文件(自己定义的头文件)不在共享库所在的目录内时,就要指定头文件所在的目录。同样,在生成可执行文件时,如果include 某自己编辑的头文件,而该文件不在当前目录里时。都要用到-I参数。语法与-L相同
这时可以先用ldd test001 查看否能找到liboperation.so文件。如果是第一次编写.so共享文件,一定会出现找不到该共享文件的情况liboperation.so=》not found
说明系统找不到该共享文件,因为无法确定其目录,即使该文件编译好到放在了当前目录,也要指定该目录的具体的位置。有的博客上要求修改/etc/ld.so.conf文件,在其后加入该共享文件的目录(本例中是在当前目录),尝试后仍不行(目前原因不明)。于是,采用了第二种方法http://blog.csdn.net/csdnxw/article/details/1650650,在/etc/ld.so.conf.d目录下新建XXX.conf文件,在文件里写上共享文件所在的目录(注意后缀.conf似乎不是必要的,我试着修改过去掉了.conf仍然可以找到,这与系统的一切机制相关了,菜鸟不懂,但看到第一种方法中提到的/etc/ld.so.conf文件中只有include /etc/ld.so.conf.d/*.conf有点不解,似乎要求要有.conf),再执行/sbin/ldconfig命令,这样可执行文件test001,就可以正常运行了。这就能回答面试中提出的那个问题,如果当前文件需要调用的共享库文件提示找不到,该如何解决,可以在bash下运行find / -name liboperation.so找到目录,再将该目录添加到/etc/ld.so.conf.d目录下的某个文件中。
如果想要修改函数的功能,只要修改相应函数的文件,然后重新生成共享文件即可。
PS:第一次写这种技术类的文章分享,的确很不容易,那些乐于分享的人致敬!
面试后的小尝试(linux下.so共享文件的创建)