不得不说,老罗写的太好了。
按照他的方法,我两次就成功了。
不过有点让人奇怪的地方就是
第一次我make snod是成功的
但是执行如下代码:
root@android:/ # cd system/bin
root@android:/system/bin # ./hello
的时候,确发生了错误。第一次可能是因为我没有
执行$ source ./build/envsetup.sh
和$ lunch full-eng
结果ut/target/product/gerneric/system/bin只有一个hello,其他的文件都不见了。
第二次,我又操作了一边,成功了。
转自:http://blog.csdn.net/luoshengyang/article/details/6571210
在前一篇文章中,我们介绍了如何在Ubuntu上为Android系统编写Linux内核驱动程序。在这个名为hello的Linux内核驱动程序中,创建三个不同的文件节点来供用户空间访问,分别是传统的设备文件/dev/hello、proc系统文件/proc/hello和devfs系统属性文件/sys/class/hello/hello/val。进一步,还通过cat命令来直接访问/proc/hello和/sys/class/hello/hello/val文件来,以验证驱动程序的正确性。在这一篇文章里,我们将通过自己编写的C可执行程序来访问设备文件/dev/hello。可能读者会觉得奇怪,怎么能在Android系统中用C语言来编写应用程序呢?Android系统上的应用程序不都是Java应用程序吗?其实是可以的,读者不妨用adb shell命令连上Android模拟器,在/system/bin目录下可以看到很多C可执行程序,如cat命令。今天,我们就来学习一下怎么在Android系统中添加用C语言编写的可执行程序吧。
一. 参照在Ubuntu上为Android系统编写Linux内核驱动程序一文,准备好Linux驱动程序。使用Android模拟器加载包含这个Linux驱动程序的内核文件,并且使用adb shell命令连接上模拟,验证在/dev目录中存在设备文件hello。
二. 进入到Android源代码工程的external目录,创建hello目录:
USER-NAME@MACHINE-NAME:~/Android$ cd external
USER-NAME@MACHINE-NAME:~/Android/external$ mkdir hello
三. 在hello目录中新建hello.c文件:
- #include <stdio.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #define DEVICE_NAME "/dev/hello"
- int main(int argc, char** argv)
- {
- int fd = -1;
- int val = 0;
- fd = open(DEVICE_NAME, O_RDWR);
- if(fd == -1) {
- printf("Failed to open device %s.\n", DEVICE_NAME);
- return -1;
- }
- printf("Read original value:\n");
- read(fd, &val, sizeof(val));
- printf("%d.\n\n", val);
- val = 5;
- printf("Write value %d to %s.\n\n", val, DEVICE_NAME);
- write(fd, &val, sizeof(val));
- printf("Read the value again:\n");
- read(fd, &val, sizeof(val));
- printf("%d.\n\n", val);
- close(fd);
- return 0;
- }
这个程序的作用中,打开/dev/hello文件,然后先读出/dev/hello文件中的值,接着写入值5到/dev/hello中去,最后再次读出/dev/hello文件中的值,看看是否是我们刚才写入的值5。从/dev/hello文件读写的值实际上就是我们虚拟的硬件的寄存器val的值。
四. 在hello目录中新建Android.mk文件:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := hello
LOCAL_SRC_FILES := $(call all-subdir-c-files)
include $(BUILD_EXECUTABLE)
注意,BUILD_EXECUTABLE表示我们要编译的是可执行程序。
五. 参照如何单独编译Android源代码中的模块一文,使用mmm命令进行编译:
USER-NAME@MACHINE-NAME:~/Android$ mmm ./external/hello
编译成功后,就可以在out/target/product/gerneric/system/bin目录下,看到可执行文件hello了。
六. 重新打包Android系统文件system.img:
USER-NAME@MACHINE-NAME:~/Android$ make snod
这样,重新打包后的system.img文件就包含刚才编译好的hello可执行文件了。
七. 运行模拟器,使用/system/bin/hello可执行程序来访问Linux内核驱动程序:
USER-NAME@MACHINE-NAME:~/Android$ emulator -kernel ./kernel/common/arch/arm/boot/zImage &
USER-NAME@MACHINE-NAME:~/Android$ adb shell
root@android:/ # cd system/bin
root@android:/system/bin # ./hello
Read the original value:
0.
Write value 5 to /dev/hello.
Read the value again:
5.
看到这个结果,就说我们编写的C可执行程序可以访问我们编写的Linux内核驱动程序了。
介绍完了如何使用C语言编写的可执行程序来访问我们的Linux内核驱动程序,读者可能会问,能不能在Android的Application Frameworks提供Java接口来访问Linux内核驱动程序呢?可以的,接下来的几篇文章中,我们将介绍如何在Android的Application Frameworks中,增加Java接口来访问Linux内核驱动程序,敬请期待。
老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注!
-
顶
- 43
-
踩
- 0
-
40楼
gulingyun789 4天前 11:12发表 [回复]
- android中跑c应用程序,lz这个是一种方法,不过貌似过程多,不过对于学习确实很好的资料,还有简单的方法,就是安装交叉编译工具,直接arm-none-linux-gnueabi-gcc -static -o hello hello.c , 然后push到手机上,chmod下hello的权限,./hello运行
-
38楼
lovebeyond1014 2013-06-02 23:46发表 [回复]
- 谢谢楼主,已买书支持!
-
37楼
livagain1988 2013-03-21 14:57发表 [回复]
- 你好,我按照您的方法都实现了,除了最后make snod,虽然前面在 bin中生成了hello二进制可执行文件,但是make snod以后,从虚拟机进入/system/bin文件夹并没有hello这个可执行文件,为什么make snod未能将hello重新打包进新的system.img呢? 望给些意见
-
36楼
all8023 2013-03-21 10:35发表 [回复]
- 罗老师,请教个问题,我在友善的tiny210v2板子上实验,板子里的系统里有led灯的驱动,也有基于android 的测试程序,我想直接写个C程序按照本文的编译方法测试一下它自带的驱动(厂家已把led驱动编译到内核里),但是根据C程序打印的信息来看能正常执行,就是灯不亮,麻烦帮忙分析一下。
-
34楼
binglansong 2012-12-26 17:10发表 [回复]
- 请问楼主,我是装的实体机的ubuntu,用天嵌的安卓源码,没有可以装mmm命令的可执行文件啊,你帖子里讲的东西,不在虚拟机,在实体机上可以实现吗
-
33楼
xzjlcyz 2012-12-18 11:18发表 [回复]
- 好吧,是百万
-
31楼
longkg 2012-11-21 15:28发表 [回复]
-
按照老罗的Android.mk,我的系统编译没办法通过,说找不到main的入口。后来加入了下面两句就通过了
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
LOCAL_EXPORT_LDLIBS := -llog
我的系统是4.0.3
-
30楼
yuzhoulangzi2008 2012-10-23 17:32发表 [回复]
- 相当精彩。。。
-
29楼
binghezhouke 2012-08-14 16:49发表 [回复]
- 楼主,发现一个小问题,c语言换行的时候是不是应该是“\n”啊
-
28楼
jeffade 2012-07-18 10:46发表 [回复]
-
你好,我编译的时候出现一下错误。不知博主能否给些建议。谢谢
make:进入目录'/home/weide/share/android/android_gingerbread'
make: *** 没有规则可以创建“out/target/product/generic/obj/EXECUTABLES/myled_intermediates/LINKED/myled”需要的目标“out/target/product/generic/obj/lib/crtbegin_dynamic.o”。 停止。
-
26楼
lqxandroid2012 2012-07-09 16:20发表 [回复]
-
不错,不错,我还以为只能在linux kernel下写呢。不过是我们脑子太僵硬,HAL 就是c语言写的,这样写肯定可以的了。呵呵。
不过楼主是原生态,android,我的S5pv210的android2.3 居然不支持 mmm ./external/hello
编译
只能make hello.so 来编译。-
Re:
lqxandroid2012 2012-07-09 16:46发表 [回复]
-
回复lqxandroid2012:晕,居然make hello.so 也不出来,不知道咋回事提示错误
说 make 没有 创建hello. so 的规则。咋回事啊
用楼主的mmm 命令也是一样的结果。
提示mmm 找不到命令..............-
Re:
lqxandroid2012 2012-07-09 16:55发表 [回复]
- 回复lqxandroid2012:搞定了, 晕死,是我自己没注意楼主前一篇文章,看的不够仔细,出来了。呵呵。
-
Re:
罗升阳 2012-07-09 16:49发表 [回复]
-
回复lqxandroid2012:mmm命令要加载一个脚本之行之后才能用,具体可以参照这篇文章:http://blog.csdn.net/luoshengyang/article/details/6566662
-
Re:
lqxandroid2012 2012-07-10 20:15发表 [回复]
-
回复Luoshengyang:搞定了,没注意楼主的文章的精髓啊。 我linux 菜鸟来的。
所以开始 少了个. 也没报错,但是就是不行,O(∩_∩)O哈哈~
楼主你差不多可以整理书籍了,北航的编辑应该会主动找你的。
-
25楼
yang5856 2012-02-25 15:58发表 [回复]
-
楼主你好,mmm ./externel/hello/输出如下
make: Entering directory `/home/Android-Prj'
make: *** No rule to make target `out/target/product/generic/system/lib/libc.so', needed by `out/target/product/generic/system/bin/hello'. Stop.
请问是什么原因,网上也没有搜到这个问题 解决方法。
-
24楼
sulen1943 2012-02-21 10:20发表 [回复]
- 罗老师好,请教您一个问题,Android从2.3开始在源码中放入了NFC芯片的驱动,但是大部分手机厂商编译ROM的时候会把这部分代码裁减掉,请问可不可以自己把这部分代码制作成一个软件包安装入系统内核让其实现对NFC芯片的驱动?(没有手机ROM的源码)我想先确定可行性,可行的话就试试
-
23楼
tcytree 2011-12-21 12:50发表 [回复]
-
楼主:
在源代码\frameworks\base\cmds下有很多类似你这样的程序,并且也有用java写的,我怎么能在里
面写一个类似android的apk的程序,比如,我想写个闹钟,IAlarmManager iAlarmManager = IAlarmManager.Stub.asInterface(ServiceManager.getService(Context.ALARM_SERVICE));
AlarmManager alarmManager = new AlarmManager(iAlarmManager);
但下一步启动闹钟我就没有办法了,无法创建
PendingIntent ,建立它需要context实例,怎么能够在这样的方式下获得一个context实例?请楼主指点.
模仿pm(那有pm的源代码)的代码,写一个android的程序,有可能吗?
。
-
22楼
hongnan006 2011-12-17 14:57发表 [回复]
-
没看过kernel的代码。。。上一篇没看懂。。。
不过楼主写的真的很好,赞一个。。。。
-
20楼
最后一个菜鸟 2011-12-09 10:25发表 [回复]
-
out/target/product/generic/obj/lib/crtbegin_dynamic.o:(.text+0x14): error: undefined reference to 'main'
编译出现此结果,是什么原因?
-
19楼
floweriswho 2011-11-16 23:34发表 [回复]
-
亲 写的 真不错 ! 真想给你一个 好评阿!
只能顶了!
-
18楼
ytllei 2011-11-12 16:25发表 [回复]
-
楼主你好,我在执行mmm ./external/hello的时候,出现以下错误,怎么解决?
make:进入目录'/opt/android/sources/android-sdk-2'
target thumb C: hello <= external/hello/hello.c
external/hello/hello.c: In function 'main':
external/hello/hello.c:18: error: expected ';' before 'read'
make: *** [out/target/product/generic/obj/EXECUTABLES/hello_intermediates/hello.o] 错误 1
-
17楼
yongwong 2011-11-08 16:19发表 [回复]
-
make: *** No rule to make target `out/target/product/generic/system/lib/libc.so', needed by `out/target/product/generic/system/bin/hello'. Stop.
在输出这个信息的前面还有一些google提示的信息。只要在Android.mk中按照提示加入提示内容就可以编译通过了。其实那些英文提示也不复杂。
-
16楼
yuyan19850204 2011-11-04 20:31发表 [回复]
-
楼主你好,我编译这个部分出现个错误,麻烦帮忙看下
最好能够加下QQ啊 谢谢 253815347
yuyan@yuyan-desktop:~/csst/gingerbread_v1.28$ mmm ./external/hello/
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=2.3.1
TARGET_PRODUCT=CSD218
TARGET_BUILD_VARIANT=eng
TARGET_SIMULATOR=
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=GINGERBREAD
============================================
make:进入目录'/home/yuyan/csst/gingerbread_v1.28'
make: *** 没有规则可以创建ut/target/product/CSD218/symbols/system/bin/hello需要的目标out/host/linux-x86/bin/acp停止
make:离开目录home/yuyan/csst/gingerbread_v1.28鈥?
yuyan@yuyan-desktop:~/csst/gingerbread_v1.28$
-
15楼
lifewind 2011-10-12 15:25发表 [回复]
- 楼主你好,根据你的流程,我写了个程序也编译成功了,不过总是帮我生成到symbols/system/bin目录下面,而不是直接的system/bin目录下,看了上面其他人的提问,也试了先make clean,后再编译,还是一样?能否请教一下这个是什么原因啊?
-
14楼
Anotherzhou 2011-10-11 17:56发表 [回复]
-
还有,make snod 后system.img文件有380M,内存溢出,还是直接用make解决掉了。:-)
-
Re:
罗升阳 2011-10-11 23:23发表 [回复]
-
回复Anotherzhou:没有这么大吧,我的只有80M+
-
Re:
Anotherzhou 2011-10-12 10:10发表 [回复]
- 回复Luoshengyang:我也不清楚,我用的是android2.3.3的源代码。后来上网看了make anod的介绍,才知道说这样产生的系统文件不稳定。换成make编译后就好了。总之,谢谢楼主的详细讲解啊,很给力啊!
-
13楼
Anotherzhou 2011-10-11 17:53发表 [回复]
- mmm模块化编译出现的问题太多了,直接make的话,时间又不长,问题又不多。之前那些generic下出现的问题都没有了。谢谢楼主的分享。
-
12楼
simon1206 2011-09-21 21:49发表 [回复]
- 如三楼的问题,最后的结果确实是这样的,但能否修改默认的路径不?关键是我在编译你上两篇模块编译举的例子EMAIL,确实能模块编译通过。
-
11楼
大只辉 2011-09-14 09:29发表 [回复]
- 4、还想请问博主,有没有其他的方法在android系统下测试硬件驱动的方法。亦或者直接在使用linux内核的根目录进行测试程序的编译。如果不使用android根目录下的bionic目录的c库文件行吗?或者有什么其他更好的方法进行c测试程序的编译或者测试。
-
10楼
大只辉 2011-09-14 09:23发表 [回复]
-
3、出错的警告:
root@ubuntu:/home/myandroid# mmm external/watchdog/
…………此处省略400字…………
No private recovery resources for TARGET_DEVICE generic
make: Entering directory `/home/myandroid'
target thumb C: wtd-d901 <= external/watchdog/wtd-d901.c
external/watchdog/wtd-d901.c:10:22: error: watchdog.h: No such file or directory
external/watchdog/wtd-d901.c: In function 'main':
external/watchdog/wtd-d901.c:39: error: 'WDIOC_SETTIMEOUT' undeclared (first use in this function)
external/watchdog/wtd-d901.c:39: error: (Each undeclared identifier is reported only once
external/watchdog/wtd-d901.c:39: error: for each function it appears in.)
external/watchdog/wtd-d901.c:50: error: 'WDIOC_KEEPALIVE' undeclared (first use in this function)
make: *** [out/target/product/generic/obj/EXECUTABLES/wtd-d901_intermediates/wtd-d901.o] Error 1
make: Leaving directory `/home/myandroid'
root@ubuntu:/home/myandroid#
-
9楼
大只辉 2011-09-14 09:20发表 [回复]
-
最近在测试imx51的watchdog驱动,出现了一下问题:
1、watchdog测试程序
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/watchdog.h>
int main(int argc, char *argv[])
{
…………此处省略500字……
ret = ioctl(fd,WDIOC_KEEPALIVE,0);
printf("ret %d\n",ret);
…………
printf("service ok\n");
sleep(sleepval);
…………
}
2、使用mmm命令的时候发现没有找到watchdog.h的头文件
我使用的Android.mk为
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := wtd-d901
LOCAL_SRC_FILES := $(call all-subdir-c-files)
include $(BUILD_EXECUTABLE)
同时我查找了android根目录下所有的watchdog.h的目录:
root@ubuntu:/home/android# find -name watchdog.h
./kernel_imx/include/config/watchdog.h
./kernel_imx/include/config/mxc/watchdog.h
./kernel_imx/include/linux/watchdog.h
./kernel_imx/arch/sparc/include/asm/watchdog.h
./kernel_imx/arch/sh/include/cpu-sh4/cpu/watchdog.h
./kernel_imx/arch/sh/include/asm/watchdog.h
./external/qemu/hw/watchdog.h
-
8楼
wantianpei 2011-09-07 18:47发表 [回复]
-
楼主问你一个makefile的问题:
hardware\tegra\hal\libnvomxmediaplayer\OMXPlayer.cpp
hardware\tegra\core\include\Nvdispmgr.h
上面的C++文件怎么调用下面路径的.h文件?
应该是要修改Android.mk文件吧?怎么修改实现呢?-
Re:
罗升阳 2011-09-08 00:16发表 [回复]
-
回复wantianpei:没试过......不过你可以试一下在Android.mk文件里面指定LOCAL_INCLUDES变量看看,hardware/libhardware目录下的Android.mk文件就是指定了LOCAL_INCLUDES变量,可以参考一下
-
Re:
wantianpei 2011-09-08 10:14发表 [回复]
- 回复Luoshengyang:谢谢楼主提醒.
-
7楼
wantianpei 2011-08-19 13:17发表 [回复]
-
写的非常好.
看了后思路清晰很多.
-
6楼
hui05504 2011-08-03 15:40发表 [回复]
-
fd = open(DEVICE_NAME, O_RDWR);
楼主,这个语句怎么会和内核hello设备驱动的open关联起来的呢?难道是上一篇文章中hello目录下的Kconfig定义了hello设备模块 /dev/hello,通过这个来关联的?
-
5楼
大只辉 2011-08-01 10:34发表 [回复]
-
同时我发现在/out/target/product/generic/symbols/system/lib/目录下有libc.so,是不是路径错了,如果是路径错了,我应该修改那个文件呢?以后编译其他的路径的文件时,是不是都是一样会出现错误呢?
-
Re:
罗升阳 2011-08-01 12:20发表 [回复]
-
回复linhui568:参与一下@hui05504这个兄弟遇到的情况:
1.
楼主,按照你上面的教程,出现了以下错误,
No rule to make target `out/target/product/generic/obj/lib/libhardware.so', needed by `out/target/product/generic/obj/SHARED_LIBRARIES/libandroid_servers_intermediates/LINKED/libandroid_servers.so'. Stop.
,麻烦指导下,谢谢
2.
不好意思,这个错误的出错原因估计是在out/target/product/generic/这个目录下,因为我编译源码的时候不是在generic里生成的,而是在新建的目录底下生成,但是这个命令确默认是在generic的路径,所以出错了-
Re:
大只辉 2011-08-01 14:14发表 [回复]
-
回复Luoshengyang:问题已经解决,就是将/out/target/product/generic/symbols/目录下的system目录整个拷贝到/out/target/product/generic/目录下就行了。再make一次。mmm命令和make snod命令编译都不会出错。
-
Re:
wantianpei 2011-09-07 00:17发表 [回复]
-
回复linhui568:你这样编译system会有问题,虽然依然可以运行起来,但我试着用你那种方法这里提示内存溢出,明显生成的system是有坏区的。
out里面的目录都是make后才产生的,make clean后就没有了。所以说system只能make让它自动产生,不能说自己从别处拷贝过来。
这个问题只需要在 mmm 之前重新make一下就可以了。以后无论是make,还是mmm,还是make clen再make都是没有问题的。
-
4楼
大只辉 2011-08-01 10:24发表 [回复]
-
楼主,我在编译$mmm ./externel/hello的时候出现了一下错误,不知为何?
root@ubuntu:/home/Android# mmm ./external/hello/
============================================
PLATFORM_VERSION_CODENAME=AOSP
PLATFORM_VERSION=3.1.4.1.5.9.2.6.5
TARGET_PRODUCT=full
TARGET_BUILD_VARIANT=eng
TARGET_SIMULATOR=
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=OPENMASTER
============================================
make: Entering directory `/home/Android'
make: *** No rule to make target `out/target/product/generic/system/lib/libc.so', needed by `out/target/product/generic/system/bin/hello'. Stop.
make: Leaving directory `/home/Android'
root@ubuntu:/home/Android#
-
3楼
navycsu 2011-07-28 23:09发表 [回复]
-
楼主你好,按照你的步骤,走到mmm ./external/hello的时候出现以下错误:
No rule to make target `out/target/product/generic/obj/lib/crtbegin_dynamic.o', needed by `out/target/product/generic/obj/EXECUTABLES/hello_intermediates/LINKED/hello'. Stop.
请问该如何解决呢?谢谢....-
Re:
罗升阳 2011-07-28 23:35发表 [回复]
-
回复navycsu:是不是没定义好Android.mk文件?
-
Re:
navycsu 2011-07-28 23:39发表 [回复]
-
回复Luoshengyang:我的mk文件是按照您在文中所讲写的。按照错误提示的意思,好像是说找不到这个文件:out/target/product/generic/obj/EXECUTABLES/hello_intermediates/LINKED/hello'
我看了下,确实没有这个文件,我的文件系统是友善之比tiny6410编译过的文件系统,确实没这个路径...请问楼主知道这个hello文件在哪呢?我手动创建这个目录试试看...-
Re:
罗升阳 2011-07-28 23:44发表 [回复]
-
回复navycsu:你参考一下@hui05504这个哥们的情况:
1.
楼主,按照你上面的教程,出现了以下错误,
No rule to make target `out/target/product/generic/obj/lib/libhardware.so', needed by `out/target/product/generic/obj/SHARED_LIBRARIES/libandroid_servers_intermediates/LINKED/libandroid_servers.so'. Stop.
,麻烦指导下,谢谢
2.
不好意思,这个错误的出错原因估计是在out/target/product/generic/这个目录下,因为我编译源码的时候不是在generic里生成的,而是在新建的目录底下生成,但是这个命令确默认是在generic的路径,所以出错了