今天在实验室的机器上配置好了Hadoop,因为今后预计会使用C++进行一些开发,
因此模仿word count的example写了个C++测试程序(好简陋 - -!!)。
贴个代码:
Mapper:
// c++ map reduce Mapper
// word count example
// 2008.4.18
// by iveney
#include <string>
#include <iostream>
using namespace std;
int main()
{
string buf;
while( cin>>buf )
cout<<buf<<"\t"<<"1"<<endl;
return 0;
}
Reducer:
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main()
{
map<string,int> dict;
map<string,int>::iterator iter;
string word;
int count;
while( cin>>word>>count )
dict[word]+=count;
iter = dict.begin();
while( iter != dict.end() )
{
cout<<iter->first<<"\t"<<iter->second<<endl;
iter++;
}
return 0;
}
编译:
[hadoop@master ~]$ g++ mapper.cpp -o mapper
[hadoop@master ~]$ g++ reducer.cpp -o reducer
简单测试:
[hadoop@master ~]$ echo "ge abc ab df ge" | ./mapper | ./reducer
ab 1
abc 1
df 1
ge 2
使用Hadoop计算:
(数据使用了Project Gutenberg的几本电子书,不过貌似国内被屏蔽了?www.gutenberg.org
好在在UPenn的图书馆里有资源 ^^V http://digital.library.upenn.edu/webbin/gutbook )
[hadoop@master ~]$ ll -h gutenberg
total 5.3M
-rw-r--r-- 1 hadoop hadoop 336K 2008-04-18 07:45 132.txt
-rw-r--r-- 1 hadoop hadoop 154K 2008-04-18 07:45 1ws1510.txt
-rw-r--r-- 1 hadoop hadoop 659K 2008-04-18 07:45 20417-8.txt
-rw-r--r-- 1 hadoop hadoop 1.4M 2008-04-18 07:45 7ldvc09.txt
-rw-r--r-- 1 hadoop hadoop 577K 2008-04-18 07:45 advsh12.txt
-rw-r--r-- 1 hadoop hadoop 377K 2008-04-18 07:45 dvldc10.txt
-rw-r--r-- 1 hadoop hadoop 185K 2008-04-18 07:45 frhnt10.txt
-rw-r--r-- 1 hadoop hadoop 152K 2008-04-18 07:45 rgsyn10.txt
-rw-r--r-- 1 hadoop hadoop 1.5M 2008-04-18 07:45 ulyss12.txt
运行结果:
[hadoop@master hadoop]$ bin/hadoop jar contrib/streaming/hadoop-0.16.3-streaming.jar -mapper /home/hadoop/mapper -reducer /home/hadoop/reducer -input gutenberg/* -output gutenberg-c++-output
additionalConfSpec_:null
null=@@@userJobConfProps_.get(stream.shipped.hadoopstreaming
packageJobJar: [/usr/share/hadoop-datastore/hadoop-hadoop/hadoop-unjar41914/] [] /tmp/streamjob41915.jar tmpDir=null
08/04/18 01:16:13 INFO mapred.FileInputFormat: Total input paths to process : 9
08/04/18 01:16:13 INFO streaming.StreamJob: getLocalDirs(): [/usr/share/hadoop-datastore/hadoop-hadoop/mapred/local]
08/04/18 01:16:13 INFO streaming.StreamJob: Running job: job_200804171952_0005
08/04/18 01:16:13 INFO streaming.StreamJob: To kill this job, run:
08/04/18 01:16:13 INFO streaming.StreamJob: /usr/share/hadoop/bin/../bin/hadoop job -Dmapred.job.tracker=master:54311 -kill job_200804171952_0005
08/04/18 01:16:13 INFO streaming.StreamJob: Tracking URL: http://master.cluster:50030/jobdetails.jsp?jobid=job_200804171952_0005
08/04/18 01:16:14 INFO streaming.StreamJob: map 0% reduce 0%
08/04/18 01:16:17 INFO streaming.StreamJob: map 11% reduce 0%
08/04/18 01:16:18 INFO streaming.StreamJob: map 22% reduce 0%
08/04/18 01:16:19 INFO streaming.StreamJob: map 67% reduce 0%
08/04/18 01:16:20 INFO streaming.StreamJob: map 78% reduce 0%
08/04/18 01:16:22 INFO streaming.StreamJob: map 100% reduce 0%
08/04/18 01:16:23 INFO streaming.StreamJob: map 100% reduce 4%
08/04/18 01:16:26 INFO streaming.StreamJob: map 100% reduce 26%
08/04/18 01:16:33 INFO streaming.StreamJob: map 100% reduce 30%
08/04/18 01:16:36 INFO streaming.StreamJob: map 100% reduce 33%
08/04/18 01:16:38 INFO streaming.StreamJob: map 100% reduce 71%
08/04/18 01:16:41 INFO streaming.StreamJob: map 100% reduce 80%
08/04/18 01:16:43 INFO streaming.StreamJob: map 100% reduce 100%
08/04/18 01:16:43 INFO streaming.StreamJob: Job complete: job_200804171952_0005
08/04/18 01:16:43 INFO streaming.StreamJob: Output: gutenberg-c++-output
跟使用例程测试得到的结果相同~成功~
用了29secs,竟然比Python写的例程还慢5secs。
很可能是数据量大小java虚拟机的启动显得没那么trivial了 -_-|||
另外直接运行其实更快……咔咔......数据量
[hadoop@master ~]$ cat test.sh
#!/bin/bash
cd /home/hadoop/gutenberg
for i in `ls`
do
cat $i | /home/hadoop/mapper | /home/hadoop/reducer \
>> /home/hadoop/output
done
[hadoop@master ~]$ time ./test.sh
real 0m4.176s
user 0m5.454s
sys 0m1.611s
Saturday, April 19, 2008
Monday, April 14, 2008
CAcert小试
CAcert是一个免费的CA系统,试图建议所谓的可信网络(Web of trust),这是它对自己object的介绍:
上去试了一下,发觉它提供的证书包括个人证书、domain证书、SSL证书等,都是免费的。
可以用于电子邮件签名、加密、SSL服务器、客户端等。
当然,认证的过程是严格的。要成为一个assurer,首先必须获得100点的assurer points。
另外还要通过所谓的Certificate Test. (我裸考过一次,60分,要80分才合格,100分才能获得资格)
-------------------------------------------
下面介绍一下如何申请与注册。
首先登陆www.cacert.org
按照页面连接进入Root certificate页面,倒入它的class 1和class 3的根证书,然后还要倒入crl(证书撤销列表)
firefox浏览器操作很方便,直接点击就可以自动下载与导入了。导入根证书时会要求用户确认,因为它是自签发的。
接下来选择join us。
然后会让你填一堆东西,其中密码有个评分制度,必须达到6分才能通过它的认证。
根据提示,必须要有足够长度、英文大小写、标点符号才能达到……我随便写了一个面目全非的,也不知有没可能记住。
点击下一步后,(我用的是firefox),firefox要求你输入一个密码用以保护证书(我不知有没理解错,后面好像都没用到),然后firefox生成一个私钥与公钥对。
cacert随之根据签发的信息生成你的帐号。必须登陆邮箱激活帐号。
最后可以去申请数字证书,登陆后发觉有3种证书,分别是个人证书、domain证书、服务器证书。
后面两种没有测试,我申请了个人证书。
申请的过程比较简单,按部就班就完成了。最后会给邮箱发一封确认邮件,点击连接自动添加证书到浏览器里
同时又需要一个密码来保护该证书……(好多密码啊……)
然后浏览器还提示要注意备份,于是我选择导出备份,然则此时又需要一个密码以保护该证书……
更新:关于导出文件.P12
In cryptography, PKCS#12 is one of the family of standards called Public-Key Cryptography Standards (PKCS), published by RSA Laboratories. It defines a file format commonly used to store private keys with accompanying public key certificates, protected with a password-based symmetric key, and is the successor to PFX.
File extension: .p12
原来这个导出文件包括私钥和包含公钥的数字证书。同时可以输入一个密码(对称的)以保护它。
最后,当证书成功保存在你的浏览器里时,就可以使用了!
进入这个网站时再也不用输入密码了 ~.~
直接点击证书登陆即可。
另外,这个证书好像只有半年有效期,到时要主动来更新。
并且在更新的页面上也有revoke的选项。(我申请了3次,前两次都不小心revoke了……)
-------------------------------------------
看了一下关于assure,发觉真的好麻烦。
Find an assurer: 离广州方圆1000里只能搜索到4个assurer,而且貌似都是HK的。
如果要成为assurer,还必须通过律师等把资料寄到相关的委员会。
-------------------------------------------
总的来说,申请个人数字证书如果普及起来,达到可信网络的状态的话,应该相当不错吧。
可惜学习梯度似乎有点大,连自认为理解能力比较好的我也看得晕晕乎乎的(之前还花了整个星期看PKI的原理、概念)
感觉PKI要做起来也不容易,虽然从各方面来分析都相当合理。
然而我认为它的最大缺陷还是:最多仅能保证到网络传输安全,端点安全也尤为重要啊。
如果别人直接用你的浏览器,它在网上的身份就成为你了……
所以说自己的电脑要保护好才行。个人电脑一定要设密码。
CAcert.org was designed to be by the community for the community, and instead of placing all the labour on a central authority and in turn increasing the cost of certificates, the idea was to get community in conjunction with this website to have trust maintained in a dispersed and automated manner!
上去试了一下,发觉它提供的证书包括个人证书、domain证书、SSL证书等,都是免费的。
可以用于电子邮件签名、加密、SSL服务器、客户端等。
当然,认证的过程是严格的。要成为一个assurer,首先必须获得100点的assurer points。
另外还要通过所谓的Certificate Test. (我裸考过一次,60分,要80分才合格,100分才能获得资格)
-------------------------------------------
下面介绍一下如何申请与注册。
首先登陆www.cacert.org
按照页面连接进入Root certificate页面,倒入它的class 1和class 3的根证书,然后还要倒入crl(证书撤销列表)
firefox浏览器操作很方便,直接点击就可以自动下载与导入了。导入根证书时会要求用户确认,因为它是自签发的。
接下来选择join us。
然后会让你填一堆东西,其中密码有个评分制度,必须达到6分才能通过它的认证。
根据提示,必须要有足够长度、英文大小写、标点符号才能达到……我随便写了一个面目全非的,也不知有没可能记住。
点击下一步后,(我用的是firefox),firefox要求你输入一个密码用以保护证书(我不知有没理解错,后面好像都没用到),然后firefox生成一个私钥与公钥对。
cacert随之根据签发的信息生成你的帐号。必须登陆邮箱激活帐号。
最后可以去申请数字证书,登陆后发觉有3种证书,分别是个人证书、domain证书、服务器证书。
后面两种没有测试,我申请了个人证书。
申请的过程比较简单,按部就班就完成了。最后会给邮箱发一封确认邮件,点击连接自动添加证书到浏览器里
同时又需要一个密码来保护该证书……(好多密码啊……)
然后浏览器还提示要注意备份,于是我选择导出备份,然则此时又需要一个密码以保护该证书……
更新:关于导出文件.P12
In cryptography, PKCS#12 is one of the family of standards called Public-Key Cryptography Standards (PKCS), published by RSA Laboratories. It defines a file format commonly used to store private keys with accompanying public key certificates, protected with a password-based symmetric key, and is the successor to PFX.
File extension: .p12
原来这个导出文件包括私钥和包含公钥的数字证书。同时可以输入一个密码(对称的)以保护它。
最后,当证书成功保存在你的浏览器里时,就可以使用了!
进入这个网站时再也不用输入密码了 ~.~
直接点击证书登陆即可。
另外,这个证书好像只有半年有效期,到时要主动来更新。
并且在更新的页面上也有revoke的选项。(我申请了3次,前两次都不小心revoke了……)
-------------------------------------------
看了一下关于assure,发觉真的好麻烦。
Find an assurer: 离广州方圆1000里只能搜索到4个assurer,而且貌似都是HK的。
| Michael B | 120km | 10 | contact by email only | Email Me |
| Yat Hei C | 130km | 35 | Please contact me at xxxx | Email Me |
| David W | 130km | 35 | Email Me | |
| Kin Fung Y | 240km | 35 | I live in Hong Kong. Email me for assurance only. | Email Me |
如果要成为assurer,还必须通过律师等把资料寄到相关的委员会。
-------------------------------------------
总的来说,申请个人数字证书如果普及起来,达到可信网络的状态的话,应该相当不错吧。
可惜学习梯度似乎有点大,连自认为理解能力比较好的我也看得晕晕乎乎的(之前还花了整个星期看PKI的原理、概念)
感觉PKI要做起来也不容易,虽然从各方面来分析都相当合理。
然而我认为它的最大缺陷还是:最多仅能保证到网络传输安全,端点安全也尤为重要啊。
如果别人直接用你的浏览器,它在网上的身份就成为你了……
所以说自己的电脑要保护好才行。个人电脑一定要设密码。
Wednesday, April 9, 2008
关于redhat系列与debian系列的网络基本配置
以前弱,只知道用system-config-network这个GUI来设置网络,又烂又慢.
最近因为要远程配置cluster,因此研究了一下静态配置的方法,其实也很简单.
但是由于cluster用的系统是fedora,但自己机器上是ubuntu,发觉有些不一样,做个笔记对比下.
PS.由于ubuntu是debian系列的,我猜想debian也是差不多的
而网上查到redhat与fedora的配置文件的确是一样的.
以下仅涉及以太网的IP,netmask,gateway,broadcast设置.
以及dns,resolve配置.
共同的设置:
1. DNS服务器 resolv.conf
均使用/etc/resolv.conf ( 注意是resolv不是resolve )来配置DNS服务器
它的格式如下:
nameserver IP
nameserver IP
...
很简单
另外还有不少的option,不过发觉似乎没什么会用到的,就没有细看了.
2.静态主机名查询表 hosts
均使用/etc/hosts来记录静态的主机名,别名以及IP. 在windows下则是 %windows%\system32\hosts( 如果没记错 )
格式如下:
IP hostname alias[,alias...]
其中这行必须存在,用于定义换回接口的地址以及域名
127.0.0.1 localhost.localdomain localhost localhost
一个IP对应一个主机名以及多个别名.使用hostname可以设置以及修改域名
不同的设置
1.
ubuntu中,/etc/hostname 用来定义本机主机名,用于启动时供启动脚本读取设定.
而redhat系列貌似没有这个文件,在hostname的手册页中介绍到
The host name is usually set once at system startup in /etc/rc.d/rc.inet1 or /etc/init.d/boot (normally by reading the contents of a
file which contains the host name, e.g. /etc/hostname).
另外在网上看到的介绍是:
在/etc/sysconfig/network中进行设定.然而我在ubuntu中貌似找不到类似的文件.
我在启动脚本看到,/etc/rc.d/rc.sysvinit里含有设定的语句.
而在/etc/rc.d/rc.local中看到用nisdomainname来设定nis的domainname.
2.
ubuntu中/etc/network/interfaces用来定义各个interface的IP等设定
----------------------
我的机器该文件如下:
auto lo
iface lo inet loopback
address 127.0.0.1
netmask 255.0.0.0
iface eth0 inet static
address 172.18.34.177
netmask 255.255.252.0
gateway 172.18.35.254
auto eth0
iface eth1 inet dhcp
----------------------
其中auto表示机器启动时自动up.
iface一项定义该界面的具体参数,
static表示静态地址而dhcp表示...就是dhcp拉 -.-
其中static又应包括address,netmask,gateway.
而在redhat中,使用/etc/sysconfig/network-scripts/ifcfg-ethn来设定
其中ethn可替换为网卡名.在某台机器上看到内容ifcfg-eth0如下:
# Intel Corporation 82562ET/EZ/GT/GZ - PRO/100 VE (LOM) Ethernet Controller
DEVICE=eth0
BOOTPROTO=none
BROADCAST=202.116.76.255
IPADDR=202.116.76.163
NETMASK=255.255.255.0
NETWORK=202.116.76.0
ONBOOT=yes
GATEWAY=202.116.76.1
TYPE=Ethernet
USERCTL=no
IPV6INIT=no
PEERDNS=yes
需要填写的field其实跟ubuntu大同小异.
同时注意到,ifup和ifdown script都在这里.它们就是通过读取这里的设定来完成interface的up & down的.
但是
另外我还注意到,在/etc/sysconfig/networking中:
devices文件夹包含ifcfg-eth{0,1},其中eth0和eth1是已有的网络设备.
这两个文件与/etc/sysconfig/network-scripts的两个文件inode相同,说明是硬链接.
而在profiles/default中包含有:
hosts ifcfg-eth0 ifcfg-eth1 network resolv.conf
几个文件,其中hosts,network,resolv.conf分别为/etc/hosts,/etc/sysconfig/network,/etc/resolv.conf的硬链接.
而ifcfg-eth{0,1}与上面提到的是硬链接.
最近因为要远程配置cluster,因此研究了一下静态配置的方法,其实也很简单.
但是由于cluster用的系统是fedora,但自己机器上是ubuntu,发觉有些不一样,做个笔记对比下.
PS.由于ubuntu是debian系列的,我猜想debian也是差不多的
而网上查到redhat与fedora的配置文件的确是一样的.
以下仅涉及以太网的IP,netmask,gateway,broadcast设置.
以及dns,resolve配置.
共同的设置:
1. DNS服务器 resolv.conf
均使用/etc/resolv.conf ( 注意是resolv不是resolve )来配置DNS服务器
它的格式如下:
nameserver IP
nameserver IP
...
很简单
另外还有不少的option,不过发觉似乎没什么会用到的,就没有细看了.
2.静态主机名查询表 hosts
均使用/etc/hosts来记录静态的主机名,别名以及IP. 在windows下则是 %windows%\system32\hosts( 如果没记错 )
格式如下:
IP hostname alias[,alias...]
其中这行必须存在,用于定义换回接口的地址以及域名
127.0.0.1 localhost.localdomain localhost localhost
一个IP对应一个主机名以及多个别名.使用hostname可以设置以及修改域名
不同的设置
1.
ubuntu中,/etc/hostname 用来定义本机主机名,用于启动时供启动脚本读取设定.
而redhat系列貌似没有这个文件,在hostname的手册页中介绍到
The host name is usually set once at system startup in /etc/rc.d/rc.inet1 or /etc/init.d/boot (normally by reading the contents of a
file which contains the host name, e.g. /etc/hostname).
另外在网上看到的介绍是:
在/etc/sysconfig/network中进行设定.然而我在ubuntu中貌似找不到类似的文件.
我在启动脚本看到,/etc/rc.d/rc.sysvinit里含有设定的语句.
而在/etc/rc.d/rc.local中看到用nisdomainname来设定nis的domainname.
2.
ubuntu中/etc/network/interfaces用来定义各个interface的IP等设定
----------------------
我的机器该文件如下:
auto lo
iface lo inet loopback
address 127.0.0.1
netmask 255.0.0.0
iface eth0 inet static
address 172.18.34.177
netmask 255.255.252.0
gateway 172.18.35.254
auto eth0
iface eth1 inet dhcp
----------------------
其中auto表示机器启动时自动up.
iface一项定义该界面的具体参数,
static表示静态地址而dhcp表示...就是dhcp拉 -.-
其中static又应包括address,netmask,gateway.
而在redhat中,使用/etc/sysconfig/network-scripts/ifcfg-ethn来设定
其中ethn可替换为网卡名.在某台机器上看到内容ifcfg-eth0如下:
# Intel Corporation 82562ET/EZ/GT/GZ - PRO/100 VE (LOM) Ethernet Controller
DEVICE=eth0
BOOTPROTO=none
BROADCAST=202.116.76.255
IPADDR=202.116.76.163
NETMASK=255.255.255.0
NETWORK=202.116.76.0
ONBOOT=yes
GATEWAY=202.116.76.1
TYPE=Ethernet
USERCTL=no
IPV6INIT=no
PEERDNS=yes
需要填写的field其实跟ubuntu大同小异.
同时注意到,ifup和ifdown script都在这里.它们就是通过读取这里的设定来完成interface的up & down的.
但是
另外我还注意到,在/etc/sysconfig/networking中:
devices文件夹包含ifcfg-eth{0,1},其中eth0和eth1是已有的网络设备.
这两个文件与/etc/sysconfig/network-scripts的两个文件inode相同,说明是硬链接.
而在profiles/default中包含有:
hosts ifcfg-eth0 ifcfg-eth1 network resolv.conf
几个文件,其中hosts,network,resolv.conf分别为/etc/hosts,/etc/sysconfig/network,/etc/resolv.conf的硬链接.
而ifcfg-eth{0,1}与上面提到的是硬链接.
Monday, April 7, 2008
我的汉编作品
/*
* 拷贝右 (西) 二零零八 逸仙之狼工作室
* 所有权限被保留
* 文件名 : 汉语编程演示程序示例.源文件
* 编写日期:二零零八年三月二十八日
* 修订版本:一点五
* 作者:艾文尼 在 逸仙时空
* 版权所有,翻版必究
*/
# 包含 "人.头文件"
# 包含 "男人.头文件"
/**
* 类 : 女人
* 描述 : 继承父类人,实现女人某些基本功能
*/
公共 类 女人:公共 人
{
公共:
女人(字符串 姓名,整数 年龄,三元组 她的三围,布尔 她的发长):
人(姓名,年龄),三围(她的三围),发长(她的发长){}
~女人(){}
/**
* 方法 : 亲吻
* 效果 : 亲吻一个人
* 参数 : 指向一个人对象的指针
* 返回 : 真 如果 成功 假 如果 失败
*/
布尔 亲吻(对象 指针 某人):抛出 反抗异常
{
尝试
{
这个.拥抱(某人);
这个.咬嘴唇(某人;
这个.舔舌头(某人);
}
抓住(反抗异常 异常)
{
返回 假;
}
返回 真;
}
私有:
三元组 三围;
布尔 发长;
}
字符串 姓名数组 [][]={"萝莉","御姐"};
整数 主要()
{
// 创建一个女人对象
女人 指针 美女;
// 创建男人,我
男人 我;
整数 索引;
整数 年龄;
布尔 长发 赋值 真;
三元组 三围;
当(真)
{// 在死循环内歪歪
索引 赋值 随机() 取模 二;
如果 ( 索引 等于 零 )
{
年龄 赋值 十五;
三围.设置(三十,十八,二十);
}
否则
{
年龄 赋值 二十五;
三围.设置(三十五,二十,二十五);
}
美女 = 新 女人(姓名数组[索引],年龄,三围,长发 取反);
美女->亲吻(我);
删除 美女;
}
返回 零;
}
* 拷贝右 (西) 二零零八 逸仙之狼工作室
* 所有权限被保留
* 文件名 : 汉语编程演示程序示例.源文件
* 编写日期:二零零八年三月二十八日
* 修订版本:一点五
* 作者:艾文尼 在 逸仙时空
* 版权所有,翻版必究
*/
# 包含 "人.头文件"
# 包含 "男人.头文件"
/**
* 类 : 女人
* 描述 : 继承父类人,实现女人某些基本功能
*/
公共 类 女人:公共 人
{
公共:
女人(字符串 姓名,整数 年龄,三元组 她的三围,布尔 她的发长):
人(姓名,年龄),三围(她的三围),发长(她的发长){}
~女人(){}
/**
* 方法 : 亲吻
* 效果 : 亲吻一个人
* 参数 : 指向一个人对象的指针
* 返回 : 真 如果 成功 假 如果 失败
*/
布尔 亲吻(对象 指针 某人):抛出 反抗异常
{
尝试
{
这个.拥抱(某人);
这个.咬嘴唇(某人;
这个.舔舌头(某人);
}
抓住(反抗异常 异常)
{
返回 假;
}
返回 真;
}
私有:
三元组 三围;
布尔 发长;
}
字符串 姓名数组 [][]={"萝莉","御姐"};
整数 主要()
{
// 创建一个女人对象
女人 指针 美女;
// 创建男人,我
男人 我;
整数 索引;
整数 年龄;
布尔 长发 赋值 真;
三元组 三围;
当(真)
{// 在死循环内歪歪
索引 赋值 随机() 取模 二;
如果 ( 索引 等于 零 )
{
年龄 赋值 十五;
三围.设置(三十,十八,二十);
}
否则
{
年龄 赋值 二十五;
三围.设置(三十五,二十,二十五);
}
美女 = 新 女人(姓名数组[索引],年龄,三围,长发 取反);
美女->亲吻(我);
删除 美女;
}
返回 零;
}
Tuesday, April 1, 2008
序列化serialization,元编程metaprogramming,反射reflexivity,quine,语法糖衣syntactic sugar
很好很强大,一上来就遇到这么一长串题目.
今晚偶尔无聊看了一下这几个概念,其实每个概念都可以引申出一长串东西了...
不过为了做个备忘,还是稍微写写吧.不保证我理解和语言表达的正确性.最终解释均以wikipedia为准.
1.序列化,serialization
序列化可以保持对象的持久性(简单来说就是把你程序运行时对象在内存的映像保存起来,写到非易失性存储介质上).
对于普通的一个数据结构,比如
class A
{
int a;
char b;
}
这样的东东显然很容易做到,比如我只要简单地把一个4B的int和1B的char保存下来就好.
如果有一堆这样的对象,比如十个A对象,也许我可以定义我保存下来这个文件,前4个字节保存的是后面含有的A对象数,
然后就可以遍历读出来了.
但是,如果对于一个链表呢?
class Node
{
int value;
Node * next;
}
我们在创建此类对象时一般是使用动态内存分配的.那么就要考虑到:对于每个run time,显然分配到的内存地址是不大可能一样的.
因为这涉及到了内存的relocate.
那么我们应该怎麽保存这种对象数据呢?这就涉及到了序列化与逆序列化(serialization,deserialization)
More specifically,
从一个对象/指针/地址的引用转换到在存储器上的表示,可以称为"pointer unswizzling"(我也不知中文怎麽喊),也即是serialization的过程.
而反过来,从一个序列化的文件转换为一个对象可以称为"pointer swizzling",也即是deserialization的过程.
完成序列化的方法是多种多样的,还是以链表为例子.
我们可以遍历一个链表,然后给每个节点一个内部标号,最后存储时描述的数据结构就可以如下:
class _Node
{
int value;
int _id;
int _next_id;
}
因此每个对象之间的相对关系可以用偏移量计算出来,因此deserialization也是一样的原理了.当然这里还有很多情况没有分析到.
不过大概的一种实现方法就就是如此.
不同语言有不同的序列化方法.我所接触过的,有
1)Java的serialization mechanism,通过声明某对象为serializable
2)MFC的serialization
3)C++的boost库的serialization实现
其余语言略.
2.元编程(meta programming)
元编程简单来说就是可编程的编程...或者理解成自动生成代码,动态改变指令也行.
因此引申出两个概念,一个是符合这种定义/有这种功能的语言--元语言,一个是该语言能生成的语言--目标语言.如果这种语言的目标语言就是它本身,那么我们称它是自反的(反射的,reflective).
比如yacc,lex等,就是一种生成语言的语言...只不过是在源代码级的.
而我们常见的"宏",通过在编译前的预处理帮助我们生成代码,这种是宏拓展,也是在源码级的.
最强大的莫过于运行时动态修改了.现代程序设计的模型(图灵机)是把指令与数据同等对待的,
那么既然我们能动态修改数据,为什么不能修改指令呢?当然要实施相应的安全机制拉.....
比如说最近我想写这么一个脚本,不过我是脚本菜鸟 -v-
我想定义一系列的shell的环境变量,分别是for i in seq `1 8`;ip$i=192.168.1.$i;
问题是,ip[1-8]这些变量现在还没定义阿...因此后面也不能进行export.于是我只好折中地先写一个脚本生成要执行的语句,
然后再执行生成的脚本,分两步执行.殊不知这也算是一种元编程(在wikipedia上是这么说的...)
我想,如果能动态生成变量就好了.其实也许是可以的,只不过我不会而已.....
另一个典型的例子是java的反射机制,这又要涉及到了所谓的first-class datatype.关于这个就先不说了.
在经典的C/C++等语言中,基本的数据类型/对象有int,char等这些,但是在java中,连类,方法本身也是一种对象!
因此对于类,方法,我们可以保存一些元信息,来做到一些强悍的事情.
比如我们可以动态地执行一个方法,通过接收用户的输入,然后在类里面查找相应的方法,创建一个这个方法的引用,
然后调用之.这在以往的C/C++中根本不可想象.
C++貌似也想加入一点这个特性,比如RTTI也算是一个半成品.另外template也多少有点这么个意思.
只不过template现在引出的是generic programming,范型编程,此处不表...
关于元编程,我理解的就这么多,还要更都的可以去学习一下lisp等...可以参见这位大牛...
http://pluskid.lifegoo.com/?p=46#more-46
最后要小小地说一下"quine",在programming领域中,它指的是"能够打印自己源代码的程序".
往往被hacker们用来show自己对某种语言的熟练与掌握程度.
Quine 以哲学家 Willard van Orman Quine (1908-2000) 而命名.因为他提出了" indirect self-reference"这个概念.
与它相关的有这么一个悖论:"This sentence is false."
那么,究竟那句sentence是对还是错呢 ^_^ 说它对时,也就承认了它是错的;说它错时,也就承认了它是对的......
一个最简单的C-quine如下,很强大:
main(a){printf(a,34,a="main(a){printf(a,34,a=%c%s%c,34);}",34);}
更多的请继续参看这位童鞋的wiki:
http://pluskid.lifegoo.com/wiki/Quine.html
3.语法糖衣syntactic sugar
这个比较好理解.我们知道一种语言有固定的语法结构与关键字.
程序设计的三种基本结构为顺序,选择,循环.
因此完成了这些基本功能的语言的语法与关键字我们可以看作一个集合,在这个集合里面我们可以干出程序允许的任何事.
但是如果我们添加一些关键字后,也许可以增强程序的可读性,或者降低编程的复杂度,然而我们不能做出比原来更多的事!
举一个例子,比如在C++中,我们完全可以使用for来完成所有的循环,而while可以改写成for.
另外由if-else结构也能完成所有的条件语句,switch, :? 这些都可以转化成if-else的表示.
因此很直观地,我们可以定义这种语言的语法的"核心"(core syntax).
语法糖衣是好的还是不好的?也许对于我们这些普通人他们是好的,习惯了写for loop的我在写shell程序时觉得写一个for i in ...
觉得很脑残,幸而有for((;;)) 这个糖衣帮我解决了问题.
然而大牛们一致认为这是没有必要的,因为单靠最基本的语法就能解决问题.
这又牵涉到了数学问题,学过scheme等函数式语言的都知道,所有语句其实都是由表达式递归定义而成,包括循环,选择.
因此大牛们写程序往往可以用几个括号,四则运算,数字就搞定了....
Linux内核维护者也坚持只需要用C来完成OO以及所有功能,而不需要C++等.
更直观地说,比如我们可以这种定义正整数:
1)最小的数是1
2)第i大的数是比它前一位的数加1
(可能写得有点不准确,不过递归定义的思想基本就如此)
然后还有两个不那么流行的术语:
语法盐 syntactic salt
被用于增强程序健壮性或代码编写规范的语法,它们本身并不能简化程序的写法或增强语言的功能.
比如一些程序语言中提倡if与endif要配对,而不是简单地用{}括起来.
语法糖精 Syntactic saccharin
这个比较无聊,指那些并不能使程序编写简单的无用的特性.
---分割线来了---
恩,好了,大概就联想这么多...
愚人节就让我geek一回...
今晚偶尔无聊看了一下这几个概念,其实每个概念都可以引申出一长串东西了...
不过为了做个备忘,还是稍微写写吧.不保证我理解和语言表达的正确性.最终解释均以wikipedia为准.
1.序列化,serialization
序列化可以保持对象的持久性(简单来说就是把你程序运行时对象在内存的映像保存起来,写到非易失性存储介质上).
对于普通的一个数据结构,比如
class A
{
int a;
char b;
}
这样的东东显然很容易做到,比如我只要简单地把一个4B的int和1B的char保存下来就好.
如果有一堆这样的对象,比如十个A对象,也许我可以定义我保存下来这个文件,前4个字节保存的是后面含有的A对象数,
然后就可以遍历读出来了.
但是,如果对于一个链表呢?
class Node
{
int value;
Node * next;
}
我们在创建此类对象时一般是使用动态内存分配的.那么就要考虑到:对于每个run time,显然分配到的内存地址是不大可能一样的.
因为这涉及到了内存的relocate.
那么我们应该怎麽保存这种对象数据呢?这就涉及到了序列化与逆序列化(serialization,deserialization)
More specifically,
从一个对象/指针/地址的引用转换到在存储器上的表示,可以称为"pointer unswizzling"(我也不知中文怎麽喊),也即是serialization的过程.
而反过来,从一个序列化的文件转换为一个对象可以称为"pointer swizzling",也即是deserialization的过程.
完成序列化的方法是多种多样的,还是以链表为例子.
我们可以遍历一个链表,然后给每个节点一个内部标号,最后存储时描述的数据结构就可以如下:
class _Node
{
int value;
int _id;
int _next_id;
}
因此每个对象之间的相对关系可以用偏移量计算出来,因此deserialization也是一样的原理了.当然这里还有很多情况没有分析到.
不过大概的一种实现方法就就是如此.
不同语言有不同的序列化方法.我所接触过的,有
1)Java的serialization mechanism,通过声明某对象为serializable
2)MFC的serialization
3)C++的boost库的serialization实现
其余语言略.
2.元编程(meta programming)
元编程简单来说就是可编程的编程...或者理解成自动生成代码,动态改变指令也行.
因此引申出两个概念,一个是符合这种定义/有这种功能的语言--元语言,一个是该语言能生成的语言--目标语言.如果这种语言的目标语言就是它本身,那么我们称它是自反的(反射的,reflective).
比如yacc,lex等,就是一种生成语言的语言...只不过是在源代码级的.
而我们常见的"宏",通过在编译前的预处理帮助我们生成代码,这种是宏拓展,也是在源码级的.
最强大的莫过于运行时动态修改了.现代程序设计的模型(图灵机)是把指令与数据同等对待的,
那么既然我们能动态修改数据,为什么不能修改指令呢?当然要实施相应的安全机制拉.....
比如说最近我想写这么一个脚本,不过我是脚本菜鸟 -v-
我想定义一系列的shell的环境变量,分别是for i in seq `1 8`;ip$i=192.168.1.$i;
问题是,ip[1-8]这些变量现在还没定义阿...因此后面也不能进行export.于是我只好折中地先写一个脚本生成要执行的语句,
然后再执行生成的脚本,分两步执行.殊不知这也算是一种元编程(在wikipedia上是这么说的...)
我想,如果能动态生成变量就好了.其实也许是可以的,只不过我不会而已.....
另一个典型的例子是java的反射机制,这又要涉及到了所谓的first-class datatype.关于这个就先不说了.
在经典的C/C++等语言中,基本的数据类型/对象有int,char等这些,但是在java中,连类,方法本身也是一种对象!
因此对于类,方法,我们可以保存一些元信息,来做到一些强悍的事情.
比如我们可以动态地执行一个方法,通过接收用户的输入,然后在类里面查找相应的方法,创建一个这个方法的引用,
然后调用之.这在以往的C/C++中根本不可想象.
C++貌似也想加入一点这个特性,比如RTTI也算是一个半成品.另外template也多少有点这么个意思.
只不过template现在引出的是generic programming,范型编程,此处不表...
关于元编程,我理解的就这么多,还要更都的可以去学习一下lisp等...可以参见这位大牛...
http://pluskid.lifegoo.com/?p=46#more-46
最后要小小地说一下"quine",在programming领域中,它指的是"能够打印自己源代码的程序".
往往被hacker们用来show自己对某种语言的熟练与掌握程度.
Quine 以哲学家 Willard van Orman Quine (1908-2000) 而命名.因为他提出了" indirect self-reference"这个概念.
与它相关的有这么一个悖论:"This sentence is false."
那么,究竟那句sentence是对还是错呢 ^_^ 说它对时,也就承认了它是错的;说它错时,也就承认了它是对的......
一个最简单的C-quine如下,很强大:
main(a){printf(a,34,a="main(a){printf(a,34,a=%c%s%c,34);}",34);}
更多的请继续参看这位童鞋的wiki:
http://pluskid.lifegoo.com/wiki/Quine.html
3.语法糖衣syntactic sugar
这个比较好理解.我们知道一种语言有固定的语法结构与关键字.
程序设计的三种基本结构为顺序,选择,循环.
因此完成了这些基本功能的语言的语法与关键字我们可以看作一个集合,在这个集合里面我们可以干出程序允许的任何事.
但是如果我们添加一些关键字后,也许可以增强程序的可读性,或者降低编程的复杂度,然而我们不能做出比原来更多的事!
举一个例子,比如在C++中,我们完全可以使用for来完成所有的循环,而while可以改写成for.
另外由if-else结构也能完成所有的条件语句,switch, :? 这些都可以转化成if-else的表示.
因此很直观地,我们可以定义这种语言的语法的"核心"(core syntax).
语法糖衣是好的还是不好的?也许对于我们这些普通人他们是好的,习惯了写for loop的我在写shell程序时觉得写一个for i in ...
觉得很脑残,幸而有for((;;)) 这个糖衣帮我解决了问题.
然而大牛们一致认为这是没有必要的,因为单靠最基本的语法就能解决问题.
这又牵涉到了数学问题,学过scheme等函数式语言的都知道,所有语句其实都是由表达式递归定义而成,包括循环,选择.
因此大牛们写程序往往可以用几个括号,四则运算,数字就搞定了....
Linux内核维护者也坚持只需要用C来完成OO以及所有功能,而不需要C++等.
更直观地说,比如我们可以这种定义正整数:
1)最小的数是1
2)第i大的数是比它前一位的数加1
(可能写得有点不准确,不过递归定义的思想基本就如此)
然后还有两个不那么流行的术语:
语法盐 syntactic salt
被用于增强程序健壮性或代码编写规范的语法,它们本身并不能简化程序的写法或增强语言的功能.
比如一些程序语言中提倡if与endif要配对,而不是简单地用{}括起来.
语法糖精 Syntactic saccharin
这个比较无聊,指那些并不能使程序编写简单的无用的特性.
---分割线来了---
恩,好了,大概就联想这么多...
愚人节就让我geek一回...
Subscribe to:
Posts (Atom)