Submitted by admin on 2011, July 19, 3:27 PM
一、grep 参数使用
Gun grep 选项
-b 在搜索到的行的前面打印该行所在的块号码。
-c 只显示有多少行匹配 ,而不具体显示匹配的行
-h 不显示文件名
-i 在字符串比较的时候忽略大小写
-l 只显示包含匹配模板的行的文件名清单,不同项目之间用换行符分隔
-L 打印不匹配模板的文件名清单
-n 在每一行前面打印该行在文件中的行数
-s 静默工作,除非出现错误信息否则不打印任何信息,这个功能在检测退出状态的时候有用
-v 反检索,只显示不匹配的行
-w
-Ax 在匹配指定行打印完毕后,再打印x行(向原文件匹配行下x行)
-By 在匹配指定行前面打印y行(在原文件匹配行上面打印y行)
-Cz 在匹配行前后打印z行 (在原文件匹配行上下打印z行)
-b 在每一行前面打印字符偏移量
-f file 从文件file中提取模板。空文件中包含0个模板
-q 取消标准输出,跟-n功能是一样的
-s 不显示关于不存在或者无法读文件的错误信息
-w 只打印以单词形式匹配模板的行,模板可以是包含数字、字符和下划线的字符串
-x 只打印整行匹配的行
-y 用法同-i
-U 把文件作为二进制文件,这个选项只在MS-DOS和MS-Windows中被支持(这个参数没有明白,请过路高人指点,非常感谢)
-u 按照unix风格报告字符偏移量。只在-b选项同时被使用的时候才有效。这个选项只在MS-DOS和MS-Windows中被支持
grep "$name" file 把变量$name 的值作为模板,在文件中寻找匹配模板的行。注意,必须使用双引号
重复作用的元字符, \{\}; 用来做标签的元字符,\(\); 用来锚定单词的元字符\<\>
二、实例
数据文件
[root@future tmp]# cat newbo
1 aa
2 AA
3 Aa
4
5
[root@future tmp]# cat bo
1
2
sss bo-
3
4
5.8 shell 5 5
6
hello grep 5
[root@future root]# grep -n "" bo
1:1
2:2
3:sss bo-
4:3
5:4
6:5.8 shell 5 5
7:6
8:hello grep 5
[root@future tmp]# grep -i "a" newbo -i关闭大小写敏感
1 aa
2 AA
3 Aa
[root@future tmp]# grep -l '2' * -l 打印匹配的文件名,而不打印匹配的行
bo
newbo
[root@future tmp]# grep -c 'a' newbo 打印有多少匹配行
2
[root@future tmp]# grep -c -i 'a' newbo
3
[root@future tmp]# grep -w 'shell' bo -w打印按照单词方式匹配模板的行,而不是作为单词的一部分匹配模板的行
5.8 shell 5 5
[root@future tmp]# grep -w 'hell' bo
[root@future tmp]#
[root@future tmp]# grep -2 '3' newbo 上下各两行
1 aa
2 AA
3 Aa
4
5
[root@future tmp]# grep -A2 '3' newbo 下两行
3 Aa
4
5
[root@future tmp]# grep -B2 '3' newbo 上两行
1 aa
2 AA
3 Aa
[root@future tmp]# grep -C2 '3' newbo 上下各两行
1 aa
2 AA
3 Aa
4
5
[root@future tmp]#
[root@future tmp]# grep -b '' newbo 打印每一行前打印字符偏移量(不明白具体指的是什么感觉比较抽象,在次请高人指教)
0:1 aa
6:2 AA
12:3 Aa
18:4
20:5
[root@future tmp]# cat regular
1
2
[root@future tmp]# grep -f regular newbo -f 是指从文件中读取模板
1 aa
2 AA
[root@future tmp]#
[root@future tmp]# grep '' *
bo:1
bo:2
bo:sss bo-
bo:3
bo:4
bo:5.8 shell 5 5
bo:6
bo:hello grep 5
newbo:1 aa
newbo:2 AA
newbo:3 Aa
newbo:4
newbo:5
regular:1
regular:2
[root@future tmp]# grep -h '' * -h 使得grep不打印头信息,这个例子中是不打印文件名
1
2
sss bo-
3
4
5.8 shell 5 5
6
hello grep 5
1 aa
2 AA
3 Aa
4
5
1
2
[root@future tmp]# grep -q '' " newbo -q取消grep的所有输出,在只需要退出状态值的场合这个选项就显得非常有用
[root@future tmp]# echo $?
0
[root@future tmp]#
数据文件
[root@future root]# cat bo
1
2
sss bo-
3
4
5.8 shell 5 5
6
hello grep 5
[root@future root]# cat nu
1
ss -bo
2
xx bo-
2222222222
3
4
[root@future root]# grep 2 * 在所有的文件中搜索“2”
bo:2
nu:2
nu:2222222222
[root@future root]# grep '^5' * ^锚定行的开始
bo:5.8 shell 5 5
[root@future root]# grep '5$' bo $锚定行的结尾
5.8 shell 5 5
hello grep 5
[root@future root]# grep '5\..' bo 第一个字符是5,然后紧跟着一个. 尔后是一个任意字符
5.8 shell 5 5
如果点前面有一个反斜杠,则点就不再特殊,而是仅仅表示一个点。
[root@future root]# grep "^[23]" bo 表示开头是以2或3开头的行
2
3
[root@future root]# grep [^0-9] bo 打印所有包含非数字字符的行
sss bo-
5.8 shell 5 5
hello grep 5
[root@future root]# grep '[^0-9]' bo
sss bo-
5.8 shell 5 5
hello grep 5
[root@future root]# grep "[^0-9]" bo
sss bo-
5.8 shell 5 5
hello grep 5
[root@future root]# grep "^[^0-9]" bo 打印所有不是以数字开头的行
sss bo-
hello grep 5
[root@future root]# grep '[a-z]\{5\}' bo 打印每个字符串至少有5个连续小写字母的字符串的行
5.8 shell 5 5
hello grep 5
[root@future root]# grep '^[a-z]\{5\}' bo打印开头字符串至少有5个连续小写字母的字符串的行
hello grep 5
[root@future root]# grep '\(5\)\.[0-9].*\1 *\1' bo 打印第一个字符是5,紧跟着一个句点,然后是任意一个数字,然后是任意字符,然后是一个5,然后是一个任意个制表符,然后又是一个5。
5.8 shell 5 5
[root@future root]# grep '\(5\)\.[0-9] \1 *\1' bo 之所以没有搜索到是因为没有“.*”任意字符
[root@future root]# grep '\(5\)\.[0-9] \1 .*\1' bo
[root@future root]# grep '\(5\)\.[0-9] .* \1 *\1' bo
5.8 shell 5 5
\1 是一个引用,含义是正则表达式中第一个被\(和\)括起来的部分
[root@future root]# grep '\<hel' bo 锚定单词的开头
hello grep 5
[root@future root]# grep '5\>' bo 锚定单词的结尾
5.8 shell 5 5
hello grep 5
[root@future root]# grep '\<hel\>' bo
[root@future root]# grep '\<hello\>' bo 打印所有包含单词hello的行
hello grep 5
[root@future root]# grep 'hello' bo
hello grep 5
[root@future root]# grep '\hello\b' bo \b是单词分界符 没有理解这个参数请路过的高人注解
hello grep 5
[root@future root]# grep '^h\w*\w' bo 也没有理解\w参数,仍然请过路高人注解,万分感激!
hello grep 5
[root@future root]# grep '\<[a-z].*o\>' bo .* 代表任意字符
sss bo-
hello grep 5
[root@future root]# grep '\<[a-z]\{4\}o\>' bo 重复4次,加上前面一次,共5次
hello grep 5
[root@future root]# grep '\<[a-z]\{5\}o\>' bo
[root@future root]# grep '\<[a-z]\{3,20\}o\>' bo
hello grep 5
[root@future root]# grep '\<[a-z]\{6,20\}o\>' bo
[root@future root]# grep '\<[a-z]\{5,20\}o\>' bo
[root@future root]#
[root@future root]# grep '\<[a-z]\{4,20\}o\>' bo 重复4次
hello grep 5
[root@future root]# grep '\<[a-z]\{3,5\}o\>' bo
hello grep 5
[root@future root]# grep '\<[a-z]\{5,6\}o\>' bo
[root@future root]#
注:a\{x,y\}\ 意义是重复a+(x和y之间含x和y)
[root@future root]# grep '2|3' bo grep不支持扩展的正则表达式,竖线是用于表示‘或’的扩展正则表达式元字符。所以没有输出。
[root@future root]# grep '2\|3' bo 加上反斜杠,这个字符就被翻译成扩展正则表达式。
2
3
[root@future root]# grep "\(2\|3\)" bo
2
3
[root@future root]# grep "\(5\)\.8.*\1" bo
5.8 shell 5 5
正则表达式5.8被匹配,模板5 就被存储到内存中的寄存器1内,这个正则表达式的含义是如果5.8被找到,标记并保存5,然后搜索任意个字符(.*),尔后是一个\1代表5
[root@future root]# grep "\(5\).*\1" bo
5.8 shell 5 5
[root@test-linux tmp]# cat te
adlkf adfkl aa 566.5
dfad 234.43 aaa
234 aaaa
adf adfa adf adf 45.556 aaaaa
[root@test-linux tmp]#
[root@test-linux tmp]#
[root@test-linux tmp]#
[root@test-linux tmp]# grep '\baaa\b' te \b 单词分界符
dfad 234.43 aaa
[root@test-linux tmp]#
[root@test-linux tmp]# cat te
adlkf adfkl aa 566.5
dfad. 234.43 aaa
dfad . 234.43 aaa
234 aaaa
adf adfa adf adf 45.556 aaaaa
[root@test-linux tmp]#
[root@test-linux tmp]#
[root@test-linux tmp]#
[root@test-linux tmp]# grep '^d\w' te \w 字母数字字符[a-zA-Z0-9] \W 非字母数字字符
dfad. 234.43 aaa
dfad . 234.43 aaa
[root@test-linux tmp]#
命令 | 评论:0
| Trackbacks:0
| 阅读:810
Submitted by admin on 2011, July 19, 11:51 AM
本文只是叙述Ubuntu下编译环境的搭建和ROM的编译过程,过程中可能会需要一些Ubuntu的常规操作技巧,在本文里就不详细介绍了,Ubuntu的新手可以通过谷歌学习一下,笔者也是新手,刚用没多久,谷歌一下并不难,另外由于源码和编译后生成的文件都比较大,如果想要折腾起来的话,Ubuntu的分区最好能有30G,20G的话一会就用完了,笔者之前也是分了20G,但不一会就空间不足了,故最后格掉分区,重新分了100G给Ubuntu。
编译环境的搭建
JDK安装
a) JDK是Ubuntu下使用Android SDK,编译源代码等必备的软件包,首先我们现来装这个
b) 从sun官方网站下载最新版的JDK,一般是个.bin的文件,笔者下载的是jdk-6u20-linux-i586.bin(根据文件不同,命令的也会有所变化,大家在使用的时候要注意,主要是文件名和路径的变化)。
c) 由于JDK运行时会在当前目录下安装,所以在安装前,先把它移动到你想要安装的目录,比如笔者将其安装在/usr/lib/jvm/java目录下,如果你也想安装在相同目录,可以照着我下面的命令来做
代码:
sudo –i
cd /usr/lib
mkdir jvm
cd jvm
mkdir java
cd java
cp “jdk-6u20-linux-i586.bin所在目录“/jdk-6u20-linux-i586.bin /usr/lib/jvm/java
chmod u+x jdk-6u20-linux-i586.bin
jdk-6u20-linux-i586.bin
此时会出现JDK的安装提示说明,按着回车不放,提示说明会持续滚动,www.linuxidc.com直到屏幕提示需要输入Yes/NO,输入YES后,即开始安装,安装完成后提示按回车继续,按完回车后,安装即告成功
d) 与Windows不同,Ubuntu是没有注册表的,故安装完成后,我们需要把我们安装JDK的目录告诉系统,故在刚才的终端里执行如下命令(如果是新开的终端,没有执行过“sudo -i”,则需要在命令前+“sudo”获得权限)
代码:
gedit /etc/environment
此时在会弹出一个文本编辑器,里面显示
代码:
PATH=”……”
其中省略号部分是其默认的路径,这里我们不要动它,我们需要对这个进行一些修改,将我们的JDK安装路径写进去,告诉系统我们的JDK装在哪里,去哪里调用,故做如下修改:
i. 在原有的 PATH=”……” 的省略号里面添加:
代码:
PATH=”……:/usr/lib/jvm/java/jdk1.6.0_20/bin”
ii. 添加两行,输入如下内容:
代码:
CLASSPATH=.:/usr/lib/jvm/java/jdk1.6.0_20/lib
JAVA_HOME=/usr/lib/jvm/java/jdk1.6.0_20
最后生成如下形式:
代码:
PATH=”……:/usr/lib/jvm/java/jdk1.6.0_20/bin”
CLASSPATH=.:/usr/lib/jvm/java/jdk1.6.0_20/lib
JAVA_HOME=/usr/lib/jvm/java/jdk1.6.0_20
其中,省略号部分是文件原有内容,我们在后面新加了一部分内容和两个新行。修改完成后保存退出。
e) Ubuntu有可能会自带JDK或者安装多个JDK,此时需要将我们安装的这个设置为默认
i. 首先,将我们的JDK安装目录加入到JDK的选择菜单,执行如下代码:
代码:
update-alternatives –install /usr/bin/java java /usr/lib/jvm/java/jdk1.6.0_12/bin/java 300
update-alternatives –install /usr/bin/javac javac /usr/lib/jvm/java/jdk1.6.0_12/bin/javac 300
ii. 其次,通过命令来选择默认的JDK,执行如下代码:
代码:
update-alternatives –config java
iii. 最后,再来检查一下系统当前的JDK版本,输入以下代码查看:
代码:
java -version
f) 至此,JDK即告安装成功。
Android SDK安装
a) 既然是做rom,那肯定需要调试和测试的工具,Android的官方SDK同样提供官方版本,我们直接下载安装即可。
b) 去谷歌的官网下载最新的SDK版本,前几天刚跟新了支持2.2的r6,不过SDK的官方网站在墙后,我们只能FQ过去下载,这点比较无奈。官方提供Windows,Mac OS X,Linux三个版本,毫无疑问,我们需要下载Linux的版本。
c) SDK不需要安装,直接解压就可以使用。建议放在主目录下,方便调用。
d) 为了方便adb命令的使用,我们同样需要将adb命令所在的目录添加到系统环境变量中去,这样,在任何目录下都能直接调用adb,不需要现cd到SDK目录,这样会比较方便,实现方法如下:
代码:
sudo gedit ~/.bashrc
用文本编辑器打开.bashrc文件,然后在最后添加一行:
代码:
export PATH=${PATH}:<你sdk的目录>/tools
这里的需要将你sdk的安装目录添写进去,保存后即可。
e) 把手机连上usb,然后在终端中输入:
代码:
adb devices
会列出所有连接在电脑上的Android设备,如果看到一串数字和字母的序列号的显示的话,即表示SDK安装成功。
软件安装
a) 配置源,更新源之类的问题就不再说了,直接说我们需要的软件,从同步源码到编译rom我们总计需要用到以下几个软件,有部分软件在我们更新过程中可能已经自动安装了,但这不影响我们工作,我把所有需要用到的程序列了出来:
? git-core
? gnupg
? flex
? bison
? gperf
? libsdl-dev
? libesd0-dev
? libwxgtk2.6-dev
? build-essential
? zip
? curl
? libncurses5-dev
? zlib1g-dev
? valgrind
? libreadline5-dev
b) 以上这些程序均通过apt-get命令来安装,比如要安装git-core软件,我们通过输入如下命令来实现:
代码:
sudo apt-get install git-core
c) 其它软件的安装过程类似,替换掉最后的软件名称即可。
d) 安装完所有软件后,编译CyanogenMod所需要的所有环境均搭建完成了。
源码同步
repo的安装
a) CyanogenMod的源码地址是http://github.com/cyanogen/android,你可以通过网址右上角的Download Source来下载源码。不过我们并不推荐这种方式下载,因为源码的变化较为频繁,每次一旦源码有变化,我们就需要重新下载完整的源码包,既费时又费力,效率也很低,故推荐通过repo同步的方式来做,在同步过程中,仅会同步源码的变化部分,效率较高。
b) Repo的安装
i. repo的安装比较方便,之需要下载一个文件,并设置成可执行权限,并添加到系统环境中去即可,具体命令如下:
代码:
cd ~
mkdir bin
在你的home根目录下创建名为bin的文件夹。
代码:
sudo gedit ~./bashrc
打开你的环境变量配置文件,在最后加一行:
代码:
export PATH=$PATH:~/bin
修改后保存文件退出,关闭终端,重新打开一个终端,输入如下命令验证路径是否成功添加到环境变量中去了:
代码:
echo $PATH
确认完后,开始安装repo,执行如下命令:
代码:
curl http://Android.git.kernel.org/repo > ~/bin/repo
chmod a+x ~/bin/repo
通过curl命令将repo下载到bin中,并将其权限修改为可执行文件,至此repo的安装结束。
Repo的配置和同步
i. 在主目录下新建一个文件夹,作为源码的存放目录
代码:
cd ~
mkdir cyanogenmod
cd cyanogenmod
ii. 在cyanogenmod目录执行repo命令,设定需要同步的源码内容:
代码:
repo init -u git://github.com/cyanogen/Android.git -b eclair
网址即为cyanogenmod的地址,-b表示我们选择需要同步的分支,cyanogenmod有不少分支,比如dount,eclair,以后还会有froyo,我们目前需要编译的是2.1,即eclair,则通过-b eclair来选择2.1的分支。
iii. 在配置过程中,会让你选择名字和邮箱,这个会显示在你最后编译出来的rom的基础信息里,可以选择你喜欢的来写
iv. 配置完成后,就可以开始同步源码了:
代码:
repo sync
同步的过程会比较长,建议在晚上睡觉前开始同步,一般早上起来就能好了。
编译环境的设置
编译环境的建立
a) 同步玩源码后,首先需要建立编译环境,CM的源码把这些命令都写成了脚本,我们只需运行相应的脚本即可,首先,先cd到源码的根目录,然后执行如下命令:
代码:
./build/envsetup.sh
执行后,屏幕上会显示:
代码:
including vendor/cyanogen/vendorsetup.sh
此时,编译环境设置成功。
专属文件的提取
a) 虽然Android系统是开源的,但有部分Dream的专属文件是不开源的,所以并不包含在源码树中。但如果希望rom能在Dream真机上运行,又需要这些文件,所以需要将这些文件提取出来,在CM中,这个操作比较简单,Steve已经给我们做好脚本了。
b) 首先你要确保安装成功了上述所有软件,然后,将Dream通过usb连接到电脑上。
c) cd到源码的/vendor/htc/dream_sapphire目录,然后执行脚本:
代码:
./extract-files.sh
d) 这个操作会调用adb命令,从你的手机里pull所需要的专属文件到vendor目录。
编译文件的修改
a) 默认的编译过程包含了所有的语言和程序,但其实我们并不需要这些,可以通过编译文件的修改来定义需要输出的语言和软件
b) 打开/vendor/cyanogen/products 目录下的cyanogen.mk文件,里面定义了要输出的软件和语言,对于不需要的软件,可以直接删除。但不建议在这里修改,可以从最后的输出目录里删除不需要的,直接在这里改容易出错
c) 在文件的最后,有一行”PRODUCT_LOCALES”,这里就包含了rom支持的语言类型,默认有几十种,编译出来后,软件会比较大,一般我们只需要保留其中的常用语言即可,笔者选择保留了en_US,zh_CN和zh_TW这三种语言,编译出来的软件就小了很多。
Kernel编译
1. kernel是Android的核心,也是最重要的部分,虽然CM源码中自带了编译完成的kernel,但既然是自主编译,那你肯定想改改kernel的信息吧,比如kernel的名字,比如打上BFS补丁、超频补丁等等,那你就需要自己来编译kernel了。
2. 编译kernel也非常简单,首先你需要一个kernel的配置文件,CM提供了现成的,直接去/kernel-msm/arch/arm/configs 目录里找,有个配置文件叫cyanogen_msm_defconfig,这个就是我们需要的配额之文件了(如果是给Nexus编译kernel的话,需要选择cyanogen_mahimahi_defconfig)。将它复制到/kernel-msm 的根目录,然后重命名为 .config
3. 用文本编辑器打开.config,其中有一条参数为CONFIG_LOCALVERSION=”-cyanogenmod”,这里即为kernel编译完成后显示的名字,可以把cyanogenmod改成任意你喜欢的名字。
4. 设置完成后,就可以开始编译了。先cd到/kernel-msm目录,然后执行如下命令
代码:
export ARCH=arm
export CROSS_COMPILE=arm-eabi-
export PATH=$PATH:~/cyanogenmod/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin
这些命令定义了编译kernel时所需要用到的环境和设置。注意第三条命令在输入的时候,路径要和自己实际安放源码的路径一致,另外,每次编译kernel前,都需要重新输入这三个命令。
5. 命令输入完后,就可以开始make了:
代码:
make -j3
make就是开始编译的命令,后面的参数-j3表示用于编译的cpu核心数量,一般是cpu核心数量+1,比如双核cpu,就用-j3这个参数。
6. 编译过程根据配置不同而有所不同,笔者笔记本用的T6400是双核2G的,一般编译kernel的时间在10分钟内。编译后的kernel生成在/kernel-msm/arch/arm/boot/目录下,名字叫zImage
CyanogenMod编译
1. 编译完kernel后,就可以开始编译主菜CM了。编译前需要先生成一个buildspec.mk文件,来定义需要编译的rom的基本信息。先cd到源码的根目录,新建一个空文件,名字叫buildspec.mk,并用记事本打开,输入如下信息:
代码:
TARGET_PRODUCT:=cyanogen_dream_sapphire
TARGET_BUILD_VARIANT:=eng
TARGET_BUILD_TYPE:=release
TARGET_PREBUILT_KERNEL:=kernel/arch/arm/boot/zImage
a) 第一条命令表示需要编译的rom的选择,我们现在编译的是G1的rom,故选择cyanogen_dream_sapphire;
b) 第二条命令表示编译的rom的种类,有eng和userdebug两个类型可选,我们当然选在eng;
c) 第三个命令表示编译的rom的类型,我们选择release
d) 第四个命令表示基于哪个kernel来编译rom,如果不设这个命令,则会基于自带的kernel来编译,既然我们自己编译了kernel,那当然用我们自己的,故设置了已经编译好的kernel的目录,供make过程调用。
2. buildspec.mk文件建立好后,就可以开始编译rom了,cd到源码根目录,然后使用命令:
代码:
make -j3
开始编译源码,源码的编译过程会比较长,试配置不同,需要的时间也不一样,笔者的T6400编译完整的CM差不多需要2个小时。
3. 编译完成后,我们的成品就在/out/target/product目录中,里面包含了system.img,recovery.img,boot.img和system文件夹等,到这里,有点制作rom经验的朋友就不需要我再多说了吧。可以在fastboot里直接刷system.img,和boot.img;也可以将system文件夹和boot.img打包成zip包,添加更新脚本并签名,通过recovery刷到机器里,至此,我们自己编译的CyanogenMod for HTC Dream就大功告成了。
-----------------------
android | 评论:0
| Trackbacks:0
| 阅读:965
Submitted by admin on 2011, July 19, 11:47 AM
原文http://www.blogjava.net/TiGERTiAN/archive/2011/01/20/343283.html
前几天下载了Android 2.3.1的源代码并在Ubuntu 10.04(32位)上编译通过。这篇文章简要记录了下载、编译的过程。
关于搭建Android开发环境的文章已经有很多,本文只简要介绍一下,做为备忘。
[ 编译前的准备 ]
这一步安装获取源代码以及编译所需要的软件,使用如下命令:
$ sudo aptitude install git-core gnupg flex bison gperf libsdl-dev libesd0-dev libwxgtk2.6-dev build-essential zip curl libncurses5-dev zlib1g-dev
另外,参考别人编译Android 2.3的经验,安装了下列软件包:
$ sudo apt-get install lib64z1-dev libc6-dev-amd64 g++-multilib lib64stdc++6
虽然Android官方网站上讲不支持Java 6,不过我使用Java 6也可以编译通过,所以在这里Easwy安装的是Java 6。首先去掉/etc/apt/sources.list中这两行的注释,使能Java 6源:
deb http://archive.canonical.com/ubuntu lucid partner
deb-src http://archive.canonical.com/ubuntu lucid partner
然后安装Java 6 JDK:
$ sudo aptitude install sun-java6-jdk
接下来下载repo工具,这是Google提供的一个Python脚本,方便管理多个Git版本库:
$ cd ~
$ mkdir bin
$ curl http://android.git.kernel.org/repo >~/bin/repo
$ chmod a+x ~/bin/repo
记得把repo加到你的路径中,方便以后使用。编辑~/.bashrc,加入下面一行:
PATH=$PATH:~/bin
export PATH
然后用命令. ~/.bashrc,以后就可以直接使用repo命令了。
接下来获取Android 2.3.1的源代码:
$ mkdir mydroid
$ cd mydroid
$ repo init -u git://android.git.kernel.org/platform/manifest.git -b android-2.3.1_r1
$ repo sync
[ 编译Android ]
接下来开始编译:
$ make -j`grep '^processor' /proc/cpuinfo | wc -l`
上面的命令中,-j参数告诉make启动多个并行任务进行编译,在支持多核的CPU上能加快编译速度。如果你知道你CPU是几核的,可以直接把这部分替换成-j2(双核)。
我在编译的过程中遇到下面的错误:
************************************************************
You are attempting to build on a 32-bit system.
Only 64-bit build environments are supported beyond froyo/2.2.
************************************************************
这是因为在Makefile中检测了CPU的字长。我直接把build/core/main.mk中下面的话注释掉:
#ifneq (64,$(findstring 64,$(build_arch)))
#$(warning ************************************************************)
#$(warning You are attempting to build on a 32-bit system.)
#$(warning Only 64-bit build environments are supported beyond froyo/2.2.)
#$(warning ************************************************************)
#$(error stop)
#endif
接下来又遇到下面的错误:
Docs droiddoc: out/target/common/docs/api-stubs
Could not load ‘clearsilver-jni’
java.library.path = out/host/linux-x86/lib
make: *** [out/target/common/docs/api-stubs-timestamp] Error 45
make: *** Waiting for unfinished jobs….
Could not load ‘clearsilver-jni’
java.library.path = out/host/linux-x86/lib
make: *** [out/target/common/docs/doc-comment-check-timestamp] Error 45
这是由于clearsilver在编译时如果检测到使用Java JDK 6,就使用64位编译。要避开此错误,需要修改下面四个文件:
external/clearsilver/cgi/Android.mk
external/clearsilver/java-jni/Android.mk
external/clearsilver/util/Android.mk
external/clearsilver/cs/Android.mk
把这四个Makefile中的下列语句注掉即可:
# This forces a 64-bit build for Java6
# Comment by Easwy
# LOCAL_CFLAGS += -m64
# LOCAL_LDFLAGS += -m64
然后在external/clearsilver目录中执行一下make clean,然后回到项目根目录,继续make即可。
当编译完成时,生成的image文件放在out/target/product/generic目录中。
android | 评论:0
| Trackbacks:0
| 阅读:793
Submitted by admin on 2011, July 19, 11:47 AM
linux | 评论:0
| Trackbacks:0
| 阅读:756
Submitted by admin on 2011, July 19, 11:43 AM
Android系统框架和上层应用是类java(不是正统的sun java)开发的,实现了自己的java虚拟机dalvik,既然用java虚拟机和java开发,一般都会认为效率低下。其实不然,在基本主流的智能手机的软件平台上,android的执行速度是最快的。
那么android效率为什么这么的高呢?特别是一个应用程序的启动时间很短,本文主要从以下个八方面进行分析:
1、 资源文件的优化读取。
我们知道android在UI开发时有个很大的好处是xml文件来描述UI,这样有个好处是只要修改UI不用修改代码就可以修改界面的布局、显示风格和字体大小等。界面定义变得灵活方便。xml配置UI在qtopia运用也有但是这么强大并且也不广泛,因为xml文件有个不足是解析xml的效率很低。
Android是怎么做的呢?
Android在编译的时候就把xml文件进行了优化,android应用程序在解析时变得非常的高效。我们看到apk文件解压后会有个优化过的资源文件。
2、 安装时进行优化dex文件
Android的应用程序都打包成一个apk文件,实际上就是一个zip文件。系统第一次起来或应用程序第一次安装时,系统就把apk文件解压了,把可执行文件dex优化成odex文件并放在/data/dalvik-cache目录下。优化后的dex文件启动速度会加快。这解释了为什么 android系统第一次启动是比较慢,以后起来很快了。
可能有人会问:为什么不在编译时直接优化呢?第⑤项会回答这个问题。
3、 制作数据库
Android的图形应用是加载整个sd卡内的所有图像的,但是为什么很快呢?其实android提前把数据做成了数据库,所以不用每次扫描整个这个sd卡,大大加快了启动速度。
4、 高效的虚拟机
Android是基于类java虚拟机dalvik,一般的java虚拟机是基于栈的,而dalvik是基于寄存器的。实事求是说我对两者的区别了解不是很深入,不过网上有专门的相关文论进行分析。我的简单理解是栈的实现方式相对容易,相关数据是在内存中的栈里,而操作寄存器里数据的速度明显快与内存里的数据处理。
5、 充分挖掘CPU的性能
Android刚出来的时候虽然支持arm cpu,实际上只支持armv5te的指令集的,因为android系统专门为armv5te 进行了优化,充分利用armv5te的执行流水线来提高执行的效率,这也是在500M的三星2440运行效果不是很好,而在200M的omap cpu上运行比较流畅的原因了,所以在最新的代码中有专门针对x86和armv4的优化部分。
6、 优化和裁剪的libc库
Libc库几乎是所以库和程序的基础,但是android没有直接利用libc库,而是自己开发了一个库:bionic,它实现了libc库的绝大多数的函数并根据平台进行了优化,但是有系统很少用并且消耗资源的少数函数是不支持的。它只有几百k,节省了空间同时也提高了执行效率。实际上体现了 20-80原则,抓住少数重要的适当舍弃不必要的。
7、 充分利用linux系统特性
分析过linux内核的朋友知道,linux fork一个新的进程是非常高效的,利用了COW机制。Android是每个进程是个独立的虚拟机(听说这么设计是为安全考虑,某个时候进程崩溃了不会影响这个系统和其他进程。)android里每个进程都是基于虚拟机的,并且也要加载基本的库,实际上这些都是共享。所以android启动一个新的程序实际上并不消耗很多的内存和cpu资源。
同时android在后台有个empty process运行,实际上就是运行一个虚拟机,当要启动一个应用时就直接在其上继续运行,qtopia也有这个机制。
Android系统在开机流程中:启动虚拟机—》启动system server ?》启动launcher。当初分析代码时疑惑为什么不直接启动system server?(qtopia就是直接启动server),实际上也利用了linux的这个特性。
这个特性说的比较简略,不过要真的把他解释清楚可能需要很大的篇幅。
8、 高效的paint机制
这个特性可能跟启动关系不大,但是也是android高效的特性之一。界面变化时大部分实际上不是全屏内容变化的,只是局部变化,android 会根据变化的内容只是跟新局部的内容,也提高了效率。这个也提醒我们在开发应用程序时,重载paint方法时尽量不要paint全屏内容
转
android | 评论:0
| Trackbacks:0
| 阅读:787
Submitted by admin on 2011, July 19, 11:39 AM
1. 说明
1) 下载编译最基本的android源码,无法在真机上使用(不能生成boot.img),只能在模拟器上使用。这是因为没有编译相关机型的内核和硬件驱动。以下介绍的是用android源码编译出对应HTC G1的版本,和烧写的过程。编译生成的版本除相机不能用之外,其它绝大部分功能都能正常使用,在G1上运行2.1版的速度也不错。
2) 本文主要参考日文文档G1/G2烧机指南,感谢原文作者,原文地址:
http://code.google.com/p/android-development-environment/wiki/EclaironADP1andADP2
同时加入中文系统的支持和JIT支持(提高速度),以及相关文字解释。
3) 以下步骤都经过验证(只验证G1手机,G2部分请参见日文文档),实验系统ubuntu8.04,实验日期2010年5月8日
4) 关键字: android 2.1 eclair g1 源码编译
2. 建立android源码编译目录
$ export ANDROID=/exports/android/android_2.1_cn/
$ mkdir -p $ANDROID
$ cd $ANDROID
3. 源码下载
$ repo init -u git://android.git.kernel.org/platform/manifest.git -b android-2.1_r2 #设定下载 2.1版代码
$ vi .repo/local_manifest.xml # 新建下载配置文件
编辑内容如下
<?xml version=”1.0″ encoding=”UTF-8″?>
<manifest>
<project path=”kernel” name=”kernel/msm” revision=”refs/heads/android-msm-2.6.29-donut”/>
<project path=”vendor/htc/common-open” name=”platform/vendor/htc/common-open” revision=”master”/>
<project path=”vendor/htc/dream-open” name=”platform/vendor/htc/dream-open” revision=”master”/>
<project path=”vendor/htc/prebuilt-open” name=”platform/vendor/htc/prebuilt-open” revision=”master”/>
<project path=”vendor/htc/sapphire-open” name=”platform/vendor/htc/sapphire-open” revision=”master”/>
<project path=”vendor/qcom/android-open” name=”platform/vendor/qcom/android-open” revision=”master”/>
<project path=”vendor/qcom/proprietary-open” name=”platform/vendor/qcom/proprietary-open” revision=”master”/>
<project path=”vendor/pv-open” name=”platform/vendor/pv-open” revision=”master”/>
<project path=”vendor/aosp” name=”platform/vendor/aosp” revision=”master”/>
<project path=”hardware/htc/dream” name=”platform/hardware/htc/dream” revision=”master”/>
</manifest>
注意:其中msm是高通芯片组,path指明下载到源码目录中的位置,name指明git上的项目名
$ repo sync # 开始下载代码,此时需要等待较长时间
4. 打补丁以支持动态壁纸(此为步骤为可选)
$ wget http://android-development-environment.googlecode.com/files/patch_devphone_eclair.tar.gz
$ tar zxvf patch_devphone_eclair.tar.gz
$ ./patch/eclair-build-patch.sh
5. 编译内核及无线网络驱动
$ cd $ANDROID/kernel
$ make ARCH=arm CROSS_COMPILE=../prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi- msm_defconfig # 设定默认的msm配置
$ vi .config # 修改新生成的配置文件,以重新设置CPU最高频率,修改如下:
修改CONFIG_MSM_CPU_FREQ_ONDEMAND_MAX项为CONFIG_MSM_CPU_FREQ_ONDEMAND_MAX=528000
$ make ARCH=arm CROSS_COMPILE=../prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi- #编译内核
$ cd $ANDROID/system/wlan/ti/sta_dk_4_0_4_32
$ make ARCH=arm CROSS_COMPILE=$ANDROID/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi- KERNEL_DIR=$ANDROID/kerne l #编译无线网络驱动
$ cp $ANDROID/kernel/arch/arm/boot/zImage $ANDROID/vendor/htc/dream-open/kernel
$ cp $ANDROID/system/wlan/ti/sta_dk_4_0_4_32/wlan.ko $ANDROID/vendor/htc/dream-open/wlan.ko
6. 编译android源码
在HTC网站http://developer.htc.com/adp.html
下载名为signed-dream_devphone_userdebug-ota-14721.zip的包,并把它放在$ANDROID目录下
$ cd $ANDROID
$ source build/envsetup.sh
$ lunch aosp_dream_us-eng # 指明机型
$ cd vendor/htc/dream-open
$ ./unzip-files.sh # 解压htc相关驱动
$ cd $ANDROID
$ vi buildspec.mk # 新建配置文件
加入如下内容
CUSTOM_LOCALES:=zh_CN # 设置编译为中文系统
WITH_JIT:=true # 加入JIT支持,使得运算速度加快1-2倍
$ make -j2 # 编译android源码,需要等待较长时间
7. 把编译好的软件烧写到手机
用usb线连接手机到电脑,按home+power键将手机启动到工程模式,按back键准备烧写
$ export PATH=$PATH:$ANDROID/out/host/linux-x86/bin # 把烧写工具所在目录加上路径
$ cd out/target/product/dream-open/
$ fastboot flash system system.img
$ fastboot flash boot boot.img
$ fastboot reboot
烧写系统后第一次启动手机需要几分钟,请耐心等待
8. 参考
1) 刷写部分未详细描述,具体请参考文档
http://xy0811.spaces.live.com/blog/cns!F8AECD2A067A6B17!1452.entry
2) 源码编译部分未详细描述,具体请参考文档
http://xy0811.spaces.live.com/blog/cns!F8AECD2A067A6B17!1364.entry
linux | 评论:0
| Trackbacks:0
| 阅读:912
Submitted by admin on 2011, July 19, 11:19 AM
共享UID
安装在设备中的每一个Android包文件(.apk)都会被分配到一个属于自己的统一的Linux用户ID,并且为它创建一个沙箱,以防止影响其他应用程序(或者其他应用程序影响它)。用户ID 在应用程序安装到设备中时被分配,并且在这个设备中保持它的永久性。
通过Shared User id,拥有同一个User id的多个APK可以配置成运行在同一个进程中.所以默认就是可以互相访问任意数据. 也可以配置成运行成不同的进程, 同时可以访问其他APK的数据目录下的数据库和文件.就像访问本程序的数据一样.
对于一个APK来说,如果要使用某个共享UID的话,必须做三步:
1、在Manifest节点中增加android:sharedUserId属性。
2、在Android.mk中增加LOCAL_CERTIFICATE的定义。
如果增加了上面的属性但没有定义与之对应的LOCAL_CERTIFICATE的话,APK是安装不上去的。提示错误是:Package com.test.MyTest has no signatures that match those in shared user android.uid.system; ignoring!也就是说,仅有相同签名和相同sharedUserID标签的两个应用程序签名都会被分配相同的用户ID。例如所有和media/download相关的APK都使用android.media作为sharedUserId的话,那么它们必须有相同的签名media。
3、把APK的源码放到packages/apps/目录下,用mm进行编译。
举例说明一下。
系统中所有使用android.uid.system作为共享UID的APK,都会首先在manifest节点中增加android:sharedUserId="android.uid.system",然后在Android.mk中增加LOCAL_CERTIFICATE := platform。可以参见Settings等
系统中所有使用android.uid.shared作为共享UID的APK,都会在manifest节点中增加android:sharedUserId="android.uid.shared",然后在Android.mk中增加LOCAL_CERTIFICATE := shared。可以参见Launcher等
系统中所有使用android.media作为共享UID的APK,都会在manifest节点中增加android:sharedUserId="android.media",然后在Android.mk中增加LOCAL_CERTIFICATE := media。可以参见Gallery等。
另外,应用创建的任何文件都会被赋予应用的用户标识,并且正常情况下不能被其他包访问。当通过getSharedPreferences(String,int)、openFileOutput(String、int)或者openOrCreate Database(String、int、SQLiteDatabase.CursorFactory)创建一个新文件时,开发者可以同时或分别使用MODE_WORLD_READABLE和MODE_WORLD_RITEABLE标志允许其他包读/写此文件。当设置了这些标志后,这个文件仍然属于自己的应用程序,但是它的全局读/写和读/写权限已经设置,所以其他任何应用程序可以看到它。
关于签名:
build/target/product/security目录中有四组默认签名供Android.mk在编译APK使用:
1、testkey:普通APK,默认情况下使用。
2、platform:该APK完成一些系统的核心功能。经过对系统中存在的文件夹的访问测试,这种方式编译出来的APK所在进程的UID为system。
3、shared:该APK需要和home/contacts进程共享数据。
4、media:该APK是media/download系统中的一环。
应用程序的Android.mk中有一个LOCAL_CERTIFICATE字段,由它指定用哪个key签名,未指定的默认用testkey.
参考文档:
Android中如何修改系统时间(应用程序获得系统权限)
http://blog.csdn.net/liujian885/archive/2010/03/22/5404834.aspx
Android-sharedUserId数据权限
http://wallage.blog.163.com/blog/static/17389624201011010539408/
Runtime.exec权限问题
http://blog.csdn.net/yihua0001/archive/2010/07/23/5758980.aspx
关于签名
http://blog.csdn.net/duandianGG/archive/2010/07/21/5752568.aspx
android | 评论:0
| Trackbacks:0
| 阅读:876
Submitted by admin on 2011, July 19, 11:19 AM
在 android 的API中有提供 SystemClock.setCurrentTimeMillis()函数来修改系统时间,可惜无论你怎么调用这个函数都是没用的,无论模拟器还是真机,在logcat中总会得到"Unable to open alarm driver: Permission denied ".这个函数需要root权限或者运行与系统进程中才可以用。
本来以为就没有办法在应用程序这一层改系统时间了,后来在网上搜了好久,知道这个目的还是可以达到的。
第一个方法简单点,不过需要在Android系统源码的环境下用make来编译:
1. 在应用程序的AndroidManifest.xml中的manifest节点中加入android:sharedUserId="android.uid.system"这个属性。
2. 修改Android.mk文件,加入LOCAL_CERTIFICATE := platform这一行
3. 使用mm命令来编译,生成的apk就有修改系统时间的权限了。
第二个方法麻烦点,不过不用开虚拟机跑到源码环境下用make来编译:
1. 同上,加入android:sharedUserId="android.uid.system"这个属性。
2. 使用eclipse编译出apk文件,但是这个apk文件是不能用的。
3. 用压缩软件打开apk文件,删掉META-INF目录下的CERT.SF和CERT.RSA两个文件。
4. 使用目标系统的platform密钥来重新给apk文件签名。这步比较麻烦,首先找到密钥文件,在我的Android源码目录中的位置是"build/target/product/security",下面的platform.pk8和platform.x509.pem两个文件。然后用Android提供的Signapk工具来签名,signapk的源代码是在"build/tools/signapk"下,用法为"signapk platform.x509.pem platform.pk8 input.apk output.apk",文件名最好使用绝对路径防止找不到,也可以修改源代码直接使用。
这样最后得到的apk和第一个方法是一样的。
最后解释一下原理,首先加入android:sharedUserId="android.uid.system"这个属性。通过Shared User id,拥有同一个User id的多个APK可以配置成运行在同一个进程中。那么把程序的UID配成android.uid.system,也就是要让程序运行在系统进程中,这样就有权限来修改系统时间了。
只是加入UID还不够,如果这时候安装APK的话发现无法安装,提示签名不符,原因是程序想要运行在系统进程中还要有目标系统的platform key,就是上面第二个方法提到的platform.pk8和platform.x509.pem两个文件。用这两个key签名后apk才真正可以放入系统进程中。第一个方法中加入LOCAL_CERTIFICATE := platform其实就是用这两个key来签名。
这也有一个问题,就是这样生成的程序只有在原始的Android系统或者是自己编译的系统中才可以用,因为这样的系统才可以拿到platform.pk8和platform.x509.pem两个文件。要是别家公司做的Android上连安装都安装不了。试试原始的Android中的key来签名,程序在模拟器上运行OK,不过放到G3上安装直接提示"Package ... has no signatures that match those in shared user android.uid.system",这样也是保护了系统的安全。
最最后还说下,这个android:sharedUserId属性不只可以把apk放到系统进程中,也可以配置多个APK运行在一个进程中,这样可以共享数据,应该会很有用的。
android | 评论:0
| Trackbacks:0
| 阅读:801