经验总结---编译出可以在Android上执行的可执行文件

来源:互联网 发布:在淘宝上买黄金可靠吗 编辑:程序博客网 时间:2024/05/21 20:46

作为一手包揽Ubuntu和Android设备的初级开发者,我不止一次地尝试把这两个同是用Linux内核的操作系统统一起来——让Ubuntu下的可执行程序能够在Android设备上运行。于是我不止一次地尝试,不止一次地查找资料,终于如愿以偿。

我把我的经验在这里与大家分享。


准备工具

【宿主机】

(1)glibc-arm2.1.7库文件——让Android系统能够跑起自己编译好的程序

(2)arm-linux-gcc4.4.3——嵌入式ARM系统的应用程序编译器,这个就不必多说了。运行之前请务必保证设置好环境变量。

【Android设备】

(1)要求已经Root——在没有开启Root权限的情况下,本教程中编译好的程序会无法运行,出现Segmentation Fault的错误。

(2)RE管理器——Android上的文件管理工具,在这里用于复制文件

(3)终端模拟器(建议用Terminal Emulator)——用于调试我们的程序


具体步骤

1.在宿主机上,通过预先用arm-linux-gcc编译,获取程序解释器和共享库文件名

a.在终端中运行:

arm-linux-gcc-o <输出文件名><源代码文件名>

得到可执行文件

b.在终端中运行:

readelf -l <输出文件名>

仔细找找,就可以找到程序解释器的文件名了。一般用方括号扩起,并有”interpreter”(程序解释器)的注明。

c.运行

readelf -d <输出文件名>    

在输出结果中找到”NEEDED”一行。该行最右边就是共享库的文件名。有多少个文件名就有多少个共享库。

d.搞定之后,把输出文件删掉。

之所以要进行这一步,是因为不同的程序对应的程序解释器可能不同。

2.在宿主机上用arm-linux-gcc正式编译出可执行文件

这一步编译出来的可执行文件是要直接放到设备上运行的。

必须使用以下格式:

arm-linux-gcc-o <输出文件名> <源代码文件名> -Wl,-dynamic-linker=/yourpath/<程序解释器文件名>

其中:-dynamic-linker后接程序解释器在设备上的完整路径(注意:不是宿主机上面的路径),下文中该路径直接简称为yourpath

3.把程序解释器、共享库复制出来

进入glibc-arm解压目录中的”lib”文件夹,在其中找到我们之前看到的几个文件。

值得注意的是,一般情况下,glibc-arm的一些库文件会用符号链接,指向另外的库文件。在文件管理器中,符号链接是带有小箭头的。可以通过右击符号链接,选择“属性”,看到它们的对应关系。

如:

ld-linux.so.3==>ld-2.17.so

libc.so.6==>libc-2.17.so

这时我们要把被链接的库文件复制出来,不能只复制带有小箭头的符号链接,否则等于没复制!


4.把可执行文件和库文件复制到设备中。

1)把可执行文件放到systemdatacust这些分区中(它们使用的是ext3yaffs2等文件系统,对Linux命令兼容较好。放到FAT文件系统中很容易出现各种PermissionDenied)。然后设置权限为rwxrwxrwx.

2)安放程序解释器

a。用RE管理器把被链接的程序解释器库文件放到systemdatacust这些分区的任意目录中,记下它所在的路径。

b.接着设置其权限为rwxrwxrwx。(长按该文件,选择“权限”)

c。打开终端,输入:ln-s <被链接的程序解释器库文件名完整路径>/<该库文件的文件名>/yourpath/<程序解释器库文件名>

在设备上建立符号链接。这样就安放好了。

注:Ubuntu下不方便用adb,所以我的做法是:打开设备的USB存储连接,把需要的文件统统拷进去,剩下的复制粘贴、符号链接建立就用RE管理器了。

3)把共享库放到Android的库目录中

Android系统可用的库目录有/system/lib,/vendor/lib,用哪个都行。可在设备上打开终端模拟器,运行echo$LD_LIBRARY_PATH查看。(值得注意的是,在没有运行su的情况下,会看到不止一个目录;但是在su之后,只能使用上述的两个目录。)

安放的方法和(2)类似:

a.RE管理器把被链接的共享库文件放到/system/lib/vendor/lib目录中。

b.接着设置其权限为rwxrwxrwx

c.打开终端,输入:

ln -s <被链接的共享库文件名完整路径>/<该库文件的文件名> /system/lib/<共享库文件名>

或输入:

ln -s <被链接的共享库文件名完整路径>/<该库文件的文件名> /vendor/lib/<共享库文件名>

在设备上建立符号链接。这样就安放好了。

4.在设备上打开终端模拟器进行调试

先运行su,打开root权限,然后切换到可执行文件所在的目录,输入

./<可执行文件名>
回车,即可看到效果。


如果觉得上面的步骤看起来有些晕,不妨看看我在下面举的具体例子!

实例说明

我打算把下面的这段C源代码编译出来,放到我的Android手机上面运行:

【代码内容】

#include<stdio.h>int main(){ int i=0; printf("HELLO ANDROID!"); for(i=0;i<=100;i++)   printf("%d ",i);printf("END");return 0;}


【可执行文件放在】/system/

【可执行文件名】hello4

【程序解释器放在】/system/(我把文件放到/vendor/lib/

【共享库文件放在】/vendor/lib/

【宿主机上的工作目录】/home/administrator/complie/


【具体步骤】

1.预先编译。

在终端中输入:

arm-linux-gcc-o hello41 hello.c

得到临时的可执行文件hello41

然后运行

readelf -l hello41

得知程序解释器的名字(ld-linux.so.3)。再运行readelf-d hello41,得知共享库的名字(libc.so.6)。

如图所示:




2.正式编译

在终端中运行:

arm-linux-gcc-o hello4 hello.c-Wl,-dynamic-linker=/system/lib-linux.so.3

回车即得输出的可执行文件hello4.


3.找到库文件

进入glibc-arm解压目录的lib子目录,找到lib-linux.so.3libc.so.6两个文件。但它们是带有小箭头的符号链接。

这时右击lib-linux.so.3,选择“属性”,查看它链接到的文件,是ld-2.17.so;类似地,得知libc.so.6链接到的文件是libc-2.17.so

ld-2.17.solibc-2.17.so复制出来。





4.把文件复制到设备上。

连上手机,打开USB存储设备,把可执行文件hello4,和上面的两个库文件ld-2.17.solibc-2.17.so都复制到设备的SD卡中。接着关闭USB存储设备,稍等片刻打开RE管理器:

把可执行文件hello4复制到/system/目录中,然后长按该文件,选择“权限”,把上面的9个勾全部勾上(也就是设置rwxrwxrwx权限)。

同理,把ld-2.17.solibc-2.17.so复制到/vendor/lib/,用同样的方法设置权限为rwxrwxrwx

接着打开终端模拟器建立符号链接,运行:

su                                                  //打开管理员权限ln-s /vendor/lib/ld-2.17.so /system/ld-linux.so.3ln-s /vendor/lib/libc-2.17.so /vendor/lib/libc.so.6


就可以了。

P.S.以上创建符号链接的操作也可以用RE管理器搞定,方法:长按文件,把菜单拖到最下面,选择”链接到文件”,进到需要创建符号链接的目录,点击“创建链接”,最后按上面ln命令的写法给符号链接重命名就可以了。


5.打开终端模拟器测试

依次输入

su            //打开管理员权限cd system     //切换到/system目录./hello4      //运行程序


就可以成功看到如下的运行结果:



至此,顺利成功!


相关资源

glibc-arm 库文件:http://download.csdn.net/detail/remme123/5422131  (感谢remme提供)


参考资料

[1]基于glibc的程序在android上的移植—转,andy_1982,http://www.eoeandroid.com/thread-22046-1-1.html

[2][11]缺少动态连接库.so--cannotopen shared object file: No such file or directory,SmartVessel,http://www.cnblogs.com/smartvessel/archive/2011/01/21/1940868.html

[3]bash:***: No such file or directory , seamus,http://blog.csdn.net/dlutxie/article/details/8645051

[4]关于-/bin/sh:命令:notfound的解决办法,micheal7500,http://blog.chinaunix.net/uid-20539088-id-115759.html





0 0
原创粉丝点击