Thursday, September 12, 2013

Android Studio 0.2.x 引入多模块 Eclipse 项目

!!!!太他妈的累人了!整整折腾了两天!!!!!!!


不知从那个版本开始 Import Module... Android StudioFile菜单中消失了,在0.2.0之前的版本作为library的模块可以像Eclipse里一样,绝对路径可以完全和主Applicaiton无关,比如如下的目录结构:

/AllProjects/androidProject/myApplication
/Libs/android/ActionbarSherlock

这里myApplication用到ActionbarSherlock这个库,但是到了0.2.x版本行不通了。首先你得把ActionbarSherlock 移成和myApplication 同级目录,但如果按照上面的目录结构,eclipse 引出Gradle后,用Android Studio 引入后,Project的名字叫andropidProject ,如果在androidProject 目录下还有其他项目,引出到Android Studio后显然会引起混乱,所以重新调整目录结构如下:

/AllProjects/androidProject/myAppProject/myApplication
/AllProjects/android/Project/myAppProject/ActionbarSherelock

然后从Eclipse Export Gradle...但是:别以为这样就OK了,后面的问题仍然是一连串的,下面我分步骤讲解下。

基本环境:
  • Ubuntu 13.04 64bit
  • Eclipse Standard 4.3 (KEPLER)
  • Android Studio 0.2.8 Build #AI-132.821530
  • JDK "1.7.0_25"
  • Android SDK Tools 22.0.5


项目:
myApplication

依赖库:
ActionbarSherlock
drag-sort-listview


第一步:
调整目录结构,并在Eclipse里正确编译。

/
├─ AllProjects
│  └─ androidProject
│  └─ myAppProject
│     ├─ myApplication
│     ├─ ActionbarSherlock
│     └─ drag-sort-listview
└─ android-sdk-linux


第二步:
导出gradle build 文件。

选择Eclipse->File->Export... ,在Export 对话框中选择Android->Generate Gradle build files .具体导出方法参看 Android 官方介绍Migrating from Eclipse 。选中所有要导出的项目,myApplication, actionbarsherlock, drag-sort-listview ,点下一步,确认Project root 是否是 /AllProjects/androidProject/myAppProject , (如果不是,说明你的项目目录结构不正确),最后向导会在Project root 目录中生成下列文件和目录:

gradle/
build.gradle
gradlew
gradlew.bat
settings.gradle

第三步:
运行Android Studio ,Welcome 窗口中选择 Import Project... File->Import Project... 选择导入 /AllProjects/androidProject/myAppProject/build.gradle .

接下来第一个问题来了,按照Android 官方站点的介绍,选择 use gradle wrapper , 出现如下错误:



这里有两个问题,第1个问题比较复杂,先解决第2个问题。
2个问题产生的原因可能是我在Android Studio 中将ADT目录 指向 /android-sdk-linux ,而不是Android Studio Bundle ADT (在Android Studio 目录下的SDK目录),我想通常同时用Eclipse Android Studio的都会这么配置吧,否则机器上保存两份ADT 不是有病嘛!

3.1 步:
Project root 目录中创建 local.properties 文件,文件中加上如下行:

sdk.dir=/home/royer/android-sdk-linux

(你也可用Android Studio new Project.. 生成一个Android Project ,让后从那里copy 一个 local.properties过来)。


现在回头看第一个问题,这个应该是Android Studio 或者 Intellij Bug... Anyway, 解决方法如下:

3.2步:
选择 Use local gradle distribution , Gradle home 里输入你本地的Gradle 路径,如下图:



Gradle 可以到 Gradle download 下载,我用了1.7 版,1.61.8应该也都可以。

到此时,导入是成功了,但编译通不过,碰到的第1个问题是:

Gradle: Execution failed for task ':myApplication:processDebugManifest'.
> Manifest merging failed. See console for more info.

按照提示,开console, 运行 ./gradlew build ,可以看到原因,是myApplication 指定的 android:targetSdkVersion 低于 actionbarsherlock 指定的版本。

第四步:
修改 AndroidManifest.xml确保 主项目和库项目的tagetSdkVersion 一致.

重新build,刚才错误消失了,但新出了19个错误,大致如下:

Gradle: Error while executing dx command
Gradle: UNEXPECTED TOP-LEVEL EXCEPTION:
Gradle: java.lang.IllegalArgumentException: already added: Landroid/support/v4/app/NotificationCompatIceCreamSandwich;

实际上是如何引用 supportv4 库的问题, Eclipse 里是copy 到个项目的libs 目录下,而Android Studio 是引用repositories 的方法。参考Android 官方文档 Support Library Setup,解决如下:

第五步:
修改每个项目的build.gradle 文件。
dependencies {
compile "com.android.support:support-v4:18.0.+"
compile fileTree(dir: 'libs', include: '*.jar', exclude: 'android-support-v4.jar')
.....
}
注:如果你的libs 目录里只有android-support-v4.jar ,则可以把 comile fileTree 整行删除。



OK, 到此为止,至少我成功的import了。

Friday, September 6, 2013

Linux 下 vmware 虚拟机中永久激活Windows 7

Linux vmware 虚拟机中永久激活Windows 7

  1. 简述

    vmware 可以指定一个外部文件作为其虚拟机的BIOS,那么就可以通过把品牌机的SLIC2.1的信息写到这个BIOS文件中来激活Windows 7. 只要能够生成这个BIOS文件,其余的步骤就和兼容机刷BIOS永久激活Windows 7的方法一样了,网上教程到处可见,比如这篇就是个不错的教程。

  2. 基本环境

    1. 主机操作系统:Ubuntu 13.04 64bit
    2. 虚拟机软件: vmware player for linux 64bit
    3. 目标虚拟机: Windows 7 64bit 旗舰版

  3. 所需工具

    1. SLIC Toolkit V3.2 (用来验证SLIC 是否成功写入)
    2. rw-everything
      下载地址:http://rweverything.com/
    3. PhoenixTool (需要 .Net Framework 2.0)

  4. 流程

    1. 第一步:提取vmwarebios

      Ubuntu, vmwarebios /usr/lib/vmware/bin/vmware-vmx 中。用objcopy 提取bios440 section

      objcopy vmware-vmx -O binary -j bios440 --set-section-flags bios440=a bios440.rom.z
      注:这里我先把/usr/lib/vmware/bin/vmware-vmx 拷贝到里临时目录下。

      如果不能提取,可以用objdump命令:
      objdump -h vmware-vmx | grep bios440 
      确认下 bios440 section是否存在或名称是否正确(有些版本的vmware section 名字是 .bios440)。得到结果如下:

      28 bios440 00033d47 0000000000000000 0000000000000000 00d6c0d0 2**0

      另外也可以根据objdump的信息用dd 命令把bios440 section dump 出来。
      dd skip=14074064 bs=1 count=212295 ibs=1 obs=1 if=vmware-vmx of=bios440.rom.z

      其中14074064 对应与objdump 00d6c0d0,bios440 seciton vmware-vmx 中起始位置,而212295是大小,对应objdump00033d47 段。

      用下面的命令对刚才提出的bios440.room.z 解压:
      perl -e 'use Compress::Zlib; my $v; read STDIN, $v, 212295; $v = uncompress($v); print $v;' < bios440.rom.z > bios440.rom
      这里212295 就是bios440.rom.z 的文件大小,vmware版本不同,大小可能略有不同。
      这样的的bios440.rom 就是vmware 512K 的虚拟机BIOS了。


    2. 第二步:用rw-everything 提取ACPI Tables

      启动虚拟机, 运行 rw.exe . Access菜单->ACPI Tables ,从ACPI Tables 的子窗口上选Save All 按钮(或Ctrl+F2), 保存文件名就用缺省的即可 AcpiTbls.rw 。如图:

    3. 第三步:用PhoenixTool 合并SLIC 生成bios

      vmware 虚拟机的BIOS是属于Phoenix类的。感谢PhoenixTool 的作者,有了这个工具,就不必再用Phoenix BIOS Editor WinHex 繁琐无比的操作来生成Phoenixbios了。
      1. Original 里输入从vmware-vmx里抽出的bios440.rom。 等待PhoenixTool完成分析。
      2. Manufacturer 里选择厂商,这个取决于你准备好的SLIC2.1 OEM证书文件是那个厂商的。
      3. SLIC File里输入你的SLIC2.1 的文件。
      4. RW File里输入刚才rw-everything生成的AcpiTbls.rw .



      5. 点击Advanced 按钮,出现可能会刷砖的警告,点“是”,出现advanced option对话框,确保”Only alter RSDT and XSDT tables” 选中,点Done按钮退出设置。



      6. Go按钮开始生成。
        成功生成的话,新的BIOS文件会在bios440.rom 所在的目录里,文件名是bios440_SLIC.rom

    4. 第四步修改 .vmx 文件

      虚拟机关机。用文本编辑软件打开要修改的虚拟机对应的.vmx文件,在文件尾加上:
      bios440.filename = “bios440_SLIC.rom”
      理论上bios440_SLIC.rom 可以放在任何目录,只要配置文件写上绝对路径即可。
      重新启动虚拟机。运行SLIC Toolkit V3.2 检查SLIC2.1 是否成功加入BIOS。如下图红框中字样表示成功提取到SLIC,厂商是LENOVO,型号TC-5K,版本2.1.



最后提供一个各品牌SLIC和证书的下载地址。http://www.360doc.com/content/12/0229/14/1309227_190545700.shtml


另外,如果需要序列号的话,请注意序列号要和你的windows版本匹配,比如你的BIOS烧的是联想的SLICWindows 7是旗舰版,则需要找个联想OEMWindows 7旗舰版的序列号,否则可能还是不能成功激活Windows

本文同步发布在我的CSDN Blog中。http://blog.csdn.net/royer/article/details/11313611

Saturday, August 17, 2013

bash中处理文件名有空格的问题 $(command ls) when file name with space

一个练习。遍历指定的目录,以树状结构显示包括子目录下的所有文件。
在bash中遍历文件用
for file in * ; do
...
done
很多教科书上用: for file in $(commmand ls *) ,但这种方法不能正确处理文件名中包含$IFS指定的分隔符,即便ls 用 --quoting-style=shell 限定也没有用。

for file in * ; 的缺点是不能处理隐藏文件或目录

完整源码如下:
#!/bin/bash

declare -r tab="---"
declare -r lead="|"

function recdir {

declare -i cbfiles=0
declare -a files 

local thistab="$2"$lead$tab
cd "$1"

# get how many files in this directory
for file in * ; do
 files[$(( cbfiles++ ))]="$file"
done

declare -i curr=0
for file in "${files[@]}" ; do
 curr=$((++curr))
 echo "$thistab$file"
 if [ -d "$file" ]; then
  space=${tab//-/' '}
  ll=""
  if [ $(( curr < cbfiles )) = 1 ]; then
   ll=$2$lead"${space}"
  else
   ll="$2 ${space}"
  fi
  recdir "$file" "$ll"
 fi
done

cd ".."
}

rootdir=${1:-.}
rootdir=${rootdir%/}

if [ -d "$rootdir" ]; then
 echo "$rootdir"
 recdir $rootdir
else
 echo "$rootdir is not a directory."
fi

unset rootdir

执行结果如下:
.
|---CRFSC_Manual.pdf
|---foo1
|---foo1~
|---p1_b.jpg
|---p1.jpg
|---p2.jpg
|---p3.jpg
|---studynote
|   |---Match Waveform Theory Notebook.odt
|   |---test.txt
|   |---whh
|       |---a.txt
|---SWIGDocumentation.pdf
|---科学和特异功能.odt

Wednesday, August 14, 2013

bash笔记(三)——条件测试

if 语句之后除了可以跟命令行之外,还可以用[...]结构,[...]结构和内部命令 test 是等效的,即 [ string1 = string2 ]test string1 = string2 的结果是相同的。另外在bash 2.05之后的版本还可以用[[...]] 结构,[[...]] 和[...]之间的不同可参考: http://stackoverflow.com/a/3427931/1036923 .

注意:在 “[” 之后和 “]” 之前空格是必须的。

通常代码形式如下:
if [ -n "$varname" ]; then
    echo "hello"
else
    echo '$varname' is null!
fi
在条件表达式里始终用双引号将变量引起,有以下两个原因:

  1. 将变量解释为一个单词。
  2. 如果变量是null, 没有双引号则上例中条件测试将变为[ -n ] ,它总是返回true; 用了双引号则表达式为[ -n "" ] ;

条件组合

if command && [ condition ] && [ condition ] || [ condition ]; then


if command && [ \( condition \) -a \( condition \) -o \( condition \) ]; then
...


-a 和 -o 只能用在测试条件表达式中

字符串比较

Operator True if...
str1 = str2 str1 matches str2
str1 != str2 str1 does not match str2
str1 < str2 str1 is less than str2
str1 > str2 str1 is greater than str2
-n str1 str1 is not null (has length greater than 0)
-z str1 str1 is null (has length 0)
注:bash 没有 >= 和 <= 比较符。

文件测试

下表列出常用的文件测试表达式。

Operator True if...
-a file file exists
-d file file exists and is a directory
-e file file exists; same as -a
-f file file exists and is a regular file(i.e., not a directory or other special type of file)
-r file You have read permission on file
-s file file exists and is not empty
-w file You have write permission on file
-x file You have execute permission on file, or directory search permission if it is a directroy
-N file file was modified since it was last read
-O file You own file
-G file file's group ID matchs yours (or one of yours, if you are in multiple groups)
file1 -nt file2 file1 is newer than file2
file1 -ot file2 file1 is older than file2


算术比较


Test Comparison
-lt Less than
-le Less than or equal
-eq Equal
-ge Greater than or equal
-gt Greater than
-ne Not equal
注:bash还有针对整数比较的独立语法,效率更高,所以要优先用它而不是上表列出的算术比较运算符。

Monday, August 12, 2013

bash 笔记(二)——字符串操作


一个常用的字符串操作是放在变量名的{}内的一些特定操作符,见下表。

Operator Substitution
${varname:-word} If varname exists and isn't null, return its value; otherwise return word.
Purpose: Returning a default value if the variable is undefined.
Example: ${count:-0} evaluates to 0 if count is undefined.
${varname:=word} If varname exists and isn't null, return its value; otherwise set it to word and then return its value. Positional and special parameters cannot be assigned this way.
Purpose: Setting a variable to a default value if it is undefined.
Example: ${count:=0} set count to 0 if it is undefined.
${varname:?message} If varname exists and isn't null, return its value; otherwise print varname:followed by message, and abort the current command or script(non-interactive shell only). Omitting message produces the default message parameter null or not set.
Purpose: Catching errors that result from variables being undefined.
Example: {count:?”undefined!”} prints “count: undefined!” and exits if count is undefined.
${varname:+word} If varname exists and isn't null, return word; otherwise return null.
Purpose: Testing for existence of a variable.
Example: ${count:+1} return 1 (which could mean “true”) if count is defined.
${varname:offset:length} Performs substring expansion. It returns the substring of $varname starting at offset and up to length characters. The first character in $varname is position 0. if length is omitted, the substring start at offset and continues to the end of $varname. If offset is less than 0 then the position is taken from the end of $varname. If varname is @, the length is number of positional parameters starting at parameter offset.
Purpose: Returning parts of a string(substrings or slices).
Example: if count is set to frogfootman, ${count:4} return footman. ${count:4:4} return foot.
表中除了最后一项,其余各项中的冒号(:)是可以省略的。如果没有冒号,则测试条件由“exists and isn't null" 变为 “exists",即仅仅测试变量是否存在。

模式匹配(Patterns and Pattern Matching)


Operator Substitution
${variable#pattern} If the pattern matches the beginning of the variable's value, delete the shortest part that matches and return the rest.
${variable##pattern} If the pattern matches the begginning of the variable's value, delete the longest part thar matches and return the rest.
${variable%pattern} If the pattern matches the end of the variable's value, delete the shortest part that matches and return the rest.
${variable%%pattern} If the parttern matches the end of the variable's value, delete the longest part the matches and return the rest.
${variable/parttern/string}
${variable//parttern/string}
The longest match to pattern in variable is replaced by string. In the first form, only the first match is replaced. In the second form, all matches are replaced. If the pattern begins with a #, it must match at the start of the variable. If it begins with a %, it must match with the end of the variable. If string is null, the matches are deleted. If variable is @ or *, the operation is applied to each positional parameter in turn and the expansion is the resultant list.
记忆小巧门:#是用在数字开头的,所以对应变量开始部分。%总是用在数字的后面,所以对应变量的结尾部分。

此类模式匹配比较经典的应用是对路径名的解析比如假设:

path=/home/david/document/long.file.name 

则:


${path##/*/}
                     long.file.name
${path#/*/}
      david/document/long.file.name
$path
/home/david/document/long.file.name
${path%.*}
/home/david/document/long.file
${path%%.*}
/home/david/document/long

最长和最短匹配只有在有通配符*存在的情况下才生效,否则他们的输出结果是一样的。比如:filename=alicece ,则${filename%ce} 和 ${filename%%ce} 两个输出的结果都是 alice .

长度操作符

 ${#varname}


*扩展的模式匹配

如果用shopt把extglob设置打开,则可以一次提供多个模式匹配,之间用|分隔。

Operator Meaning
*(patternlist) Matches zero or more occurrences of the given patterns.
+(patternlist) Matches one or more occurrences of the given patterns.
?(patternlist) Matches zero or one occurrences of the given patterns.
@(patternlist) Matches exactly one of the given patterns.
!(patternlist) Matches anything except one of the given patterns.
例子:

  • *(alice|hatter|hare) would match zero or more occurrences of alice, hatter, and hare. So it would match the null string, alice, alicehatter, etc.
  • +(alice|hatter|hare) would do the same except not match the null string.
  • ?(alice|hatter|hare) would only match the null string, alice, hatter, or hare.
  • @(alice|hatter|hare) would only match alice, hatter, and hare.
  • !(alice|hatter|hare) matches everything except alice, hatter and hare.

模式字串里可以包含shell的通配符,比如:+([0-9])可以匹配一位或多位的数字。模式还可以嵌套,比如 rm !(vt+([0-9])) 可以删除所有文件除了文件名由vt开始后跟一串数字的文件。

bash 笔记(一)——变量

1.变量的定义

varname=value
注意:等号两边不能有空格。如果变量(value)超过一个单词,则必须用引号引起。


2.变量和引号

$ fred='Four spaces between these    words.'
$ echo $fred 

Four spaces between these words. 
当使用不带双引号使用变量时,shell会把字符串切分成多个单词,在处理命令行参数时通常就这样做。如果用双引号引起,则shell把整个字符串作为一个单词处理。
$ echo "$fred"
Four spaces between these    words.
双引号和单引号的区别
双引号称为“弱引用”,单引号称为“强引用”。顾名思义,双引号会对引号里的内容进行转意,比如将变量里的内容引出;而单引号则完全拷贝单引号里的内容,对特殊字符不做转意处理。以上面$fred为例:
$ echo '$fred'
$fred

3.位置参数变量

3.1 $0, $1, $2, $3, ...

$1, $2, $3, ... 分别代表命令行中/函数第1, 2, 3, ...个参数。$0 是脚本名字。在函数中$0仍然是脚本名,而不是函数名(如果脚本是用 source 命令执行,则 $0=bash)

3.2 $* 和 $@


  • $* 把所有的参数作为一个单独的字符串,其中用环境变量IFS(internal field separator)中的第一个字符作为参数之间的分隔符。
  • $@ 等价于"$1" "$2" "$3"... "$N" ,就是N个独立的用双引号引起的字符串,它们之间用空格分开。


4.变量名通用写法

完整的变量名书写格式是${varname} 。比如你有超过9个以上的参数,你必须用${10}而不是$10 来引用第10个参数。另外当你想在输出的变量后跟一下划线,你必须用:
echo ${UID}_ 
如果使用 
echo $UID_ ,shell 会把UID_ 看作变量名。

5.变量的类型

用内建命令declare 定义变量的类型,比如 declare -i varname ,表示varname 是个整数变量。 用'-'定义,用'+'取消。常用的设置变量属性的 declare option 见下表。

Option Meaning
-a to make NAMEs indexed arrays (if supported)
-A to make NAMEs associative arrays (if supported)
-i to make NAMEs have the `integer' attribute
-l to convert NAMEs to lower case on assignment
-r to make NAMEs readonly
-t to make NAMEs have the `trace' attribute

当declare 作为命令使用时还有另外一些参数:

Option Meaning
-f restrict action or display to function names and definitions
-F restrict display to function names only (plus line number and source file when debugging)
-g create global variables when used in a shell function; otherwise ignored
-p display the attributes and value of each NAME

Friday, August 2, 2013

Android Audio Arduino: Cross compiling native audio libraries for Android...

Android Audio Arduino: Cross compiling native audio libraries for Android...: Update July, 31 2013: The latest git version of libsndfile builds fine without editing sndfile-play.c In  part 1 of this small series of ...

Android Audio Arduino: Cross compiling native audio libraries for Android...

Android Audio Arduino: Cross compiling native audio libraries for Android...: Update July, 31 2013: Use more recent libs and NDK Preface In my science shows I'm using many sound cues - like playing an intro whe...

Saturday, July 20, 2013

CRFSC 笔记

ACTS —— The Vital Four ACTS of Firearm Safety

A:    Assume every firearm is loaded.
C:    Control the muzzle direction at all times.
T:    Trigger finger must be kept off the trigger and out of the trigger guard.
S:     See that the firearm is unloaded——PROVE it safe.

"PROVE" Safe

P:      Point the firearm in the safest available direction.
R:     Remove all ammunition.
O:     Observe the chamber.
V:     Verify the feeding path.
E:     Examine the bore for obstructions. 

Monday, July 15, 2013

Android NDK 基本概念及注意事项


  1. 必须作为原生动态链接库(native shared library) 提供。文件名必须符合Unix库文件命名规范,必须包含标准的JNI入口函数。例:

    libname.so 
  2. 应用必须显式加载该库。通常在应用启动时加载。例:
  3. static {
    System.loadLibrary("FileLoader");
    }

    注意:不能包含"lib"前缀和.so 后缀。

Saturday, July 13, 2013

流水帐

完成sndfile 学习。

gcc -l 参数 要把前缀lib去掉 。比如要库文件名是libsndfile.a 则:

gcc -lsndfile

Friday, June 25, 2010

Linux 系统 C++ 开发工具概述

本文转自 http://www.linuxidc.com/Linux/2009-02/18381.htm


概述
就C++开发工具而言,与Windows下微软(VC, VS2005等)一统天下相比,Linux/Unix下C++开发,可谓五花八门,各式各样。Emacs, vi, eclipse, anjuta,kdevelop等层出不穷。
Windows下,开发工具多以集成开发环境IDE的形式展现给最终用户。例如,VS2005集成了编辑器,宏汇编ml,C /C++编 译器cl,资源编译器rc,调试器,文档生成工具, nmake。它们以集成方式提供给最终用户,对于初学者而言十分方便。但是,这种商业模式,直接导致用户可定制性差,不利于自动化,集成第三方工具的能力 弱。例如,无法定制一些宏来处理一些重复操作;体会不到自动化makefile一步到位快感;无法远程登录到服务器上进行开发;无法使用某种”粘合剂”来 把第三方工具(例如,文本工具,字符串工具)有效地调用起来。可以说,良好的商业支持和傻瓜式开发,是它们主要的优点。
在Linux下, 开发工具被切割成一个个独立的小工具。各自处理不同的问题。例如,编辑器(emacs, vim)用来进行编辑程序的,调试器(gdb)用来调试程序,编译器(GCC)用来编译和链接程序的,性能分析工具(gcov, gprof)用来优化程序的,文档生成器(doxygen)用来生成文档的。同时,还有一些系统工具和系统知识,我们是很有必要了解的:程序自动化机制 makefile,系统粘合剂shell,系统查找工具grep, locate, find。其它的工具(例如ctags, OCI公司的MPC等等),一旦熟练掌握,它们将成为你手中的利器。
本文主要是一些针对Linux下开发工具使用的经验之谈。由于,工具品种繁多,我们没有能力也没有必要一一介绍。对于Linux下IDE工具,例如 eclipse, anjuta等,它们虽然也很实用,但是使用起来比较简单,而且目前还算不上主流。所以,它们将不被着重介绍。同时,本文也不打算写成各个工具的操作手 册,只着眼于介绍各个工具的想要解决的问题、运行机理和主要特性。



编辑器
要进行开发,第一件事情就是选择一个合适的编辑器。编辑器选择有几个要素:
1)减少不必要的编辑动作,减少编辑的时间。
一切能够无二义性描述出来的编辑任务,都可以而且应该能被自动化。例如,每一个C++程序都会有一个main函数;我们在定义.h文件时,都希望加入一些 预处理指令#define来帮我们解决重复引用同一个头文件而带来的麻烦。鼠标操作总是比键盘操作要慢的。这方面EMACS做得可算是到了极致。所以, EMACS用户经常会吹嘘:他们编辑的速度等同于他们思考的速度。

2)可扩展性高。
程序员预期的编辑器应该能提供一些编程的帮助,例如,语法高亮,自动补齐,自动排版,语法检查等等。留心观察一下gedit, vim, emacs, ultraEdit,就会发现它们提供的远不是windows 记事本,写字板提供的那么简陋的功能。对于一种新的语言,新的语法,它们应该能很方便地提供支持,而不停留在一种或几种固定的语言上。
3)用户可定制性高。
如果想长期从事研发,特别是Linux/unix下研发的话,那么你很有必要学好一个功能足够的编辑器。有这么一句话:Linux下程序员分为三种,使用emacs的,使用vi的,还有其它。
EMACS是Stallman用lisp语言写的一个GPL的编辑器。我们这里所说的emacs指的是GNU emacs,而非Xemacs。由于它的开放性,我们可以把它打造成一个功能强大的IDE。我们在安装好CGYwin之后,也可以在Windows系统下 使用 EMACS。CGYwin和MINGW是第三方写的一个在Windows系统上模拟POSIX系统的工具。
EMACS与其说的是一个编辑器,倒不如说它是一个操作系统。我们可以用它来写编程,写wiki,收发邮件等等。EMACS主要是通过两种方式来进行扩 展:el脚本(elisp是lisp的一种方言)和第三方扩展包。EMACS的入门成本很高。由于是纯键盘操作,所以需要记忆大量的快捷键;功能强大是通 过用户添加一些扩展包,lisp脚本来实现的。如何正确配置和修改是很需要耐心和技巧的。


编译器
编译器首选GCC(GNU COMPILER COLLECTION)。原因有两个,它是GNU开源的,同时它对标准C++的 支持度高达96.15%。而VC++6.0的支持度只有83.43%。 GCC不仅是通常意义上的C或C++的编译器,它还可以编译java等其它语言。gcc是gnu c的编译器,g++是gnu c++的编译器, 而EGCS(Enhanced GNU Compiler Suite)可以认为是gcc的改进版。

编译语言从源程序到目标代码会经过如下几个阶段:源程序->汇编程序->编译成obj程序->链接成最终可执行程序。我们可以通过一条编译指令来完 成所有步骤。也可以分步执行。gcc有三个重要选项-E(只进行预处理), -S(生成汇编代码), -g(生成带原代码调试符号的可执行文件,如果想用gdb调试的话,就应该在编译时打开这个选项)。
GCC可以看作一个软件包,除了编译工具,它还集成了调试器gdb,性能分析工具gcov, gprof。只要我们装好了GCC,这些强大工具就可以直接使用了。
通过gcov,我们可以查看一个程序,源代码中每行代码的运行次数。我们优化运行次数最多的代码,那么就可以大大优化程序。使用gcov时,需要打开 GCC的fprofile-arcs和ftest-coverage两个选项。gcov中常用的选项有-b分支统计信息。
通过gprof工具,我们可以查看函数之间的调用顺序,及各个函数运行的时间。我们可以将gprof理解为Linux/unix自带工具time的加强版。使用gprof时,需要打开GCC的pg选项。
gcov和 gprof的共同点是在编译程序时,加入自己的一些辅助信息,由此来进行程序诊断。除了,这些优化手段,我们还可以使用一些内存泄漏工具,来减少野指针,未释放的内存空间。



调试器
GDB即GNU的调试器,它是GCC附带的一个性能优质的调试器。通过GDB和脚本结合,我们可以很好的实现回归测试。
GDB可以运行于CLI和GUI两种模式。默认GDB是CLI模式的,我们可以去下载和安装GUI模式的GDB,例如xxgdb, ddd等。一个更好的方式是在 EMACS中使用GDB。GDB包括visual studio工具的所有调试功能,还 包括它没有的功能。它除了支持,我们一般的设置断点,单步跟踪,step in, step out, step over等,还有一些强大的功能。在gdb中,我们可以有以下几种暂停方式:断点(BreakPoint)、观察点(WatchPoint)、捕捉点 (CatchPoint)、信号(Signals)、线程停止(Thread Stops)。

下面列举几个让我印象深刻的功能。1)通过 watch指令,可以让程序在某个变量的值发生变化时,暂停下来。2)通过print指令,在程序运行时,设置变量的值,运行一个程序自身支持的一个方 法。3)通过until指令,我们可以让程序在运行到某个程序时暂停下来。4)通过break.. if指令,使得程序在满足某个bool表达式时,暂停下来。

粘合剂
我想通过”粘合剂”这个词来表达将多个工具粘合起来的”胶水”。例如,通过shell脚本,我们可以把OS命令,sed指令,awk指令,其它脚本文件等 串联起来,发挥它们的合力。在Linux C++编程中,我们不可避免地会使用makefile文件。通过,它我们可以把编译指令,生成文档操作,清除操作等等串联起来。从某种意义上来看,它也相 当于一个粘合剂。

makefile的出发点是,维护好一个项目中众多文件的依赖关系,由此得到一个源程序的拓扑图。当我们只修改图中某个结点时,重新编译时就只需要将拓扑 图中关联的链路进行编译就好了。由此,大大缩短了编译的时间。make有两大概念:dependencies和rules。规则rule即针对每一个依赖 关系 dependency定义一个操作规则。这个细粒度的分离,就可以使我们可以定制软件构建的行为。例如,修改使用的编译器,修改includepath, 修改libpath, 修改编译选项等等。我们常见的VC中的nmake,功能和make是类似的。
make使用的重点和难点是编写Makefile文件。Makefile的语法相对其它语言来说是很不一样的,我们要特别注意TAB键和空格键的区别。有 很多工具可以用来帮助我们生成Makefile。最出名的就是GNU的autoconf了。一个GNU程序的编写,需要autoscan, aclocal, autoconf, automake这四个工具。
我们知道GNU软件安装的三步曲是:./configure, make, make install。其中./configure就是根据autoconf, alocal等工具生成一个makefile文件。make指令就是调用make指令来根据makefile文件的规则来编译源程序。而make install就是执行makefile中的install规则指出的操作(一般是copy操作)。而make clean就是执行makefile中的clean规则指出的操作(一般是rm操作)。我们用Eclispe+CDT开发Managed C++ Project时,它就是通过objects.mk,subdir.mk,sources.mk三个文件来生成Makefile。我们注意观察编译时的输 出信息,就可以看到显示的Makefile文件的内容。
可以说,如果想编译出跨平台的C++程序,那么makefile是一种最方便的机制。
OCI公司为Douglas C.Schmidt的ACE,TAO开源社区编写了一段伟大的perl脚本--MPC。它由平台信息,一个规则文件,源代码,生成用户想要的工程文件,例 如Make, Nmake, Visual C++ 6, Visual C++ 7等等。Google Web Tookit, Celtix做的事情与之类似,不过它们是针对JAVA的,而MPC是针对C++的。


结束语
国内资料太多的低层次的重复,经常是一个网页被多次转载,而且回答问题时深度不够。个人找资料的顺序是:查看quick start或how to文档->自带的帮助(如果看起来不太吃力话)->百度查一下中文网页,来理清一下基本概念->google查一下->几个大的,相关的网站查下资料 ->看自带帮助。再者,面对面的交流是十分重要的,大家可以相互理一下概念,交流一下心得。可惜,我身边这种氛围还是不够。

Linux下开发还可以更友好一些。个人感觉, Linux开发要在国内普通程序员中大规模普及,还有一段很长的路要走。Ubuntu火 爆的主要原因,就是它帮用户搭好一些默认配置。用户如果想新加一些 服务,它们提供了良好,有效地支持。所以,我想我们可以在IDE和现在Linux这种一个个小部件的这两种状态之间,取一个折衷。也就是针对几种主要需求 的用户,发布一些配置好的环境。尤其是emacs的各种el脚本(例如界面主题的color-theme, C/C++语言编辑策略,代码样式设置脚本,各种emacs系统设置), 第三方扩展包(模板template, 编程支持包cedet等)。每一个用户浪费时间来进行这些配置是十分没有意义的!工具始终只是工具,我们不能沦为工具的奴隶,不能把一大部分精力浪费在配 置工具上。
值得注意的是现在方兴未艾的eclipse有向这方面迈进的趋势。但是,现在emacs已经做得很好了,ecilpse能否超越它,我们还有待观察。我们 可以通过在eclipse上安装SDT插件来进行C++开发。但是,它目前还不支持调试功能,而且不太稳定,功能不够强。例如,有时会无故死掉;如果想通 过eclipse来转向函数原型的话,那么迎接你的将是一个漫长、焦急的等待。
由于本人缺少在Linux下进行实际大规模程序的开发经验,对很多工具和机制的理解还比较肤浅。对它们的熟悉程度离真正实用,还有一段很长的路要走。

Tuesday, May 25, 2010

Scheduling Jobs in Linux

Scheduling one-time jobs
If you want to run one or more commands at a later time, you can use the at command. The atd daemon --- a program designed to process jobs submitted using at --- runs you commands at the specified time and mails the output to you.

Before you try the at command, you need to know that the following configuration files control which users can schedule tasks using the at command:

  • /etc/at.allow contains the names of the users who may submit joibs using the at command.
  • /etc/at.deny contains the names of the users not allowed th submit jobs using the at command.
If these file aren't present or if you find an empty /etc/at.deny file, any user can submit jobs by using the at command. The default in Linux is an empty /etc/at.deny file; with this default in place, anyone can use the at command.

To use at to schedule a one-time job for execution at a later time, follow these steps:

1. Run the at command with the date or time when you want your commands executed.
    When you press Enter, the at> prompt appears, as follows:
        at 21:30
        at>

    Simply specify the time in a 24-hour format. In this case, you want to execute the commands at 9:30pm. tonight ( or tomorrow, if it's already past 9:30pm.). 

2. At the at> prompt, type the commands you want to execute as if typing at the shell prompt. After each command, press Enter and continue with the next command. When you finish entering the commands you want to execute, press Ctrl+D to indicate the end.

Here's an example showing how to execute the ps command at a future time:

at> ps
at>
job 1 at 2010-05-24 21:30

After you press Ctrl+D, the at command responds with a job number and the date and time when the job will execute.


Formats for the Time of Execution with the at Command
CommandWhen the Job will Run
at nowImmediately
at now + 15 minutes15 minutes from current time
at now + 4 hours4 hours from the current time
at now + 7 days7 days from the current time
at noonAt noontime today(or tomorrow,if already past noon)
at now next hourExactly 60 minutes from now
at now next dayat the same time tomorrow
at 17:00 tomorrowat 5pm. tomorrow
at 4:45pmAt 4:45pm. today(or tomorrow, if it's already past 4:45pm)
at 3:00 Dec 28,2008At 3:30am on December 28,2008

atq command uses to view current list of scheduled jobs:

The output looks similar to the following:

4         2006-12-28   03:00    a    root
5         2006-12-26   21:57    a    root
6         2007-10-26   16:45    a    root

The first field on each line shows the job number --- the same number that the a command displays when you submit the job. The next field shows the year, month, day, and time of execution. The last filed shows the jobs pending in the a queue.

If you want to cancel a job, use the atrm command to remove that job from the queue. When removing a job with the atrm command, refer to the job by its number, as fllows:

atrm 4


Scheduling recurring jobs


crontab command : used to schedule

You schedule recurring jobs by placing job information in a file with a specific format and submitting this file with the crontab command. The cron daemon --- crond ---- checks the job information every minute and executes the recurring jobs at the specified times. Because the cron daemon processes recurring jobs, such jobs are also referred to as cron jobs.

Any output from a cron job is mailed to the user who submits the job. (In submitted job-information file, you can specify a different recipient for the mailed output.)

Two configuration files control who can schedule cron jobs using crontab:


  • /etc/cron.allow contains the names of the users who may submit jobs using the crontab command.
  • /etc/cron.deny contains the names of users not allowed to submit jobs using the crontab command.
If the /etc/cron.allow file exists, only users listed in this file can schedule cron jobs. If only the /etc/cron.deny file exists, users listed in this file can't schedule cron jobs. If neither file exists, the default Linux setup enables any user to submit cron jobs.

To submit a cron job, follow these steps:

1. Prepare a shell script (or an executable program in any programming language) that can perform the recurring task you want to perform.
    You can skip this step if you want to execute an existing program periodically.

2. Prepare a text file with information about the times when you want the shell script or program (from Step 1) to execute and then submit this file by useing crontab.
    You can submit several recurring jobs with a single file. Each line with timing information about a job has a standard format with six fields --- the first five specify when the job runs, and the sixth and subsequent fields constitute the actual command that runs. For example, here's a line that executes the myjob shell script in a user's home directory at five minutes past midnight each day:
     5 0 * * *  $HOME/mujob
Next table shows the meaning of the first five fields.

3. Suppose the text file jobinfo (in the current directory) contains the job information. Submit this information to crontab with the following command:
    crontab jobinfo
That's it! You're set with the cron job. From now on, the cron job runs at regular intervals ( as specified in the job information file), and you receive mail messages with the output from the job.

Format for the Time of Execution in crontab Files
Field NumberMeaning of FieldAcceptable Range of Values*
1Minute0-59
2Hour of the day0-23
3Day of the month0-31
4Month1-12 or the names of month using the first three letters
5Day of the week0-6 or the three-letter abbreviations of weekdays
*An asterisk in a field means all possible values for that field. For example, if an asterisk in the third field,the job is executed avery day.

To Vereify that the job is indeed scheduled, type the following command:

crontab  -1

The output of the crontab -1 command shows the cron jobs currently installed in your name. To remove you cron jobs, type crontab -r.

Search This Blog