打印
[嵌入式linux]

busybox疑难杂症 求救!!

[复制链接]
5750|38
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
eee|  楼主 | 2009-6-28 19:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
# ls
bin         helloworld  lost+found  root        tmp
dev         lib         mnt         sbin        usr
etc         linuxrc     proc        sys
# helloworld
-/bin/sh: helloworld: not found
# ./helloworld
-/bin/sh: ./helloworld: not found
#
如上
busybox 1.14.2 静态链接,helloworld是可拟行文件,我另外下载了一个动态链接编译好的busybox,可以执行helloworld。可是我编译的这个就是死活不行,改文件名,移动目录都不行!!

相关帖子

来自 2楼
goosen| | 2009-6-30 15:48 | 只看该作者

re

对于出现莫名其妙的问题,
若确定是动态链接,则基本可以确认是所使用的编译器库版本与rootfs中的库的不一致导致的

一个良好的习惯:确保使用的编译器与rootfs中库版本一致。同时,对于busybox,建议使用静态编译(strip后,应该才9百多k)
这样的话,出现问题,首先可确定不是busybox的问题。

使用特权

评论回复
板凳
一朝成名| | 2009-6-28 19:21 | 只看该作者

你这个hello world是静态还是动态?

使用特权

评论回复
地板
eee|  楼主 | 2009-6-28 19:26 | 只看该作者

如果是链接出问题,那也不会报 not found吧?

使用特权

评论回复
5
sinanjj| | 2009-6-28 21:06 | 只看该作者

ls -al看看

使用特权

评论回复
6
eee|  楼主 | 2009-6-29 09:24 | 只看该作者

问题已解决,多谢

二楼给了很重要的提示.
因为我的busybox是静态链接的所以没向,没向板子里面copy动态库,helloworld是默认编译,gcc在默认编译下是动态链接标准库的,我将gcc的动态标准库copy到板子上就正常了.
但是在这里不得不鄙视一下gcc和linux
1.找不到动态库居然只提示;"not found",纯粹误导用户
2.gcc -static指定静态链接情况下一个简单的printf()居然编译出来50M的可执行文件!我分析了一下目标文件发现,gcc把其它没有用到的函数全给链接进来了!!这是为什么?!我用的是glibc

使用特权

评论回复
7
sinanjj| | 2009-6-29 09:32 | 只看该作者

.............

你用的啥系统啊???
.gcc -static指定静态链接情况下一个简单的printf()居然编译出来50M的可执行文件!

使用特权

评论回复
8
lelee007| | 2009-6-29 10:37 | 只看该作者

hello如果静态编译的话,应该相当的不小吧

哈哈,没有静态编译过

待会试试看

使用特权

评论回复
9
sinanjj| | 2009-6-29 12:35 | 只看该作者

我静态编译过很多东西也没这么大过

$ ldd test
    not a dynamic executable
$ ls -al
-rwxr-xr-x 1 industry industry 574060 2009-06-29 12:30 test

这个才500多KB

使用特权

评论回复
10
EEE| | 2009-6-29 17:30 | 只看该作者

我看错了,是500k

不过我认为500K那也是不对头

使用特权

评论回复
11
sinanjj| | 2009-6-29 18:34 | 只看该作者

500k正常

建议LZ学习下静态库和动态库的基本知识

使用特权

评论回复
12
cool_coder| | 2009-6-29 22:21 | 只看该作者

吓我一跳,原来是0.5MB呀

使用特权

评论回复
13
eee|  楼主 | 2009-6-30 12:30 | 只看该作者

0.5M正常?

8楼有没有分析过一个就只有调printf()的代码,GCC会把那些标准库里的函数给链接进来?

为了简化问题我写了如下一个代码,没有调任何函数。
int main()
{
 int i,j;
 for(j = 0, i = 0;i < 100; i++)
    j += i;
 return 0;
}
这个代码
gcc -static xx.c -o xx -O3
编译后有 556743byte
gcc -static xx.c -o xx
编译后有 556775byte
gcc -nostdlib xx.c -o xx
编译后有 662byte,提示没有发现入口符号_start
那么这500K的代码在做什么?全在初始化?
我用vc6.0 release 使用动态MFC编译是16K,不用MFC或静态MFC是36K,这才叫正常!
我的答案是GCC的linker太傻,把没用到的标准库一股脑全link进来了!
ps:请8楼给在下指点一下静态库和动态库的基本知识




使用特权

评论回复
14
sinanjj| | 2009-6-30 14:41 | 只看该作者

500kb是正常的

“8楼有没有分析过一个就只有调printf()的代码,GCC会把那些标准库里的函数给链接进来?”
----------------500Kb并没有把标准库里的函数链接进来。

“那么这500K的代码在做什么?全在初始化?
我用vc6.0 release 使用动态MFC编译是16K,不用MFC或静态MFC是36K,这才叫正常!
我的答案是GCC的linker太傻,把没用到的标准库一股脑全link进来了!”
------------------要解释这个问题, 首先要清楚
1,我们常用的可执行文件不是纯2进制指令组成的,而是由一定标准规定的。linux下使用了国际标准elf格式。windows下自定义标准:pe。
2,你没有包含stdlib并不代表你除去的就是stdlib的库。libc的库有多大呢?仔细看看大小,一般的没有X的linux上,除了内核就是它了,我看到的这个大小还是压缩后的。
 
 清楚了以上,我们就可以分析这个问题的原因了。
我认为这是由于elf格式本身的因素造成的。具体原因因为本人只看过elf格式的标准没看过pe(微软也没公开)格式的标准也不得而知。

我们可以做一个小例子来证明下。

使用特权

评论回复
15
sinanjj| | 2009-6-30 14:46 | 只看该作者

接上

$cat test1.c
int main()
{}
$cat test.c
int main()
{
printf("aaaa");
}
$gcc -o test1 test1.c -static
$gcc -o test test.c -static

然后比对一下test和test1的差距,大于100byte,这100byte应该才是printf函数。

如果你认为printf调用占了这么大, 你可以再做个实验,看看2个printf编译出来的程序多大。

使用特权

评论回复
16
sinanjj| | 2009-6-30 14:53 | 只看该作者

为什么要用elf?

那么我们为什么要用elf格式呢?

(ps:不加static比比vc的看哪个大)

因为这是标准的,比如:哪个位代表什么意思,这里该放什么字段。如何找链接库等。
标准的东西受到绝大部分操作系统支持,这也是为什么unix linux mac可以2进制可执行文件通用的原因。(不能执行的大部分是因为依赖的库)包括andorid,也是静态编译完了就能跑的。

这就是标准的好处。

为什么微软不遵守标准?这个一方面是因为历史和技术能力原因,一方面还是为了和别人不兼容,造就根深蒂固的垄断。

使用特权

评论回复
17
eee|  楼主 | 2009-7-1 09:30 | 只看该作者

继续讨论关于链接的问题

1.我不认为这500k是elf造成的.对elf和PE我都没有去了解过,所以现在我只能推测、想当然。但是不管是elf和PE本质都是在二进制代码上加了个壳,执行程序时PE格式是由系统脱壳装载,难道elf是自装载的?如果elf也是由系统装载的,那么PE和elf在功能上没有什么大的差别.那么在功能上差别不大的两件东西在数据量上会差别那么大?至于elf和pe熟优势劣不是我所关心的,linux和windows制定不同的标准的出发点也并不见得有多少差别,另外对于一个有确定性解的技术问题也不存在技术能力问题
2. 14楼的代码这100byte的差别并不是printf本身造成的,这是call printf的差别,而实现printf的代码远远不至100byte,因为你指定nostdlib,所以gcc没有把printf给链接进来。我在12楼已经把问题给简化,说明了这500k不是printf。我的观点是,这500k东西包括但不限于,elf壳,初始化,代码本身。因为这些东西占不了那么多,所以最大的可能是把一些没有用到的标准库给链进来了,如果不是那会是什么?是一张**mm图?哈哈哈

to楼上
   我的busybox是静态链接的,我的程序全是静态链接的,因为我认为在一个封闭的嵌入式系统上用动态链接一点必要都没有.正因为这样所以没往根目录上放动态库,面helloworld是动态的,所以就出问题,但是他提示not found误导我,很无语.

  

使用特权

评论回复
18
一朝成名| | 2009-7-1 09:37 | 只看该作者

此话题置顶讨论

使用特权

评论回复
19
goosen| | 2009-7-1 16:43 | 只看该作者

to eee

再重复一遍发过的,
1)对于出现莫名其妙的问题,
若确定是动态链接,则基本可以确认是所使用的编译器库版本与rootfs中的库的不一致导致的

2)一个良好的习惯:确保使用的编译器与rootfs中库版本一致。同时,对于busybox,建议使用静态编译(strip后,应该才9百多k)
这样的话,出现问题,首先可确定不是busybox的问题。

不存在误导不误导的问题。可参考1)(经验,个人觉得也没必要深究),对于2),这个是需要你来确保的。
要知道的是,是库版本的不一致(不一致,是否会正常工作、或别的什么提示,我想,还 与这个不一致的程度相关的)

使用特权

评论回复
20
sinanjj| | 2009-7-1 20:14 | 只看该作者

继续给大家讲解历史

"1.我不认为这500k是elf造成的.对elf和PE我都没有去了解过,所以现在我只能推测、想当然。但是不管是elf和PE本质都是在二进制代码上加了个壳,执行程序时PE格式是由系统脱壳装载,难道elf是自装载的?如果elf也是由系统装载的,那么PE和elf在功能上没有什么大的差别.那么在功能上差别不大的两件东西在数据量上会差别那么大?至于elf和pe熟优势劣不是我所关心的,linux和windows制定不同的标准的出发点也并不见得有多少差别,另外对于一个有确定性解的技术问题也不存在技术能力问题"
----------------------------------------首先elf格式是"脱壳装载"的, 脱壳器/lib/ld-linux.so.2.
功能上没什么区别?区别大了.大到可以改变现在软件格局的程度.
关于标准, 首先我所知道的是: linux下的标准全是国家化的,由权威组织制定的, 然后由开源软件实现. windows下的标准是微软自己制定的, 从来不管什么ISO什么ANSI之类, 运动员也是裁判员.

就elf格式标准的制定, 那是在80年代, 那个时候还没微软里, 全是unix机器, unix也是开源的啊, IBM弄个, sun弄个, 为了统一标准, 一个国家化组织(当时的美国标准)制定了elf格式.这个格式的先进性在于: 只要你符合了这个格式, 那么只要是同一硬件平台(2进制指令相同), 无论在哪编译的, copy完了就能跑.

也就是说:elf格式是与操作系统无关的. 无论什么操作系统, 只要符合elf标准,  那么你上边能跑的软件我这边也能跑.

大家可以看出微软如何采取elf格式的后果: 我们的什么office什么游戏, 全可以在*nix下跑, 你说这个是不是改变格局, 是不是有利于我们, 当然不利于微软, 于是, .....大家都知道的. pe格式. 在elf格式改改, 改什么? 当然是那些平台无关的信息都给剪掉. 好, 我们被微软绑架了.

那么elf和pe哪个好? elf是通用的, 肯定更加复杂, 包含的头信息更多, pe好实现, 而且要垄断 ,于是微软把精简的elf改了个名pe.

现在你该清楚为什么pe和elf如此类似.



使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

eee

3

主题

38

帖子

0

粉丝