Android架构分析之基于Android系统的C应用程序开发
作者:刘昊昱
博客:http://blog.csdn.net/liuhaoyutz
Android版本:2.3.7_r1
Linux内核版本:android-goldfish-2.6.29
本文介绍基于Android系统的C应用程序开发。我们知道,Android应用程序开发使用的是JAVA语言,但有时候我们也需要一些基于命令行的小程序,这些小程序一般使用C语言开发,程序的写法与PC平台的C程序没有区别,但需要把C程序注册到Android系统中,使其能在Android平台上运行。在这篇博客中,我们就写一个基于Android平台的C应用程序,该程序用来访问我们在上篇博客中创建的底层Linux驱动程序example。
创建development/example_test/example_test.c文件,其代码如下:
1#include <stdio.h>
2#include <unistd.h>
3#include <fcntl.h>
4#include <string.h>
5#include <sys/types.h>
6#include <sys/stat.h>
7
8#define DEVICE_FILE "/dev/example"
9
10int main(int argc, char *argv[])
11{
12 int ret = 0, num = 12, val = 0, fd = 0;
13
14 fd = open(DEVICE_FILE, O_RDWR);
15 if(fd < 0)
16 {
17 printf("open device error!\n");
18 return -1;
19 }
20
21 ret = write(fd, &num, sizeof(int));
22 if(ret < 0)
23 {
24 printf("write device error!\n");
25 return -1;
26 }
27
28 printf("write val %d to device!\n", num);
29
30 ret = read(fd, &val, sizeof(int));
31 if(ret < 0)
32 {
33 printf("read device error!\n");
34 return -1;
35 }
36
37 printf("read val = %d\n", val);
38
39 return 0;
40}
这个C程序打开/dev/example,向该设备寄存器写入一个数字12,再读取设备寄存器,所以读取得到的值应该也是12。
创建development/example_test/Android.mk文件,该文件用于注册本模块到Android系统中,其内容如下:
1LOCAL_PATH:= $(call my-dir)
2include $(CLEAR_VARS)
3
4LOCAL_SRC_FILES := $(call all-subdir-c-files)
5
6LOCAL_MODULE := example_test
7LOCAL_MODULE_TAGS := optional
8include $(BUILD_EXECUTABLE)
要看明白这个Android.mk,需要对Android编译系统有一个全面了解,这里,我不打算全面分析Android编译系统,只对这个Android.mk进行单独的分析。
第1行,定义变量LOCAL_PATH,其内容是通过$(call my-dir)语句调用自定义函数my-dir赋值的。这个my-dir函数定义在build/core/definitions.mk文件中的106-120行,其作用是返回这个Android.mk所在的目录。
第2行,包含变量CLEAR_VARS,这个变量定义在build/core/config.mk文件的第54行:
CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk
变量BUILD_SYSTEM定义在build/core/main.mk文件的第46行
BUILD_SYSTEM := $(TOPDIR)build/core
所以,变量CLEAR_VARS就是build/core/ clear_vars.mk。打开该文件,可以看到,这个文件的作用就是将除LOCAL_PATH以外的全部编译相关变量清零。
第4行,设置变量LOCAL_SRC_FILES,其内容是通过$(call all-subdir-c-files)语句调用自定义函数all-subdir-c-files赋值的。all-subdir-c-files函数定义在build/core/definitions.mk文件中的195-202行,其作用是返回当前目录及其子目录下的所有".c"文件文件名。
第6行,设置变量LOCAL_MODULE为example_test。即模块名。
第7行,设置变量LOCAL_MODULE_TAGS为optional。
第8行,包含变量BUILD_EXECUTABLE,该变量定义在build/core/config.mk文件的第60行:
BUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mk
即包含build/core/executable.mk,包含这个文件表明是要编译成一个可执行程序。
编写完C程序源码和Android.mk,我们就可以编译C应用程序了。有两种编译方法
方法一:在模块Android.mk所在目录下执行mm命令,系统就会对该模块进行编译。
方法二:在Android主目录下执行mmm 模块路径名,这里即mmm development/example_test,系统也同样能开始对模块进行编译。
mmm和mm分别表示对指定目录和当前目录下的模块进行编译,这两个命令都定义在build/envsetup.sh文件中,我们在编译Android之前,首先要执行source build/envsetup.sh命令,这样才能使用这两个命令。
编译完模块后,在out/target/product/generic/system/bin目录下就能看到example_test程序,这就是我们写的C应用程序。
下一步是重新打包文件系统system.img,把example_test程序包含进文件系统镜像中,命令如下:
# make snod
重新启动Android模拟器:
# emulator -kernel kernel/goldfish/arch/arm/boot/zImage
进入命令行界面,执行C应用程序:
# adb shell
# example_test
write val 12 to device!
read val = 12
可以看到我们的C应用程序example_test访问Linux内核驱动程序example成功了。
更多推荐
所有评论(0)