2008年04月17日

转自http://blog.163.com/hello-_-world/blog/static/231894442007101995827755/

Linux与Windows 共享文件Samba

作者:北南南北,正在增加中… … 需要您的参与;
来自:LinuxSir.Org
简介:本文只是讲一讲我们最常用的Linux与Windows共享文件,主要是为新手指一指路。如何建立最简单的Samba服务器,并讲述遇到问题应该从何处寻找解决方案;正在更新之中,希望您的参加 … … 谢谢;

目录

0、架设Samba 服务器的前提;
0.1 查看文件内容和编辑文件的工具;
0.2 关于文件和目录相关;
03 用户和用户组相关;
04 进程管理;
1 Samba 简介
2 Samba 功能和应用范围
3 Samba 两个服务器相关启动程序、客户端及服务器配置文件等;
3.1 Samba 有两个服务器,一个是smbd,另一个是nmbd;
3.2 查看Samba 服务器的端口及防火墙;
3.3 查看Samba 服务器的配置文件;
3.4 Samba 在Linux 中的一些工具(服务器端和客户端);
3.5 在Linux 中的常用工具,Windows查看Linux共享的方法 ;
3.5.1 在Linux系统中查看网络中Windows共享文件及Linux中的Samba共享文件;
3.5.2 在Windows中访问Linux Samba服务器共享文件的办法;
3.5.3 smbfs文件系统的挂载;
4 由最简单的一个例子说起,匿名用户可读可写的实现;

第一步: 更改smb.conf
第二步:建立相应目录并授权;
第三步:启动smbd和nmbd服务器;
第四步:查看smbd进程,确认Samba 服务器是否运行起来了;
第五步:访问Samba 服务器的共享;
5、复杂一点的用户共享模型(适合10人左右的小型企业);

5.1 共享权限设计实现的功能;
5.2 在服务器上创建相应的目录;
5.3 添加用户用户组,设置相应目录家目录的权限;
5.3.1 添加用户组;
5.3.2 添加用户;
5.3.3 添加samba用户,并设置密码;
5.3.4 配置相关目录的权限和归属;
5.4 修改Samba配置文件;
5.5 关于客户端访问;
5.5.1 Windows客户端访问;

++++++++++++++++++++++++++++++++++++++++++++++++
正文
++++++++++++++++++++++++++++++++++++++++++++++++

0、架设Samba 服务器的前提;

Linux是一个多用户的操作系统,对任何服务器的架设与都用户、用户组及权限相关,这是操作的基础。Samba服务器也不例外,对这些知识的掌握也是极为重要的。在Windows系统上虽然也能架共享文件服务器,但它的权限控制实在令人不敢恭维。如果我们用Windows系统来架网络共享文件系统,就是点鼠标也能把我们点迷糊了。但在Linux中,我们可以轻松的改一改配置文件,不到几分钟就能建好自己的Samba服务器。哪个更容易,只有你知道;

对于Samba服务器的架设,有的弟兄简单的认为,只要把改一下配置文件,创建好相应的目录就行了。其实并不是这样的,还要深入的工作,比如目录的权限和归属,也就是说能让哪个用户和用户组有读写权。只有把配置文件和共享目录的权限结合起来,才能架好Samba服务器;

下面是常用的基础知识,我们在本文中所涉及的内容都可以在下面的列表中找到相应的解释;

0.1 查看文件内容和编辑文件的工具;

《Linux 文件内容查看工具介绍》
《文件编辑器 vi》

0.2 关于文件和目录相关;

《Linux 文件类型 及文件的扩展名》
《Linux 文件和目录管理之列出、删除、复制、移动及改名》
《Linux 文件和目录的属性》
《简述Linux文件搜索》

03 用户和用户组相关;

《Linux 用户(user)和用户组(group)管理概述》
《用户(User)和用户组(Group)配置文件详解》
《Linux 用户管理工具介绍》
《Linux 用户(User)查询篇》

04 进程管理;

《Linux 进程管理》

1 Samba 简介

Samba(SMB是其缩写) 是一个网络服务器,用于Linux和Windows共享文件之用;Samba 即可以用于Windows和Linux之间的共享文件,也一样用于Linux和Linux之间的共享文件;不过对于Linux和Linux之间共享文件有更好的网络文件系统NFS,NFS也是需要架设服务器的;

大家知道在Windows 网络中的每台机器即可以是文件共享的服务器,也可以同是客户机;Samba 也一样能行,比如一台Linux的机器,如果架了Samba Server 后,它能充当共享服务器,同时也能做为客户机来访问其它网络中的Windows共享文件系统,或其它Linux的Sabmba 服务器;

我们在Windows网络中,看到共享文件功能知道,我们直接就可以把共享文件夹当做本地硬盘来使用。在Linux的中,就是通过Samba的向网络中的机器提供共享文件系统,也可以把网络中其它机器的共享挂载在本地机上使用;这在一定意义上说和FTP是不一样的。

Samba 用的netbios协议,如果您用Samba 不成功,

Linux与Windows 、Linux 和 Linux

2 Samba 功能和应用范围

Samba 应该范围主要是Windows和Linux 系统共存的网络中使用;如果一个网络环境都是Linux或Unix类的系统,没有必要用Samba,应该用NFS更好一点;

那Samba 能为我们提供点什么服务呢?主要是共享文件和共享打印机;

3 Samba 两个服务器相关启动程序、客户端及服务器配置文件等;

3.1 Samba 有两个服务器,一个是smb,另一个是nmb;

smb 是Samba 的主要启动服务器,让其它机器能知道此机器共享了什么;如果不打开nmb服务器的话,只能通过IP来访问,比如在Windows的IE浏览器上打入下面的一条来访问;

\\192.168.1.5\共享目录
\\192.168.1.5\opt

而nmb是解析用的,解析了什么呢?就是把这台Linux机器所共享的工作组及在此工作组下的netbios name解析出来;
一般的情况下,在RPM包的系统,如果是用RPM包安装的Samba ,一般可以通过如下的方式来启动Samba服务器;

[root@localhost ~]# /etc/init.d/smb start
启动 SMB 服务: [ 确定 ]
启动 NMB 服务: [ 确定 ]

如果停止呢?就在smb后面加stop ;重启就是restart

[root@localhost ~]# /etc/init.d/smb stop
[root@localhost ~]# /etc/init.d/smb restart

对于所有系统来说,通用的办法就是直接运行smb 和nmb;当然您要知道smb和nmb所在的目录才行;如果是自己编译的Samba ,您应该知道您把Samba放在哪里了;

[root@localhost ~]# /usr/sbin/smbd
[root@localhost ~]# /usr/sbin/nmbd

查看服务器是否运行起来了,则用下面的命令;
[root@localhost ~]# pgrep smbd
[root@localhost ~]# pgrep nmbd

关掉Samba服务器,也可以用下面的办法,大多是通用的;要root权限来执行;

[root@localhost ~]# pkill smbd
[root@localhost ~]# pkill nmbd

3.2 查看Samba 服务器的端口及防火墙;

查看这个有何用呢?有时你的防火墙可能会把smbd服务器的端口封掉,所以我们应该smbd服务器所占用的端口;下面查看中,我们知道smbd所占用的端口是139和445 ;

[root@localhost ~]# netstat -tlnp |grep smb
tcp 0 0 0.0.0.0:139 0.0.0.0:* LISTEN 10639/smbd
tcp 0 0 0.0.0.0:445 0.0.0.0:* LISTEN 10639/smbd
如果您有防火墙,一定要把这两个端口打开。如果不知道怎么打开。可能你和我一样是新手,还是把防火墙规则清掉也行;

[root@localhost ~]# iptables -F

[root@localhost ~]# /sbin/iptables -F
3.3、查看Samba 服务器的配置文件;

如果我们是用Linux发行版自带的Samba软件包,一般情况下Samba服务器的配置文件都位于/etc/samba目录中,服务器的主配置文件是smb.conf;也有有户配置文件 smbpasswd、smbusers和lmhosts等(最好您查看一下这些文件的内容);还有一个文件是secrets.tdb,这个文件是 Samba 服务器启动手自动生成的;我们慢慢根据教程的进度来适当地增加这些文件的说明吧;一下子都说出来,感觉内容太多;所以只能一点一点的来了;

3.4、Samba 在Linux 中的一些工具(服务器端和客户端);

smbcacls smbcontrol smbencrypt smbmount smbprint smbstatus smbtree
smbclient smbcquotas smbmnt smbpasswd smbspool smbtar smbumount
smbd nmbd mount

其中服务器端的是smbd、nmbd、smbpasswd ;其它的大多是客户端;这些并不是都需要一定要精通的,但至少得会用几个;比如smbmount(也就是mount 加参数的用法),还用smbclient等;

3.5 在Linux 中的常用工具mount(smbmount)和smbclient;Windows查看Linux共享的方法 ;

3.5.1 在Linux系统中查看网络中Windows共享文件及Linux中的Samba共享文件;

一般的情况下,我们要用到smbclient;常用的用法也无非是下面的;

[root@localhost ~]# smbclient -L //ip地址或计算机名
smbclient 是Samba 的Linux 客户端,在Linux机器上用来查看服务器上的共享资源,也可以象FTP一样,用户可以登录Samba服务器,也可以上传put和下载get文件,遗憾的是对中文支持并不友好;

查看服务器上的资源;

smbclient -L //IP [-U 用户名]
如果您的Samba服务器配置为user模式,就要加 “-U 用户名“,如果是share模式,省略也可;

比如:

[root@localhost ~]# smbclient -L //192.168.1.3 -U sir01
Password: 请输入用户sir01的密码
如果您是用share模式,就可以不必理会用户和密码,直接用;

[root@localhost ~]# smbclient -L //192.168.1.3
Password: 直接按回车
登录用户身份Samba服务器共享

以用户身份登录共享后,能象FTP用户一样,下传和下载文件;用put表示上传,用get表示下载;

smbclient //IP地址/共享文件夹 -U 用户
说明:IP地址大家都知道,你不知道自己的IP地址,可以用/sbin/ifconfig 来查看; 共享文件夹是我们在smb.conf中定义的[共享文件夹],比如[sir01]。-U 用户名表示Samba 的用户;

比如:

[root@localhost ~]# smbclient //192.168.1.3/sir01 -U sir01
Password:
Domain=[LINUXSIR] OS=[Unix] Server=[Samba 3.0.21b-2]
smb: \> ls
说明:登录到Samba服务器上,就可以用smbclient的一些指令,可以象用FTP指令一样上传和下载文件;

smbclient 命令说明

命令 说明?或help [command] 提供关于帮助或某个命令的帮助![shell command] 执行所用的SHELL命令,或让用户进入 SHELL提示符cd [目录] 切换到服务器端的指定目录,如未指定,则 smbclient 返回当前本地目录lcd [目录] 切换到客户端指定的目录;dir 或ls 列出当前目录下的文件;exit 或quit 退出smbclient get file1 file2 从服务器上下载file1,并以文件名file2存在本地机上;如果不想改名,可以把file2省略mget file1 file2 file3 filen 从服务器上下载多个文件;md或mkdir 目录 在服务器上创建目录rd或rmdir 目录 删除服务器上的目录put file1 [file2] 向服务器上传一个文件file1,传到服务器上改名为file2;mput file1 file2 filen 向服务器上传多个文件3.5.2 在Windows中访问Linux Samba服务器共享文件的办法;

这个简单吧,在网上领居,查看工作组就能看得到,或者在浏览器上输入如下的

\\ip地址或计算机名
这样就能看到这个机器上有什么共享的了,点鼠标操作完成;如果访问不了,不要忘记把Linux的防火墙规划清掉,或让相应的端口通过;

3.5.3 在Linux中smbfs文件系统的挂载;

mount 的用法,加载网络中的共享文件夹到本地机;mount就是用于挂载文件系统的,SMB做为网络文件系统的一种,也能用mount挂载;smbmount说到底也是用mount的一个变种;

mount 挂载smbfs的用法;

mount -t smbfs -o codepage=cp936,username=用户名,password=密码 , -l //ip地址/共享文件夹名 挂载点

mount -t smbfs -o codepage=cp936,username=用户名,password=密码 , -l //计算机名/共享文件夹名 挂载点

mount -t smbfs -o codepage=cp936 //ip地址或计算机名/共享文件夹名 挂载点

smbmount的用法:

smbmount -o username=用户名,password=密码 , -l //ip地址或计算机名/共享文件夹名 挂载点
smbmount //ip地址或计算机名/共享文件夹名 挂载点

说明:
如果您的服务器是以share共享的,则无需用户名和密码就能挂载,如果出现要密码的提示,直接回车就行;您也可以用smbmount 来挂载,这样就无需用mount -t smbfs来指定文件系统的类型了;

对于挂载点,我们要自己建立一个文件夹,比如我们可以建在/opt/smbhd,这由您说的算吧;

在mount的命令中,我们发现有这样的一个参数codepage=cp936,这是服务器端文件系统的编码的指定,cp936 就是简体中文,当然您可以用utf8等,尝试一下吧。

如果您挂载了远程的smbfs文件系统出现的是简体中文乱码,就要考虑挂载时要指定编码了;

4、由最简单的一个例子说起,匿名用户可读可写的实现;

第一步: 更改smb.conf

我们来实现一个最简单的功能,让所有用户可以读写一个Samba 服务器共享的一个文件夹;我们要改动一下smb.conf ;首先您要备份一下smb.conf文件;

[root@localhost ~]# cd /etc/samba
[root@localhost samba]# mv smb.conf smb.confBAK
然后我们来重新创建一个smb.conf文件;

[root@localhost samba]#touch smb.conf

然后我们把下面这段写入smb.conf中;

[global]
workgroup = LinuxSir
netbios name = LinuxSir05
server string = Linux Samba Server TestServer
security = share

[linuxsir]
path = /opt/linuxsir
writeable = yes
browseable = yes
guest ok = yes

注解:
[global]这段是全局配置,是必段写的。其中有如下的几行;

workgroup 就是Windows中显示的工作组;在这里我设置的是LINUXSIR (用大写);
netbios name 就是在Windows中显示出来的计算机名;
server string 就是Samba服务器说明,可以自己来定义;这个不是什么重要的;
security 这是验证和登录方式,这里我们用了share ;验证方式有好多种,这是其中一种;另外一种常用的是user的验证方式;如果用share呢,就是不用设置用户和密码了;

[linuxsir] 这个在Windows中显示出来是共享的目录;
path = 可以设置要共享的目录放在哪里;
writeable 是否可写,这里我设置为可写;
browseable 是否可以浏览,可以;可以浏览意味着,我们在工作组下能看到共享文件夹。如果您不想显示出来,那就设置为 browseable=no

guest ok 匿名用户以guest身份是登录;

第二步:建立相应目录并授权;

[root@localhost ~]# mkdir -p /opt/linuxsir
[root@localhost ~]# id nobody
uid=99(nobody) gid=99(nobody) groups=99(nobody)

[root@localhost ~]# chown -R nobody:nobody /opt/linuxsir

注释:关于授权nobody,我们先用id命令查看了nobody用户的信息,发现他的用户组也是nobody,我们要以这个为准。有些系统nobody用户组并非是nobody ;
第三步:启动smbd和nmbd服务器;

[root@localhost ~]# smbd
[root@localhost ~]# nmbd
第四步:查看smbd进程,确认Samba 服务器是否运行起来了;

[root@localhost ~]# pgrep smbd
13564
13568

第五步:访问Samba 服务器的共享;

在Linux 中您可以用下面的命令来访问;

[root@localhost ~]# smbclient -L //LinuxSir05
Password: 注:直接按回车

在Windows中,您可以用下面的办法来访问;

\\LinuxSir05\

5、复杂一点的用户共享模型(适合10人左右的小型企业);

比如一个公司有五个部门,分别是linuxsir,sir01,sir02,sir03,sir04。我们想为这家公司设计一个比较安全的共享文件模型。每个用户都有自己的网络磁盘,sir01到sir04还有共用的网络硬盘;所有用户(包括匿名用户)有一个共享资料库,此库为了安全是只读的;所有的用户(包括匿名用户)要有一个临时文件终转的文件夹… ….

5.1 共享权限设计实现的功能;

1)linuxsir部门具有管理所有SMB空间的权限;
2)sir01到sir04拥有自己的空间,并且除了自身及linuxsir有权限以外,对其它用户具有绝对隐私性;
3)linuxsir01到linuxsir04拥有一个共同的读写权限的空间;
4) 所有用户(包括匿名用户)有一个有读权限的空间,用于资料库,所以不要求写入数据。
5)sir01到sir04还有一个共同的空间,对sir01到sir04的用户来说是隐私的,不能让其它用户来访问。
6) 还要有一个空间,让所有用户可以写入,能删除等功能,在权限上无限制 ,用于公司所有用户的临时文档终转等;

5.2 在服务器上创建相应的目录;

[root@localhost ~]# mkdir -p /opt/linuxsir
[root@localhost ~]# cd /opt/linuxsir
[root@localhost linuxsir]# mkdir sir01 sir02 sir03 sir04 sirshare sir0104rw sirallrw
[root@localhost linuxsir]# ls

sir01 sir0104rw sir02 sir03 sir04 sirallrw sirshare
注:功用如下:

/opt/linuxsir 这是管理员目录,负责管理其下所有目录;
/opt/linuxsir/sir01 是sir01的家目录,用于私用,除了用户本身和linuxsir以外其它用户都是不可读不可写;
/opt/linuxsir/sir02 是sir02的家目录,用于私用,除了用户本身和linuxsir以外其它用户都是不可读不可写;
/opt/linuxsir/sir03 是sir03的家目录,用于私用,除了用户本身和linuxsir以外其它用户都是不可读不可写;
/opt/linuxsir/sir04 是sir04的家目录,用于私用,除了用户本身和linuxsir以外其它用户都是不可读不可写;
/opt/linuxsir/sirshare 所用用户(除了linuxsir有权限写入外)只读目录
/opt/linuxsir/sir0104rw 是用于sir01到sir04用户可读可写共用目录,但匿名用户不能读写;
/opt/linuxsir/sirallrw 用于所有用户(包括匿名用户)的可读可写;

5.3 添加用户用户组,设置相应目录家目录的权限;

5.3.1 添加用户组;

[root@localhost ~]# /usr/sbin/groupadd linuxsir
[root@localhost ~]# /usr/sbin/groupadd sir01
[root@localhost ~]# /usr/sbin/groupadd sir02
[root@localhost ~]# /usr/sbin/groupadd sir03
[root@localhost ~]# /usr/sbin/groupadd sir04
[root@localhost ~]# /usr/sbin/groupadd sir0104

5.3.2 添加用户;

[root@cuc03 ~]# adduser -g sir01 -G sir0104 -d /opt/linuxsir/sir01 -s /sbin/nologin sir01
[root@cuc03 ~]# adduser -g sir02 -G sir0104 -d /opt/linuxsir/sir02 -s /sbin/nologin sir02
[root@cuc03 ~]# adduser -g sir03 -G sir0104 -d /opt/linuxsir/sir03 -s /sbin/nologin sir03
[root@cuc03 ~]# adduser -g sir04 -G sir0104 -d /opt/linuxsir/sir04 -s /sbin/nologin sir04
[root@cuc03 ~]# adduser -g linuxsir -d /opt/linuxsir -G linuxsir,sir01,sir02,sir03,sir04,sir0104 -d /opt/linuxsir -s /sbin/nologin linuxsir
为什么这样添加用户?请参考:

《Linux 文件和目录的属性》
《Linux 用户管理工具介绍》

当然我们还得学会查看用户信息的工具用法,比如 用finger和id来查看用户信息,主要是看用户是否添加正确;比如;请参考《Linux 用户(User)查询篇》

[root@localhost ~]# id linuxsir
[root@localhost ~]# finger linuxsir

5.3.3 添加samba用户,并设置密码;

我们用的方法是先添加用户,但添加的这些用户都是虚拟用户,因为这些用户是不能通过SHELL登录系统的;另外值得注意的是系统用户密码和 Samba用户的密码是不同的。如果您设置了系统用户能登入SHELL,可以设置用户的Samba密码和系统用户通过SHELL登录的密码不同。

我们通过smbpasswd 来添加Samba用户,并设置密码。原理是通过读取/etc/passwd文件中存在的用户名。

[root@localhost sir01]# smbpasswd -a linuxsir
New SMB password: 注:在这里添加Samba用户linuxsir的密码;
Retype new SMB password: 注:再输入一次;
用同样的方法来添加 sir01、sir02、sir03、sir04的密码;

5.3.4 配置相关目录的权限和归属;

[root@cuc03 ~]# chmod 755 /opt/linux
[root@cuc03 ~]# chown linuxsir:linuxsir /opt/linuxsir

[root@cuc03 ~]# cd /opt/linuxsir
[root@cuc03 ~]# chmod 2770 sir0*

[root@cuc03 ~]# chown sir01.linuxsir sir01

[root@cuc03 ~]# chown sir02.linuxsir sir02

[root@cuc03 ~]# chown sir03.linuxsir sir03

[root@cuc03 ~]# chown sir04.linuxsir sir04

[root@cuc03 ~]# chown linuxsir.sir0104 sir0104rw

[root@cuc03 ~]# chown linuxsir.linuxsir sirshare
[root@cuc03 ~]# chmod 755 sirshare

[root@cuc03 ~]# chown linuxsir:linuxsir sirallrw
[root@cuc03 ~]# chmod 3777 sirallrw

5.4 修改Samba配置文件 smb.conf;

配置文件如下,修改/etc/samba/smb.conf后,不要忘记重启smbd和nmbd服务器;

[global]
workgroup = LINUXSIR
netbios name = LinuxSir
server string = Linux Samba Test Server
security = share

[linuxsir]
comment = linuxsiradmin
path = /opt/linuxsir/
create mask = 0664
#create mask是用户创建文件时的权限掩码;对用户来可读可写,对用户组可读可写,对其它用户可读;
directory mask = 0775
#directory mask 是用来设置用户创建目录时的权限掩码,意思是对于用户和用户组可读可写,对其它用户可读可执行;
writeable = yes
valid users = linuxsir
browseable = yes

[sirshare]
path = /opt/linuxsir/sirshare
writeable = yes
browseable = yes
guest ok = yes

[sirallrw]
path = /opt/linuxsir/sirallrw
writeable = yes
browseable = yes
guest ok = yes

[sir0104rw]
comment = sir0104rw
path = /opt/linuxsir/sir0104rw
create mask = 0664
directory mask = 0775
writeable = yes
valid users = linuxsir,@sir0104
#@sir0104是用户组;
browseable = yes

[sir01]
comment = sir01
path = /opt/linuxsir/sir01
create mask = 0664
directory mask = 0775
writeable = yes
valid users = sir01,@linuxsir
browseable = yes

[sir02]
comment = sir02
path = /opt/linuxsir/sir02
create mask = 0664
directory mask = 0775
writeable = yes
valid users = sir02,@linuxsir
browseable = yes

[sir03]
comment = sir03
path = /opt/linuxsir/sir03
create mask = 0664
directory mask = 0775
writeable = yes
valid users = sir03,@linuxsir
browseable = yes

[sir04]
comment = sir04
path = /opt/linuxsir/sir04
create mask = 0664
directory mask = 0775
writeable = yes
valid users = sir04,@linuxsir
browseable = yes

5.5 关于客户端访问;

5.5.1 Windows 访问;

我们打开Windows的IE浏览器,用IP地址的访问方式就能访问了,格式为 \\192.168.1.3 类似的。当然也可以把共享文件夹挂在本地使用。比如我们把sir01文件夹挂在本地中,应该以sir01用户来挂载,挂载流程图如下;

2006年04月23日

(一) 网络中遍布著大量的Linux相关站点;

(二)用户无须详细了解每一个此类站点,实际上,一百个站点足够你使用了。
  

  评选出的这100个优秀站点,将按照下述20个类别作以评介:

  (一) 文件下载

  (二) 幽默娱乐

  (三) 相关新闻

  (四) 通用硬体

  (五) 专用硬体

  (六) 新手站点

  (七) 图形/多媒体

  (八) 游戏站点

  (九) 网路杂志

  (十) 入口(教育、链结)

  (十一) 软体发展

  (十二) 购物

  (十三) Linux内核

  (十四) 职业机会

  (十五) 科学工程

  (十六) 文档管理

  (十七) X-Window 系统

  (十八) Linux 分发站点

  (十九) 用户团体

  (二十) 网管站点

                 

(一) 软件下载

(1) Freshmeat站点

网址:http://www.freshmeat.net

评介:如果你绝对肯定,非要获取开放源代码应用程式,那毫无疑问,
Freshmeat就是个不错的站点。
这个最值得推崇的软体下载站点,有著数以千计的大量开放源代码应用程式的分类链结。
此外,Freshmeat站点在更新程式的基础上,每天还会添加10到30个新程式链结。

(2) Tucows Linux

网址:http://linux.tucows.com

评介:最初,该站点是一个基於Windows的软体园地,几年後,Tucows拓宽领域。
现在,该站点已经发展成为了最开放的Linux下载站点之一。
不过,说真的,这也是因为Linux从一开始就增强了伺服器的缘故。

(3) Woven Goods for Linux

网址:http://www.fokus.gmd.de/linux

评介:Woven Goods for Linux 是一个德语站点,
它的特徵就在於英文和德文版的Linux程式下载和文档。
该站点还有一个很不错的综合列表,几乎列出了你所能想像出的每一个Linux分发。

(4) Linux ISO Images

网址:http://www.LinuxISO.org

评介:是不是已经极其厌倦了查找ISO图像?
在LinuxISO.org站点中一个非常醒目的地方,就放置了最流行的Linux 分发ISOs的链结。
当然,它不能让你56k的数据机具有更快的下载速度,但他们已经竭尽所能了,
那些有DSL或光缆数据机的用户们会非常高兴的。

(5) RPMfind.net

网址:http://www.rpmfind.net

评介:如果你还沉浸在网路海洋寻找最新用RPM
(Red Hat Package Manager)格式编写的软体,
那这个站点最适合不过了。
凡是存在的RPM Package,这里都可以找到,而且这些软体还被编进了索引,
用户可以通过多种不同方式来分类。
例如,你可以分别用类别(比如游戏等等)、创建日期、
package maintainer或名称等等多种方式查询一个套装软体。

(二)娱乐休闲

(1) UserFriendly

网址:http://www.userfriendly.org

评介:真应该建议Netscape在流览器(就在"Home"旁边)上添加一个按钮,
以便用户可以很轻易地跳转到User Friendly上的Daily Static链结中去。
喜欢新奇感觉的用户可能没有人愿意错过该站点上的冒险体验。
此外,还有其他像卡通等等内容丰富的东西。
User Friendly站点的最大特点就是每日都有新服务内容,
而且还有庞大的人才资料库和Ufie社区。

(2) Segfault

网址:http://www.segfault.org

评介:是一个不错的Linux娱乐站点。
该站点的特徵在於喜欢拿Linux界的名流人物来开涮,非常可笑且带有讽刺意味。
在这里用户不会找到太多有用的资料,但绝对可以让你捧腹大笑。

(3) Sluggy Freelance

网址:http://www.sluggy.com

评介:可以肯定,第一名的UserFriendly绝对不是惟一的滑稽喜剧站点,
Sluggy Freelance就是一个典型例证。
该站点的创建日期可以回溯到1997年,特徵就是提供了不少通俗易懂的素材。
尤其值得一提的是,Sluggy站点非常体贴新用户,专门在最醒目的位置放置了新读者指南。
建议大家不妨请一天假,完完整整地流览一个这个不错的网站。

(4) Humorix

网址:http://i-want-a-website.com/about-linux

评介:Humorix站点既讲述Linux的相关知识,
又著力於Linux,、Microsoft以及其他许多相关系统或软体的趣事收集。
此外,还有许多专栏作者和自愿投稿者的搞笑文章。

(5) Jargon File

网址:http://www.tuxedo.org/~esr/jargon

评介:不是特别了解"行话"?难道不想去深入了解滑稽语言隐含的深层含义?
那就访问Jargon File站点吧。该站点收集了庞大的滑稽行语概要,时间跨度相当大。
在这里,你会同时发现像早期的"Bit Bucket"和"404",
同时还有现在时新的有关Hacker Writing Style和Lamer-speak的文章。
该站点由Eric Raymond编辑整理而成。

(三)相关新闻

(1) Slashdot.org

网址:http://slashdot.org

评介:这个自称为"为大众服务的新闻"站点早先是以"晶片和程式"起家的。
後来慢慢发展成为搞笑闲谈的场所。
成千上万的铁杆支持者和匿名用户通过该站点搜寻大量的技术故事和未过滤的社区回信。
当CmdrTaco和Hemos的语法成为时兴後,
他们关於这个搞笑网站尝试後的成功地位自然也无人可比了。

(2) Linux Today

网址:http://www.Linuxtoday.com

评介:Linux Today网站遵从的是Rolling Stone Magazine杂志的座右铭
"All the News that Fits"。
并且作为一个网站,它的确作得相当不错。
对於想直接访问大多Linux业界主要大事的用户来说,
由於该站点提供了新闻故事、出版发行等相关资讯,所以确实是一个不错的切入点。

(3) Linux Weekly News

网址:http://www.lwn.net

评介:如果你想查找所有简明扼要的新闻,那就不应该错过Linux Weekly News站点。
它的范围非常广泛,远至安全事件,近至社会问题。
而且每周星期四,该站点都非常有规律地提供一个关於所有业界所发生事件的编辑评注,
仔细流览,你会发现它的评注非常合情合理。

(4) Wired News

网址:http://www.wired.com

评介:尽管,每周Wired News站点只有几组专门的Linux新闻故事,
但这些新闻故事中却总有技术爱好者所关心的资讯。
而且在当今充盈著"链结到—-网站"的情况下,
该站点还做了其他此类网站没有时间去真正做的事—-自己亲自动手写稿件。

(5) Wide Open News

网址:http://www.wideopen.com

评介:该站点的新闻区经常包含一些相当有意义的专题特写和文章,
而且一般都由专业记者撰写。
Wide Open News站点每周都会发布一些原创作品,而且通常稿件质量都很高。
喜欢流览行业新闻的不妨去感受一番。

(四)通用硬体

(1) Linux Hardware

网址: http://www.linuxhardware.net/

评介:Linux Hardware站点中包括一个内容非常广泛的Linux系统中所有的硬体资讯资料库。
用户既可以流览这些资料库资料,
也可以使用该站点的搜索引擎来快速查找所需要的硬体资料。
同样,该站点也允许搜索Usenet 组。
其中Linux Friendly Hardware Vendor 列表也是另一个特点所在。

(2) Linux Hardware Database

网址:http://lhd.datapower.com

评介:尽管每天Linux下的硬体支援变得越来越少,
但不可否认仍然有那么几款硬体非常适合於Linux用户。
Linux Hardware Database站点就是一个可以找到此类适合Linux的控制项类别的不错站点。

(3) The Linux Benchmarking Project

网址:http://www.tux.org/bench

评介:差不多每一个电脑爱好者都喜欢基准,
特别是当他们的硬体产品处於顶级时更是如此。
The Linux Benchmarking Project站点提供了一个基准结果资料库,
以及可供下载的基准软体。

(4) Tom’s Hardware Guide

网址:http://www.tomshardware.com

评介:该站点虽然并不是一个专门的Linux站点,
但是有关Linux的内容非常不错,很值得一看。
用户不但在这里可以找到评论、新闻、技巧,还可以查找图形资讯、微处理器硬体等等。

(5) Linux on Laptops

网址:http://www.cs.utexas.edu/users/kharker/linux-laptop/

评介:如果你还在顽强地想将Linux装进你的笔记本电脑,
那这个站点绝对是最适合不过了。
从德克萨斯学院毕业的Kenneth Harker用了五年的时间
来对相关笔记本电脑的站点进行精选和分类。
同时,还让真正的用户推荐如何可以在他们的笔记本电脑中装入和运行Linux系统。

(五)专用硬体

(1) LinuxPPC.org

网址:http://www.linuxppc.org/

评介:如果你正在犹豫,不能判断壁橱里的老式Macintosh能不能支援Linux系统,
那LinuxPPC.org站点就是个值得一去的地方。
它是通往Linux/PPC方案的家园,能够将Linux埠置於Mac,
而且还可以链结到Linux/Macintosh邮件列表、常用问题解答、软体等等。

(2) iMac Linux

网址:http://www.imaclinux.net

评介:如果你难以忍受玻璃鱼缸样式、果冻般颜色的iMac,
而现在想运行Linux,不知行不行?
可以肯定地说,没问题,iMac Linux 网站可以帮助你在短短几分钟内完成你的心愿。

(3) Printer Compatibility Database

网址:http://www.picante.com/~gtaylor/pht/printer_list.cgi

评介:在Linux下执行列印任务可能有些烦人,
以至於想购买一个新的印表机来同Linux配套。
Printer Compatibility Database网站可以给用户提供一个
在Linux下工作的印表机综合列表,包括如何同Linux配套使用的综合资讯。
同时,用户可以在该网站找到Linux Printing HOWTO和其他有用的列印资讯。

(4) Linux Modem Compatibility Knowledge Base

网址:http://www.o2.net/~gromitkc/winmodem.html

评介:该站点提供了一个范围广泛的用户级数据机列表(包括Linux下)
以及一些有帮助价值的Linux数据机链结。

(5) SANE

网址:http://www.mostang.com/sane/

评介:如果你不知道如何在Linux下使用扫描器,
那SANE (Scanner Access Now Easy)站点就可以告诉你该怎么办了。
况且,该站点不仅有最流行的Linux扫描器软体,而且还以相容硬体的资料库而颇具特色。

(六) 新手站点

(1) Penguin Magazine

网址:http://www.penguinmagazine.com/

评介:事实上,找一个能给Linux入门者提供各种所需的网站并不是很多,
因此,相比之下,这个後起之秀Penguin Magazine站点的确还算是能解决这个难题。
该站点在今年初才启动,由一个名叫Scott Haven的Linux爱好者个人制作完成,
网站中包含了大量的有关Windows和Linux档系统的逐步式内容介绍。
在厌倦了阅读大多网站中专业化程度超过自己知识容量的资料之後,
Penguin Magazine可以让你轻轻松松地喘口气了。

(2) LinuxPlanet.com

网址:http://www.linuxplanet.com/

评介:由於制作优秀而被Big Company所认可的Linux站点之一就是LinuxPlanet,
自从去年推出核心Linux内容之後,该站点就被网际网路上的人们所看好。
难度适中的论坛、评论、以及一些列印、查找文档等现实问题的疑难指点等。
对於Linux菜鸟级的用户,LinuxPlanet绝对是一个有用的站点。

(3) Beginners Linux Guide

网址:http://www.linux.ie/beginners-linux-guide

评介:Beginners Linux Guide是Irish Linux User Group Web站点的一部分。
它的可圈可点之处在於其中通俗易懂的指南性专题,
包括如何使用基本Linux命令、以及安装资讯等等。

(4) Linuxdot.org

网址:http://www.linuxdot.org/

评介:从这个站点完全可以证明,Linux并不只是美国佬的专利。
因为Linuxdot.org是英国站点,而且的确是一个适用于初学者的向导性优秀站点。
几乎可以冠以"Linux入门者的手册"美称了。
该站点的特徵是从硬碟分区直到MySOL的简单介绍几乎无所不包,
囊括了所有Linux的相关知识。

(5) Linuxnewbie.org

网址:http://www.Linuxnewbie.org/

评介:Linuxnewbie.org是一个综合性站点,包括新闻标题、论坛、
著名的Newbieized帮助档(Newbieized Help Files)等等。
这种帮助档是为了帮助用户习惯使用Linux,进行部分系统的配置。
此外,用户还可以讨论或者检验该站点书架所推荐的图书。

(七)图形/多媒体

(1) LinuxArtist.org

网址:http://www.linuxartist.org/

评介:LinuxArtist.org是我们目前所见过的Linux系统下最综合全面的图形站点。
不论用户喜欢平面图形还是三维图形,
LinuxArtist.org都能给那些使用Linux来创建名作的艺术家们
提供大量的链结和邮件列表。

(2) The Gimp

网址:http://www.gimp.org/

评介:一旦你提到图像和Linux,那就不得不说说The GIMP Web站点。
该站点特别适合於那些希望在Linux市场里得到最好图形程式的用户。
站点里包含了大量的资源和下载软体,此外还展示了一些GIMP.自己制作的美术作品。

(3) 3D software for Linux

网址:http://www.linux3d.org/

评介:虽然3D software for Linux站点不是网路中最可爱的网站,
但用户可以在这里找到许多有价值的Linux下的3D应用程式,
同时还有支援Linux的3D硬体等。
此外,站点页面中还有许多Linux下的3D相关链结、当前新闻、
Linux下的有关3D图形的事件等等。

(4) GraphicsMuse

网址:http://www.graphics-muse.com/

评介:GraphicsMuse站点是一个资源丰富的Linux下图形资讯网站。
在这个站点上,用户可以找到大量的图形资源、推荐图书、
关於GIMP的原始内容以及其他一些非常好的图形方案。

(5) General Graphics Interface Project

网址:http://www.ggi-project.org/

评介:不知你是否抱怨过,X Window系统可能压根就不适合你?
这些家伙们对於用X设计一点都没有激情,但他们希望有一种更好的工作方式。
现在,他们应该有了一个计画,而且,更重要的是,他们拥有beta代码。

(八)游戏站点
(1)Linux Game Tome

网址:http://happypenguin.org/

评介:从1995年开始,Linux Game Tome就已经成为了一个Linux游戏竞赛的专门场所。
而那时,Linux游戏世界本身也还是一片小天地。
现在,他们以http://happypenguin.org/ 为网址,
频道设置有新闻、游戏场景图片、游戏预告,以及最新游戏的评论等等。
同时,该站点还有一个不错的搜索引擎,可以让用户根据游戏类别、等级、名称,
甚至该游戏添加到网站的日期等分类流览游戏评论。

(2)Linux Games

网址:http://www.linuxgames.com/

评介:网站内容设置有下载、基本知识、论坛以及新闻等。
特别是新闻成为该网站的特色频道。
毫无疑问,Linux Games是一个可以覆盖全球绝大多数Linux游戏新闻的站点。

(3)Linux Quake

网址:http://www.linuxquake.com/

评介:绝对不能错过的站点。是一个非常精彩的《雷神之锤》站点。
包括了Linuxe下《雷神之锤》(Quake)的安装、运行,以及新闻和非常活跃的论坛等。

(4)Linux Game Development Center

网址:http://sunsite.auc.dk/lgdc/

评介:如果你想寻找一个非常精彩、且又能找到Linux游戏开发人员一切所需的场所,
那可以肯定目前这样的站点的确还没有出现。
不过,Linux Game Development Center 的发展目标也基本类似。
现在,该站点设置了精彩新闻、游戏开发指南、针对开发人员的访谈等,
但它还正在开发代码仓库、开发工具列表、以及新工作方案,以求不断发展。

(5)Loki

网址:http://www.lokigames.com/

评介:目前,Loki是一个商业性的Linux游戏公司。
从《文明》到《雷神之锤3》,再到《铁路大亨2》等等,
Loki公司几乎将所有最流行的游戏软体都移植到了Linux平台上。
如果你想看看最近有什么大游戏,那就上去看看吧!

(九)网上杂志

(1)Linux Journal Online

网址:http://www.linuxjournal.com/

评介:Linux Journal是其印刷杂志的电子版,大部分和印刷版特徵相符,
不过也添加了一些新的资料。
此外,电子版的特色频道还体现在职业中心、论坛,以及著名软体列表等等。
怎样说服你的老板使用Linux系统,只要看看该站点的企业部分就可以了。

(2)LinuxWorld

网址:http://www.linuxworld.com/

评介:LinuxWorld是一个发行量很大的周刊,范围涉及到Linux的方方面面,
从软体评论到Linux市场的大幅专题。
对於反微软的业界来说,LinuxWorld可是一个几乎无人不知的驰名站点。

(3)Linux Gazette

网址:http://www.linuxgazette.com/

评介:Linux Gazette是由Linux Journal 出版的电子刊物,
属於Linux Documentation Project的一部分。
自从1995年成立以来,无数的志愿者都在踊跃提交稿件,
以至於该站点现在已经成为一个实力很强的站点之一
(如果翻看他们的档案,就能看到一个非常非常古老的Red Hat图示)。
对於很多高级Linux用户来说,该站点的优势在於提供了很多指南和技巧,
同时用户还可以对未来想了解的专题发送提议。

(4)Salon Magazine: The Free Software Story

网址:http://www.salon.com/tech/special/opensource/

评介:最早在1998年,Salon就开始初涉Linux和开放源代码。
和其他大量再线Linux杂志不同的是,该站点所涉的内容题材非常广泛而且相当有意义。

(5)Linux Focus

网址:http://www.linuxfocus.org/

评介:这个定期按时发送的电子杂志自从1997年就开始诞生了。
它以月刊的形式,给用户提供了许多新颖(多少有些深奥)的技术性文章。
而且以多种语言发行,当然也包括英文版。

(十)链结/入口

(1) Linux.com

网址:http://www.Linux.com

评介:仅仅一年的时间,VA Linux的Linux.com 就已经成长为
网际网路上最具竞争力的Linux站点之一。
在网站经理Trae McCombs和他的自愿者小组努力下,
该网站为Linux社区添加了无数非常有用的特色内容和资源。
近来,该站点和O’Reilly & Associates结成合作关系,
双方合作的结果使Linux.com站点更具有专业化和更高质量。

(2) LinuxStart.com

网址:http://www.LinuxStart.com

评介:想一想Yahoo,基本就能够想像得出Linux的同类站点
——LinuxStart.com站点的特色
也正在於有一个相当不错的分成好多个主题区的精选链结。
此外,如果你正在费劲地用Hotmail发送网路信件,不妨试试Linux-Start的电子信箱。
甚至你还可以将你的网页也一并搬到上面。

(3) LinuxLinks.com

网址:http://www.linuxlinks.com

评介:LinuxLinks.com是最综合性的Linux站点之一,
在这里你能见到许多曾经印象比较深刻的站点链结。
目前,该站点的链结数量超过10,000,而且随时都在增加。

(4) Linux Online

网址:http://www.linux.org

评介:Linux Online的名称甚至比它的功能变数名称Linux.org更为知名。
是一个比较早的Linux站点,虽然介面做得并不是非常漂亮,
但其中包含的Linux资源价值却使其成为了一个必须参观的网站之一。

(5) Linsight

网址:http://Linsight.com

评介:Linsight在宣传中介绍自己为"Linux时代的Linux资讯"。
该网站实际上是由好几个部分组成的,
其中包括命名为LinDeveloper的一个开发人员分区、
一个叫做Linsider的Linux市场跟踪区、
追踪全年所发生的Linux业界焦点事件报导的LinEvents区、
以及可以告诉你和你的员工们在那里得到Linux培训的LinTraining专区。

(十一)软体发展

(1) SourceForge

网址:http://www.SourceForge.net

评介:SourceForge站点是VA Linux针对开发人员的一个入口。
程式师们在这里可以放置他们的开放源代码方案,
包括CVS工具、调试追踪和补丁管理工具。
SourceForge给所有没有资源来自己安装一个伺服器的Linux和
开放源代码程式师们一个家园。
用户可以流览和下栽网站上已开发的软体,也可以给这些方案做补丁。

(2) Catalog of Free Compilers and Interpreters

网址:http://www.idiom.com/free-compilers/

评介:在没有明确限制Linux和开放源代码软体的时候,
免费编译器和解释程式的目录对於开放源代码的开发人员还是会有些兴趣的。
此外,该站点包含了许多编程工具和编译器。

(3) SourceXchange

网址:http://www.sourcexchange.com

评介:SourceXchange是一个可以让Linux和开放源代码软体发展人员得到报酬的站点。
通过链结到一个付费的商业公司,就可以用开放源代码软体赚钱了。
需要开放源代码吗?需要提交方案、标明你的价格——-当然,
成功的前提是他们必须正好有你所需要的代码。

(4) CoSource

网址:http://www.cosource.com

评介:CoSource是又一个专门给源代码开发人员提供的付费站点。
目前,表单上已经有将近250个要求,总量达$71,500。

(5) Linux Source Navigator

网址:http://www.metalab.unc.edu/navigator-bin/navigator.cgi?

评介:该站点将源代码镶进一个简单的导航性分层档夹系统中,
以便用户快速查找到所需要的代码。

(十二)购物

(1) LinuxMall.com

网址:http://www.linuxmall.com

评介:可能由於最近更新过的缘故,LinuxMall.com站点看起来不想是购物站点,
倒像是一个专门的Linux链结入口。
而且,它还远不只是一个普通的电子商务站点。
目前,该站点已经打算建立很多特色社区了,如论坛以及已经启动的新闻服务等。

(2) Thinkgeek

网址:http://thinkgeek.com

评介:该网站有随手可得地最酷Linux附件。
但除了一些$1.99的发行CD外,用户可能在这里不会找到任何软体。
不过,如果你想用""compile"、"telnet"、和"regexp"写点东西,
最好还是上这个站点看看吧!

(3) The Linux Store

网址:http://thelinuxstore.com

评介:该站点比较自豪的是他们易於使用、简洁的介面、非常广泛的产品线,
以及大量的技术支持,没准在这里你还能找到你需要的东西呢。

(4) eLinux.com

网址:http://www.elinux.com

评介:这个进入Linux购物市场的新入口是由Creative Computers公司提供支援的,
该公司同时还有PCMall和MacMall。
Elinux站点中有一个非常广泛的Linux硬体和软体区,
同时还有一个由Linuxcare提供支援的FAQ资料库。

(5) Linuxcentral

网址:http://www.linuxcentral.com

评介:图书、T恤——–用户在这里可以找到所有传统Linux电子商务所能买到的东西,
此外,在这里还有一些更有趣的东西,比如网卡等等。

(十三)Linux内核

(1) Kernel Notes

网址:http://kernelnotes.org

评介:KernelNotes.org是一个可以得到所有内核的地方。
该站点所包括的内容比较广泛,而且,特色是能够找到最新内核的升级技巧。

(2) The Linux Kernel Archives

网址:http://www.kernel.org/

评介:该站点奉行的原则是:简洁、简洁,再简洁。
用户可以选择Linux内核、不稳定内核、稳定内核以及内核源代码。
如果你想找最新的稳定Linux内核或开发中内核,那就去看看吧。

(3) Kernel Traffic

网址:http://kt.linuxcare.com/

评介:难道每周不想要一个几乎达到6MB的Linux开发邮件列表吗?
Kernel Traffic站点的那帮家伙们早就替你想到了这一点。
Kernel Traffic是一个时事通讯周刊,总结了本周主要的专题。
一个不错的站点。

(4) GNU Hurd

网址:http://www.gnu.ai.mit.edu/software/hurd/hurd.html

评介:稳定版目前已经具体化,但关於Hurd kernel 的GNU Project还在发展之中。
Hurd内核是一个微核设计的实练。
GNU/ Hurd站点的特徵就是说明了如何将Hurd安装进Debian distribution中去。

(5) Linux Mama

网址:http://www.LinuxMama.com/

评介:无论如何,也不是每一个内核补丁都得作到fold中,
如果你正好属於好奇心比较重的类型,想玩玩非正式内核补丁,
那就不要错过Linux Mama了。

(十四) 职业机会

(1)Geekfinder

网址:http://www.geekfinder.com/

评介:主机位於User Friendly站点的Geekfinder是一个猎职的好去处。
该站点不只限於Linux类相关工作,
用户可以根据自己的技能搜索和选择最适合自己的工作。
此外,用户还可以根据自己的意愿按照州和地区来搜索职位。

(2)Linux.com Jobs Page

网址:http://www.linux.com/jobs/

评介:想寻找专职Linux工作的人,值得来Linux.com’s Jobs page站点看看。
根据提交的职位,该站点有大量适用於Linux求职者的有用专题和链结。

(3)eLance

网址:http://www.elance.com

评介:正式发布於去年的eLance站点为包括电脑业求职的各类自由服务开辟了一个新市场。
用户可以在该站点填写个人资料表格,并在其"固定薪酬"
部分根据填写者自己要求的计时薪酬
(在这里你也可以以每小时3到300美圆的价格雇佣其他人),
或者你也可以流览网站上的各种资讯看看是否有适合你的自由工作。

(4)Linux Today Jobs

网址:http://jobs.linuxtoday.com/

评介:该站点有两个特徵:网路上综合性最强的Linux新闻站点之一;
能够同时提供Linux企业公司招聘和Linux个人求职的专业站点。

(5)Hotjobs.com

网址:http://www.hotjobs.com

评介:Hotjobs.com是一个不局限於Linux特定求职的网站,
该站点每天发布5到10个Linux相关职位,
而且所公布的职位资料绝对不是那些看起来充裕却几乎没有什么回映的过时消息。

(十五)科学工程

(1) SAL: Scientific Applications for Linux

网址:http://www.kachinatech.com/SAL/

评介:Linux现在不仅仅是供玩乐的东西了,但这并不是意味著就此失去了许多乐趣。
对於年轻的科学工作者们来说,
可以在该网站找到许多适用於Linux下各种科研应用程式的开放源代码、
共用软体和商业软体等等。

(2) Beowulf Project at CESDIS

网址:http://beowulf.gsfc.nasa.gov/

评介:一个很酷的Linux站点。以帮助科学家们联系大量质优价廉的电脑而出名。

(3) High-Availability Linux Project

网址:http://www.henge.com/~alanr/ha/

评介:如果你正在Linux下运行企业级的应用程式,
或者只想验证一下Quake伺服器从不会崩溃,那该站点就太适合你了。
同时该站点还提供了许多簇管理、Linux-HA软体以及大量地此类相关站点链结。

(4) Free Physics Project

网址:http://freephysics.sourceforge.net/

评介:是一个创建Linux下的GPL物理模拟器的站点。
用户可以下载运行代码、专案处理等等。

(5) Linux and Chemistry

网址:http://chpc06.ch.unito.it/chem_linux.html

评介:这是一个综合了Linux和化学的网站,其中有许多商业、共用软体和GPL的软体,
适合於那些在Linux下做研究工作的化学家。想必化学系的学生和教授应当喜欢这个站点。

(十六)文档管理

1)Linux Documentation Project

网址:http://www.linuxdoc.org/

评介:在所有Linux站点中,LDP已经作了相当久的FAQ、HOWTO以及Linux导引了。
该站点最为夸耀的是各种格式的Linux详细资讯集萃。
此外,此站点中的HOWTO分项也是一个能解答用户所有疑难问题的权威场所。
最近由於新鲜血液的加盟,该站点又有了新特色。

2)Open Source Writer’s Group

网址:http://www.oswg.org:8080/oswg

评介:该站点是由LinuxChix的Deb Richardson在去年制作完成的,
为一个开放源代码的集萃站点,特别适合於开放源代码项目的用户。

3)Linux Resources

网址:http://www2.linuxjournal.com/cgi-bi….pl/lr-toc.html

评介:该站点是一个优秀的资料站点,同时适用于Linux新手和专业人士。
在这里,用户可以找到所有相关Linux的资料,而且它还告诉你,
在哪里可以找到相关资料、可以和使用这些资料的人见面,以及其他更多。

4)GNU Project Documentation

网址:http://www.gnu.org/doc/doc.html

评介:如果你手里有一个很好的免费软体却不知如何使用,怎么办?
幸运的是,GNU Project Documentation站点的管理人员已经
为你提供了一个非常综合的文档区。
此外,如果你心情不错,
那么还可以去读读Free Software and Free Manuals上刊登的Richard Stallman的评论。

5)The Vim Homepage

网址:http://www.vim.org/

评介:一个绝对让新手震动的Linux网站。这里有大量的Vim资讯和使用资料。

(十七)X-Window 系统

1)Themes.org

网址:http://www.themes.org

评介:这里有装扮你桌面的所有好东西,
同时还有在window 管理器和其他流行套装软体上更新的X资源和新闻。
此外,Themes.org还有SawMill、Afterstep、 Enlightenment、
WindowMaker、KDE专区等等。

2)KDE Home

网址:http://www.kde.org

评介:该站点能提供给你适用於K Desktop Environment的任何开发资料,
而且还有随时更新的适用於KDE的最新发行软体。
此外,KDE还有许多像K Office之类的相关资料。

3)GNOME Home

网址:http://www.GNOME.org

评介:Gnome.org是一个组织最好的免费软体站点。
在这里,用户可以得到有关GNOME的开发资源,可以加入GNOME邮件列表,
还可以进行软体下载。
开发人员将搜索到最新的附加资料,GNOME用户们还将找到大量有用的文档。

4)XFree86 Project

网址:http://www.xfree86.org

评介:XFree86 Project站点将给用户Linux系统的相关资料、最新发行的软体、
以及一个精彩的FAQ等等。
XFree86站点对於刚入门的Linux新手来说将是一个不可错过的站点。

5)Window Managers for X

网址:http://www.PLiG.org/xwinman

评介:Window Managers for X站点是有关X视窗管理器的最综合性站点。
从最早的一直到最新的乃至全部,以及最大的视窗管理器都可以在该站点找到。
还不知道一个视窗管理器和一个桌面环境的区别吗?该站点也可以回答你这些基本问题。

(十八)Linux 分布站点

1)Debian

网址:http://www.debian.org

评介:Debian网站用户介面非常友好,
并且关於Debian GNU/Linux和Linux一般使用方面内容丰富。
如果你喜欢冒险,
你甚至可以在这里找到如何使用GNU/Hurd内核运行Debian而不是我们都知道
和喜爱的Linux内核。而且还有很多各种各样免费资源的链结供用户使用!

2)Red Hat

网址:http://www.RedHat.com

评介:Red Hat的网站在过去的一年里已经多次发生变化。
但是RedHat.com只是保持做更好的改变。
最新的介面容易流览,并且还为用户提供了大量的链结和下载。

3)SuSE

网址:http://www.SuSE.com

评介:SuSE网站是一个商业站点──没有打算成为"门户"站点或其他。
所以该网站只是仅仅包含了你想了解的SuSE Linux的一切相关资讯。
SuSE的网站对於想知道Linux是否能和他们的硬体相容的用户则是非常有用。

4)Slackware

网址:http://www.Slackware.com

评介:该站点让用户唯一不满的就是太多的图片和太慢的下载速度。
相对而言,Slackware站点是一个漂亮、整洁、黑白形象设计,
而且还对所有重要的材料建了链结。

5)Linux-Mandrake

网址:http://www.Linux-Mandrake.com

评介:Linux-Mandrake站点对於Linux-Mandrake distro的用户来说
确实是一个优秀的网站。
无论你是一个需要寻找技术支援的菜鸟,还是一个想同最新的代码打交道的开发者,
Linux-Mandrake都是实现这一切的捷径。

(十九)用户团体

1)Linux User Groups WorldWide

网址:http://lugww.counter.li.org/lugww.php3

评介:想要寻找离你最近或最远的Liunx用户组吗?
Linux User Groups WorldWide网站有最全面的相关LUGs(Linux用户组)列表。
基於用户地址定位的列表允许相互间建立联系,而且该站点还给出如何创建指南。

2)SVLUG

网址:http://www.sulug.org

评介:该网站很可能是世界上最有活力的LUG站点,
而且一定是人们常频繁光顾的热点地带。
Silicon Valley Linux Users Group站点包含了许多相当有趣的历史和有用链结。

3)Groups of Linux Users Everywhere

网址:http://www2.linuxjournal.com/glue/index.html

评介:GLUE是Linux Journal的主办者。
注册过的LUGs可以参加世界各地的友好Linux公司所提供的活动。
同时,GLUE网站中也有一定数量的LUGs资源,包括技巧等等。

4)Linux Online’s Linux User Group Registry

网址:http://www.linux.org/users/index.html

评介:Linux Online有一个很全面的世界性LUGs列表。
如果你想在此找点你的LUG,请在Linux Online site上列出来。

5)LinuxChix

网址:http://www.linuxchix.org

评介:没错,Chix的确是在钻研Linux。
创立LinuxChix的Deb Richardson想打算制作一个能让女性使用的Linux邮件列表。
LinuxChix发展的很快,简直比Deb期望的还要流行。
而且地区化的LinuxChix LUGs 也已经开始走向全球。

2006年04月06日

开源在今天的软件业已经很普遍,但开源是否意味着使用者可以对开源后的代码为所欲为呢?答案是否定的。开源运动同样有自己的游戏规则和道德准则。不遵行这些规则不但损害开源运动的健康发展,也会对违规者造成名誉和市场上的损失,更可能陷入法律纠纷和赔偿。

现今存在的开源协议很多,而经过Open Source Initiative组织通过批准的开源协议目前有58种。我们在常见的开源协议如BSD, GPL, LGPL,MIT等都是OSI批准的协议。如果要开源自己的代码,最好也是选择这些被批准的开源协议。

这里我们来看四种最常用的开源协议及它们的适用范围,供那些准备开源或者使用开源产品的开发人员/厂家参考。

BSD开源协议

BSD开源协议是一个给于使用者很大自由的协议。基本上使用者可以”为所欲为”,可以自由的使用,修改源代码,也可以将修改后的代码作为开源或者专有软件再发布。

但“为所欲为”的前提当你发布使用了BSD协议的代码,或则以BSD协议代码为基础做二次开发自己的产品时,需要满足三个条件:

1. 如果再发布的产品中包含源代码,则在源代码中必须带有原来代码中的BSD协议。

2. 如果再发布的只是二进制类库/软件,则需要在类库/软件的文档和版权声明中包含原来代码中的BSD协议。

3. 不可以用开源代码的作者/机构名字和原来产品的名字做市场推广。

BSD代码鼓励代码共享,但需要尊重代码作者的著作权。BSD由于允许使用者修改和重新发布代码,也允许使用或在BSD代码上开发商业软件发布和销售,因此是对商业集成很友好的协议。而很多的公司企业在选用开源产品的时候都首选BSD协议,因为可以完全控制这些第三方的代码,在必要的时候可以修改或者二次开发。

Apache Licence 2.0

Apache Licence是著名的非盈利开源组织Apache采用的协议。该协议和BSD类似,同样鼓励代码共享和尊重原作者的著作权,同样允许代码修改,再发布(作为开源或商业软件)。需要满足的条件也和BSD类似:

1. 需要给代码的用户一份Apache Licence

2. 如果你修改了代码,需要再被修改的文件中说明。

3. 在延伸的代码中(修改和有源代码衍生的代码中)需要带有原来代码中的协议,商标,专利声明和其他原来作者规定需要包含的说明。

4. 如果再发布的产品中包含一个Notice文件,则在Notice文件中需要带有Apache Licence。你可以在Notice中增加自己的许可,但不可以表现为对Apache Licence构成更改。

Apache Licence也是对商业应用友好的许可。使用者也可以在需要的时候修改代码来满足需要并作为开源或商业产品发布/销售。

GPL

我们很熟悉的Linux就是采用了GPLGPL协议和BSD, Apache Licence等鼓励代码重用的许可很不一样。GPL的出发点是代码的开源/免费使用和引用/修改/衍生代码的开源/免费使用,但不允许修改后和衍生的代码做为闭源的商业软件发布和销售。这也就是为什么我们能用免费的各种linux,包括商业公司的linuxlinux上各种各样的由个人,组织,以及商业软件公司开发的免费软件了。

GPL协议的主要内容是只要在一个软件中使用(“使用”指类库引用,修改后的代码或者衍生代码)GPL协议的产品,则该软件产品必须也采用GPL 协议,既必须也是开源和免费。这就是所谓的”传染性”。GPL协议的产品作为一个单独的产品使用没有任何问题,还可以享受免费的优势。

由于GPL严格要求使用了GPL类库的软件产品必须使用GPL协议,对于使用GPL协议的开源代码,商业软件或者对代码有保密要求的部门就不适合集成/采用作为类库和二次开发的基础。

其它细节如再发布的时候需要伴随GPL协议等和BSD/Apache等类似。

LGPL

LGPLGPL的一个为主要为类库使用设计的开源协议。和GPL要求任何使用/修改/衍生之GPL类库的的软件必须采用GPL协议不同。 LGPL允许商业软件通过类库引用(link)方式使用LGPL类库而不需要开源商业软件的代码。这使得采用LGPL协议的开源代码可以被商业软件作为类库引用并发布和销售。

但是如果修改LGPL协议的代码或者衍生,则所有修改的代码,涉及修改部分的额外代码和衍生的代码都必须采用LGPL协议。因此LGPL协议的开源代码很适合作为第三方类库被商业软件引用,但不适合希望以LGPL协议代码为基础,通过修改和衍生的方式做二次开发的商业软件采用。

GPL/LGPL都保障原作者的知识产权,避免有人利用开源代码复制并开发类似的产品。

P.S. 随手写写,是因为跟客户交谈的时候发现很多人其实对开源有完全错误的理解,特别是开源协议。很多人认为只要是开源,就意味着随便用,随便改都可以。

dlee补充:

这些知识 Linux Fans 大多比较清楚,因为经常使用开源软件,每天下载源代码,编译、测试、安装是常事。这些问题在各个 Linux 论坛上也早已经是老生常谈,但是有些 Java Fans 以及大多数 M$ 平台的开发人员几乎一无所知。我在这里一般不会谈跟 Java 关系不大的内容。既然 Charlesxp 想谈谈,我也补充一下。

首先,软件有两种分类方法:

商业软件 vs. 免费软件

商业软件:软件是要卖钱的。

免费软件:软件不卖钱,出于兴趣开发,可以随便使用。

开源软件 vs. 私有软件

开源软件:软件的源代码是公开的,可以在遵守某种 license 的条件下加以修改。

私有软件:软件的源代码不公开,用户仅仅只能得到软件的二进制版本。

  从上面的两种区别我们可以看出,开源软件和商业软件不是对等或对立的关系,开源软件同样也可以卖钱。但是给了你源代码,你如果没有一定的功力也未必能看懂。而且用户常常不具备相应的能力(没有从事过软件开发),仅仅想要使用软件的功能。既然这样,开源对于这类用户还有何意义呢?开源可以保护这类用户免于陷入厂商设置的锁定陷阱。因为提供了全部源代码,只要用户能找到有能力维护这些代码的人或公司,他就可以持续发展这些代码的功能。这个人或公司不一定是最初卖软件给他的那一家。用户不会在大部分功能用的好好的,某个关键功能无法使用的时候,买家告诉他,你希望获得的这个功能在我们的下一版本中有,但是你必须支付我们 10w$ 升级费我们才可以提供。这个就叫做厂商锁定。如果软件不是开源的,用户没有办法做出选择,上了贼船后想下来可就难了。所以开源的商业软件对于保护用户自己的利益是非常重要的。用户可以获得真正的安全,而且更体现了软件的本质就是一种高级的服务。

  那么有人会担心,这样做究竟能不能赚到钱?你能不能赚到钱要看市场和需求有多大。只盯着厂商锁定一种方式来赚钱其实是一种短视的行为。现在国内大部分软件开发商都不重视维护和服务,仅仅靠卖软件本身的 copy license 来赚钱,用户感觉不到自己是上帝,怨声载道。其实用户所需要的还是长期的维护和服务。所以这样的软件如果真能把服务做好,用户是会非常欢迎的。既然经过分析预计会有很大的需求,从长期看,我相信肯定是可以赚到钱的。

  还有一类软件:共享软件。这类软件不是开源的,但是有免费的版本可以使用。如果你用的很爽,良心发现了,可以把钱汇给作者。如果希望作者提供服务,也可以找他谈。国内很有名的 FoxMail 就是这类软件。但是对于用户最有价值的一类软件,其实还是开源的商业软件。

  开源软件卖的是长期的服务,不是软件本身的 copy。不是所有的软件都有可能卖服务,也不是所有的用户都需要服务(这个问题我们以后可以讨论)。但是一个大型企业或者重要的政府机关,假设使用了 JBoss+MySQL 这种组合,长期的服务是非常必要的(至少出了事情可以找到一个替罪羊)。你问这个问题就说明你没有多少企业应用的经验,不知道 IBM 这些公司的商业模式就是建立在 IT 服务的基础之上的。开源软件提供了一个新的组合,对于更好地做好这种服务非常有帮助。实际上,IBM 的解决方案中就包括了大量开源的成果。HP 做的方案也有采用 JBoss 的,为了得到长期的服务,HP JBoss 专门签订了长期合作的协议。

    中国国内由于市场容量的限制,以及用户缺乏信息化的经验,对于软件长期服务的重要性认识不足,因此总是只看到软件本身的售价,给了一些夫妻店竞相压价钻空子的机会。但是必须承认,这并不是一种良性竞争的状态。最终还是要走到切实为用户做好服务的道路上来的。服务是值钱的,不是免费的。你去路边的理发馆随便理个发,5 块钱,出来以后仍然蓬头垢面。你去高级发廊做头,500 块,但是你得到了按摩等各种服务(不要联想引申),身心得到了放松,出来以后精神焕发。你只盯着路边的理发馆,但是仍然有别人愿意去高级的发廊。

  当然,真正要做好服务,对于技术等各方面的能力要求是非常高的。这种要求不是随便哪个夫妻店就能够达到的。

robbin补充:

  Richard StallmanGNU创始人和GPL的创造者,Stallman开发的比较著名的GPL软件包括GNU GCCGNU Emacs。其中EmacsStallman独立开发的早期也是卖钱的。Stallman定的Emacs售价为每份150美元。

  因此请记住: 开源软件不等于免费软件。

2006年03月19日

收自 : http://www.jy361.com/Article/xtxuexi/linux/200509/4557.shtml
和UNIX系统相同,Linux超级用户root拥有系统的最高权限。当由于用户的疏忽,遗忘了root 密码,或者系统受到黑客的入侵,无法用root 账号登录系统时,我们可以通过下列办法来恢复root 的密码。
  一、进入单用户模式
  1.使用Linux 系统启动软盘
  如果你已创建了Linux 系统的启动软盘,而且设置计算机系统从软盘启动,当显示boot 提示符后输入:
  boot: linux single
  系统进入了提示符为“#”的单用户模式,计算机引导的运行级别为1,本地文件系统被挂载,很多系统服务没有运行,跳过所有系统认证,是一个系统管理员使用特定的机器,把 root 文件系统挂为读写,此时你可以使用:
  (1)passwd 程序来设置root的新密码
  # passwd root
  # reboot
  重启系统后,root 密码已被更新。
  (2)通过修改 /etc/shadow 文件,删除root 的密码
  # cd /etc
  # vi shadow
  将以root 开头的一行中“root:”后和下一个“ :”前的内容删除,
  第一行将类似于“root ::??”,保存后重启系统,root 密码置为空。
  2.以LILO 多系统引导程序启动
  当系统以LILO 引导程序启动时,在出现LILO 提示符时输入:
  LILO: linux single
  进入单用户后,更改password 的方法同1。
  3.以GRUB 多系统引导程序启动
  用GRUB引导系统进入单用户步骤:
  (1) 启动GRUB,选择Red Hat Linux的选项,然后键入 e 来编辑;
  (2) 选择以kernel开头的一行,再按e 键,在此行的末尾,按空格键后输入single,以回车键来退出编辑模式;
  (3) 回到了 GRUB 屏幕后,键入 b 来引导进入单用户模式。
  进入单用户后,更改password 的方法同1。
  二、使用Linux 系统安装盘
  如果你既没做系统启动软盘,同时多系统的引导LILO 和GRUB 又被删除(如重装了Windows 系统后),那么只能使用Linux 系统安装盘来恢复root 的密码。
  用第一张Linux 系统安装盘启动,出现boot 提示符后输入:
 oot: linux rescue
  此时系统进入救援模式,然后根据提示完成:
  1.选择语言和键盘格式;
  2.选择是否配置网卡,一般系统因网络不需要,所以可以选择否跳过网卡配置;
  3 . 选择是否让系统查找硬盘上的Redhat Linux 系统,选择继续;
  4.系统显示硬盘上的系统已经被找到,并挂载在/mnt/sysimage 下;
  5.进入拯救状态,可重新设置root 的密码:
  # chroot/mnt/sysimage (让系统成为根环境)
  # cd /mnt/sysimage
  # passwd root

2006年03月16日

小飞驴的网站 http://www.flyingdonkey.com/  马维达 C++网络编程 卷二 译者

http://www.flyingdonkey.com/cgi-bin/LB5000MX/leoboard.cgi

WeiZone 我们的社区 http://www.weizone.com/forumdisplay.php?fid=22&page=1 ACE网络通讯编程版

LoveUnix技术论坛 http://www.loveunix.com/viewthread.php?tid=29276

hxh(贺星河)的专栏  http://blog.csdn.net/hxhbluestar/category/25379.aspx  ACE网络编程

ACE自适配通信环境讨论 http://www.huihoo.org/chat/ace_20030702.html


[ACE技术论文集]一.ACE自适配通信环境:用于开发通信软件的面向对象网络编程工具包
ACE程序入口函数替换机制分析
[ACE技术论文集]二 包装外观(Wrapper Facade):用于在类中封装函数的结构型模式
精华帖标志
[ACE技术论文集]三 IPC SAP:用于高效、可移植和灵活的网络编程的C++包装
[ACE技术论文集]四 ACE轻量级OS并发机制的OO封装 
[ACE技术论文集]五 C/C++线程专有存储:用于访问“per-Thread”状态的对象行为模式 

ACE的类结构图[pdf文档]

ACE自适配通信环境

Douglas C. Schmidt


一、ACE综述

  ACE自适配通信环境(ADAPTIVE Communication Environment)是可以自由使用、开放源码的面向对象(OO)框架(Framework),在其中实现了许多用于并发通信软件的核心模式。ACE提供了一组丰富的可复用C++ Wrapper Facade(包装外观)和框架组件,可跨越多种平台完成通用的通信软件任务,其中包括:事件多路分离和事件处理器分派、信号处理、服务初始化、进程间通信、共享内存管理、消息路由、分布式服务动态(重)配置、并发执行和同步,等等。

ACE的目标用户是高性能和实时通信服务和应用的开发者。它简化了使用进程间通信、事件多路分离、显式动态链接和并发的OO网络应用和服务的开发。此外,通过服务在运行时与应用的动态链接,ACE还使系统的配置和重配置得以自动化。

ACE正在进行持续的改进。Riverace公司(http://www.riverace.com)采用开放源码商业模式对ACE进行商业支持。此外,ACE开发组的许多成员目前正在进行The ACE ORB(TAO,http://www.cs.wustl.edu/~schmidt/TAO.html)的开发工作。

二、使用ACE的好处

使用ACE的好处有:

l       增强可移植性:在ACE组件的帮助下,很容易在一种OS平台上编写并发网络应用,然后快速地将它们移植到各种其他的OS平台上。而且,因为ACE是开放源码的自由软件,你无需担心被锁定在特定的操作系统平台或编译器上。

l       更好的软件质量:ACE的设计使用了许多可提高软件质量的关键模式,这些质量因素包括通信软件灵活性、可扩展性、可复用性和模块性。

l       更高的效率和可预测性:ACE经仔细设计,支持广泛的应用服务质量(QoS)需求,包括延迟敏感应用的低响应等待时间、高带宽应用的高性能,以及实时应用的可预测性。

l       更容易转换到标准的高级中间件:TAO使用了ACE提供的可复用组件和模式。它是CORBA的开发源码、遵循标准的实现,并为高性能和实时系统作了优化。为此,ACE和TAO被设计为能良好地协同工作,以提供全面的中间件解决方案。

三、ACE的结构和功能

下图显示了ACE中的关键组件以及它们的层次关系:



图中的结构和各层的组成部分描述如下。

四、ACE OS适配层

该层直接位于用C写成的本地OS API之上。它提供轻型的类POSIX OS适配层,将ACE中的其他层及组件和以下与OS API相关联的平台专有特性屏蔽开来:

l       并发和同步:ACE的适配层封装了用于多线程、多进程和同步的OS API。

l       进程间通信(IPC)和共享内存:ACE的适配层封装了用于本地和远地IPC、以及共享内存的OS API。

l       事件多路分离机制:ACE的适配层封装了用于对基于I/O、定时器、信号和同步的事件进行同步和异步多路分离的OS API。

l       显式动态链接:ACE的适配层封装了用于显式动态链接的OS API。显式动态链接允许在安装时或运行时对应用服务进行配置。

l       文件系统机制:ACE的适配层封装了用于操作文件和目录的OS文件系统API。

ACE OS适配层的可移植性使得ACE可运行在许多操作系统上。ACE已在广泛的OS平台上进行了移植和测试,包括Win32(也就是,在Intel和Alpha平台,使用MSVC++、Borland C++ Builder和IBM Visual Age的WinNT 3.5.x、4.x、2000、Win95/98和WinCE)、Mac OS X、大多数版本的UNIX(例如,SPARC和Intel上的Solaris 1.x和2.x、SGI IRIX 5.x和6.x、DG/UX、HP-UX 9.x、10.x和11.x、DEC/Compaq UNIX 3.x和4.x、AIX 3.x和4.x、UnixWare、SCO,以及可自由使用的UNIX实现,比如Debian Linux 2.x、RedHat Linux 5.2、6.x和7.x、FreeBSD和NetBSD)、实时操作系统(比如,LynxOS、VxWorks、Chorus ClassiX 4.0、QnX Neutrino、RTEMS和PSoS)、MVS OpenEdition和CRAY UNICOS。

由于ACE的OS适配层所提供的抽象,所有这些平台使用同一棵代码树。这样的设计极大地增强了ACE的可移植性和可维护性。此外,还有Java版本的ACE可用(http://www.cs.wustl.edu/~eea1/JACE.html)。

五、OS接口的C++ Wrapper Facade

可以直接在ACE OS适配层之上编写高度可移植的C++应用。但是,大多数ACE开发者使用的是上图中所示的C++ Wrapper Facade层。通过提供类型安全的C++接口(这些接口封装并增强本地的OS并发、通信、内存管理、事件多路分离、动态链接和文件系统API),ACE Wrapper Facade简化了应用的开发。应用可以通过有选择地继承、聚合和/或实例化下面的组件来组合和使用这些包装:

l       并发和同步组件:ACE对像互斥体和信号量这样的本地OS多线程和多进程机制进行抽象,以创建高级的OO并发抽象,像主动对象(Active Object)和多态期货(Polymorphic Future)。

l       IPC和文件系统组件:ACE C++包装对本地和/或远地IPC机制进行封装,比如socket、TLI、UNIX FIFO和STREAM管道,以及Win32命名管道。此外,ACE C++包装还封装了OS文件系统API。

l       内存管理组件:ACE内存管理组件为管理进程间共享内存和进程内堆内存的动态分配和释放提供了灵活和可扩展的抽象。

ACE C++包装提供了许多与ACE OS适配层一样的特性。但是,这些特性是采用C++类和对象、而不是独立的C函数来构造的。这样的OO包装有助于减少正确地学习和使用ACE所需的努力。

例如,C++的使用提高了应用的健壮性,因为C++包装是强类型的。所以,编译器可在编译时、而不是运行时检测类型系统违例。相反,不到运行时,不可能检测像socket或文件系统I/O这样的C一级OS API的类型系统违例。

ACE采用了许多技术来降低或消除额外的性能开销。例如,ACE大量地使用C++内联来消除额外的方法调用开销;这样的开销可由OS适配层和C++包装所提供的额外的类型安全和抽象层次带来。此外,对于性能要求很高的包装,比如socket和文件I/O的send/recv方法,ACE会避免使用虚函数。

六、框架

ACE还含有一个高级的网络编程框架,集成并增强了较低层次的C++ Wrapper Facade。该框架支持将并发分布式服务动态配置进应用。ACE的框架部分包含以下组件:

l       事件多路分离组件:ACE Reactor(反应器)和Proactor(前摄器)是可扩展的面向对象多路分离器,它们分派应用特有的处理器,以响应多种类型的基于I/O、定时器、信号和同步的事件。

l       服务初始化组件:ACE Acceptor(接受器)和Connector(连接器)组件分别使主动和被动的初始化任务与初始化一旦完成后通信服务所执行的应用特有的任务去耦合。

l       服务配置组件:ACE Service Configurator(服务配置器)支持应用的配置,这些应用的服务可在安装时和/或运行时动态装配。

l       分层的流组件:ACE Stream组件简化了像用户级协议栈这样的由分层服务组成的通信软件应用的开发。

l       ORB适配器组件:通过ORB适配器,ACE可以与单线程和多线程CORBA实现进行无缝集成。

ACE框架组件便利了通信软件的开发,它们无需修改、重编译、重链接,或频繁地重启运行中的应用,就可被更新和扩展。在ACE中,这样的灵活性是通过结合以下要素来获得的:(1)C++语言特性,比如模板、继承和动态绑定,(2)设计模式,比如抽象工厂、策略和服务配置器,以及(3)OS机制,比如显式动态链接和多线程。

七、分布式服务和组件

除了OS适配层、C++ Wrapper Facade和框架组件,ACE还提供了包装成自包含组件的标准分布式服务库。尽管这些服务组件并不是ACE框架库的严格组成部分,它们在ACE中扮演了两种角色:

1.       分解出可复用分布式应用的“积木”:这些服务组件提供通用的分布式应用任务的可复用实现,比如名字服务、事件路由、日志、时间同步和网络锁定。

2.       演示ACE组件的常见用例:这些分布式服务还演示了怎样用像Reactor、Service Configurator、Acceptor和Connector、Active Object,以及IPC包装这样的ACE组件来有效地开发灵活、高效和可靠的通信软件。

八、高级分布式计算中间件组件

即使使用像ACE这样的通信框架,开发健壮、可扩展和高效的通信应用仍富有挑战性。特别是,开发者必须掌握许多复杂的OS和通信的概念,比如:

l       网络寻址和服务标识。

l       表示转换,比如加密、压缩和在异种终端系统间的字节序转换。

l       进程和线程的创建和同步。

l       本地和远地进程间通信(IPC)机制的系统调用和库例程。

通过采用像CORBA、DCOM或Java RMI这样的高级分布式计算中间件,可以降低开发通信应用的复杂性。高级分布式计算中间件驻留在客户端和服务器之间,可自动完成分布式应用开发的许多麻烦而易错的方面,包括:

l       认证、授权和数据安全。

l       服务定位和绑定。

l       服务注册和启用。

l       事件多路分离和分派。

l       在像TCP这样的面向字节流的通信协议之上实现消息帧。

l       涉及网络字节序和参数整编(marshaling)的表示转换问题。

为给通信软件的开发者提供这些特性,在ACE中绑定了下面的高级中间件应用:

1.       The ACE ORB(TAO):TAO是使用ACE提供的框架组件和模式构建的CORBA实时实现,包含有网络接口、OS、通信协议和CORBA中间件组件等特性。TAO基于标准的OMG CORBA参考模型,并进行了增强的设计,以克服传统的用于高性能和实时应用的ORB的缺点。TAO像ACE一样,也是可自由使用的开放源码软件。

2.       JAWS:JAWS是高性能、自适配的Web服务器,使用ACE提供的框架组件和模式构建。JAWS被构造成“框架的框架”。JAWS的总体框架含有以下组件和框架:事件多路分派器、并发策略、I/O策略、协议管道、协议处理器和缓存虚拟文件系统。每个框架都被构造成一组协作对象,通过组合和扩展ACE中的组件来实现。JAWS也是可自由使用的开放源码软件。

九、主页

ACE的主页为:http://www.cs.wustl.edu/~schmidt/ACE.html,在这里可获得最新版本的ACE以及其他相关资源。


 =======================================

网络通信

ACE

参考网站:http://www.c’>http://www.c’>http://www.c’>http://www.cs.wustl.edu/~schmidt/ACE.html

C++库的代表,超重量级的网络通信开发框架。ACE自适配通信环境(Adaptive Communication Environment)是可以自由使用、开放源代码的面向对象框架,在其中实现了许多用于并发通信软件的核心模式。ACE提供了一组丰富的可复用C++包装外观(Wrapper Facade)和框架组件,可跨越多种平台完成通用的通信软件任务,其中包括:事件多路分离和事件处理器分派、信号处理、服务初始化、进程间通信、共享内存管理、消息路由、分布式服务动态(重)配置、并发执行和同步,等等。

StreamModule

参考网站:http://www.omnifarious.org/StrMod/’>http://www.omnifarious.org/StrMod/

设计用于简化编写分布式程序的库。尝试着使得编写处理异步行为的程序更容易,而不是用同步的外壳包起异步的本质。

SimpleSocket

参考网站:http://home.hetnet.nl/~lcbokkers/simsock.htm

这个类库让编写基于socket的客户/服务器程序更加容易。

A Stream Socket API for C++

参考网站:http://www.pcs.cnu.edu/’>http://www.pcs.cnu.edu/~dgame/sockets/socketsC++/sockets.html

又一个对Socket的封装库。

2006年03月07日

 SCTP:流控制传输协议

(SCTP:Stream Control Transmission Protocol)



  流控制传输协议 SCTP 主要被设计来在 IP 网络上(也能用于更宽的应用程序)传输 PSTN 信令信息 SS7/C7。SCTP 是一种执行在无连接包网络如 IP 上面的可靠传输协议,其被设计来解决 TCP 在传输实时信令和数据如网络上的信令时所存在的局限性和复杂性问题。此外 SCTP 也能运行在 UDP 层上。

  SCTP 提供如下服务:

  • 承认响应用户数据的错误释放非复制转换;
  • 数据碎片遵从于发现路径的大小;
  • 在多重流中,为个人用户信息的发送到达顺序提供了一个选项,用户信息可以按序发送;
  • 为进入单个 SCTP 包的多重用户信息提供可选包;
  • 通过连接的一个终端或两个终端支持多重自导引来提供网络故障公差。

  SCTP 的设计包括适当的拥塞避免行为和对攻击的泛滥和乔装的抵抗。SCTP 数据报由通用头和块构成,该块既包括了控制信息也包括了用户数据。



协议结构



16 32 bit
SourcePort Number DestinationPort Number
Verification Tag
Checksum



  • Source Port Number ― SCTP 发送方的端口号。接收方结合源 IP 地址,通过使用该端口号识别数据报归属的联接。
  • Destination Port Number ― 目的端口号,即 SCTP 数据报即将到达的地方。接收主机利用该端口号去解除复用 SCTP 数据报使之到达正确的接收终点/应用程序。
  • Verification Tag ― 接收方使用 Verification Tag 去识别联接。在传输过程中,Verification Tag 的值必须设置为联接初始化阶段从对等终点接收到的初始值。
  • Checksum ― 该字段包含一个 SCTP 数据报 Adler-32 校验和。



相关协议

UDPTCPIPSS7/C7

组织来源

SCTP 由 IETF(www.ietf.org)定义在 RFC 2960中。

相关链接 http://www.javvin.com/protocol/rfc2960.pdf: Stream Control Transmission Protocol


相关链接=====================
IBM Develop Work向人们介绍了一种新的传输协议SCTP(Stream Control Transmission Protocol)。这是一种能够在两个端点之间提供稳定,顺序数据收发(类似TCP),同时保持数据消息边界(Data Message Boundaries, 类似UDP)的可靠协议。与TCP和UDP不同的是,SCTP还提供了其他许多高级特性,比如Multi-Homing和Multi-Streaming。
Better networking with SCTP


SCTP数据传输过程的技术研究

http://rence.blogchina.com/3547769.html

实验题目:流控制传输协议实现
系统环境:debian linux sctp 2.6.11.7
               内核需要重新编译,添加SCTP功能
开发环境:gcc-3.3

实验目的:
1.实现基本sctp信息传递。(1-to-1)
2.实现sctp一对多消息传递。(1-to-many)
3.实现sctp多宿主机功能。(sctp more IP)

SCTP基本特点:
1 引言

  在过去的20年内,作为一种可靠的数据传输方式,TCP提供了许多应用服务,但随着IP网的多业务化,尤其是VoIP的发展,TCP出现了很多局限性,例如对于VoIP信令及异步基于事务应用的处理。因此,IEFT的信令传输工作组(SIGTRAN)提出了一种面向多媒体通信的流控制传输协议(SCTP),用于在IP网络上传输PSTN信令消息,即通常所说的SS7 over IP。目前,IEFT将SCTP传输层协议作为主要研究目的,与TCP和UDP共筑于IP层之上。  同TCP一样,SCTP提供面向连接的、点到点的可靠传输,它继承了TCP强大的拥塞控制、数据包丢失发现等功能,任何在TCP上运行的应用都可被移至SCTP上运行。

  不同于TCP的是,SCTP提供了许多对于信令传输很重要的功能,同时,对于其他一些对性能和可靠性有额外需要的应用,它能提供传输优势来满足这些需要。SCTP和TCP最大的区别在于SCTP对多宿(multihoming)和部分有序(partial ordering)的支持。SCTP的多宿使得每个端点可被多个传输地址访问到,选择不同传输地址会导致两个端点间不同的数据路径,理想情况是在每一条路径都建立一条独立的拥塞控制。所以,SCTP的多主机拥塞控制仍需改进。

2 SCTP的特点

  SCTP处于SCTP用户应用层与IP网络层之间,它运用“关联”(association)这个术语定义交换信息的两个对等SCTP用户间的协议状态 。SCTP也是面向连接的,但在概念上,SCTP“关联”比TCP连接更为广泛:TCP的连接只有一个源地址和一个目的地址,SCTP提供一种方式使得每个SCTP端点能为另一个对等端点提供一组传输地址,即传输地址= 一组IP地址+端口号。

在继承TCP特点的基础上,SCTP提供了一些额外的功能:

1. 在多个“流”(stream)中实现用户数据的有序发送

“流”在TCP中指一系列的字节,而在SCTP中是指发送到上层协议的一定系列的用户消息,这些消息的顺序与流内其他消息相关。SCTP用户在建立关联时,可以规定关联支持的流的数目。这个数目是与源端商定的,用户消息与流数目关联。在链路中,SCTP为每个送到对等端的消息分配一个流序号。在接收端,SCTP确保在给定流中消息按顺序发送。同时,当一个流正在等待下一个非顺序的用户消息时,其他流的发送会继续。
2. 根据已发现的路径MTU(最大传输单元)大小进行用户数据分片

  为了确保发送到下层的SCTP数据包与路径MTU一致,SCTP对用户消息分片。在接收端,分片被重组后传给上层SCTP用户。

3. 选择性确认(SACK)和拥塞控制

  选择性确认用于数据包丢失发现,TCP中确认序号返回的是发送方已成功收到数据字节序号(不包含确认序号所指的字节),而SCTP反馈给发送端的是丢失的并且要求重传的消息序号。

  SCTP运用了TCP中的拥塞控制技术,包括慢启动,拥塞避免和快速重传。因此,当和TCP应用共存时,SCTP应用可接收属于SCTP的网络资源部分。

4. 块(chunk)绑定

  即多个用户消息可选择地绑定到一个SCTP包上,通过将消息放到一个或多个SCTP数据结构——“块”中,SCTP保留了应用程序的消息框架边界。不同类型的块可绑定到一个SCTP包中,但是控制块必须放在任何一个数据块之前。

5. 路径管理

  SCTP 路径管理功能主要负责从远端提供的一组传输地址中选择目的传输地址,它根据两个方面来选择目的地址:SCTP用户指示和当前可达的合格目的地。当其他流控制不能提供可达性信息时,路径管理功能定时地扫描链路的可达性,并向SCTP报告远端传输地址所发生的变化。SCTP 路径管理功能模块同时还负责在建立链路时,向远端报告可用的本地地址,并把远端返回的传输地址告诉SCTP用户。

6. 支持多宿

  当SCTP传送数据包给目的IP地址时,如果此IP地址是不可达的,SCTP可以将消息重路由给一个交替的IP地址。这样,在关联的一端甚至两端,可容忍网络级错误。

7. 防范拒绝服务(DoS)攻击

  DoS的攻击方式有很多种,最基本的DoS攻击就是利用合理的服务请求来占用过多的服务资源,从而使合法用户无法得到服务的响应。SYN Flooding攻击是DoS攻击的一种实例,是目前效果最好的一种黑客攻击方式。为了抵抗SYN Flooding对目标主机攻击,SCTP在关联初始化阶段实施了一种安全的“Cookie”机制。

8. 支持多种传输模式

严格有序传输(像TCP),部分有序传输(像per-stream)和无序传输(像UDP)。

实验原理:
1. 利用sctp实现一对一建立连接的S/C数据传输程序。此模式非常类似传统的TCP/IP程序设计流程,但是sctp数据帧的格式与传统TCP/IP数据帧的格式不同。


实验过程:
1. Sctp建立连接的一对一数据传输。


//服务器端程序原代码
//此服务器从客户端接收一个字符串,然后将其中的小写字符转换为大写字符后再反馈给客//户端程序。
//服务器端程序的端口号设为8000

//server.c //基本头文件与传统TCP程序相似,其中指需要添加
#include <stdio.h> // netinet/sctp.h头文件
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <arpa/inet.h>
#include <netdb.h>

#define PORT 8000 //设服务器程序端口号为8000

int main()
{
struct sockaddr_in sin; //定义接收数据的sockaddr结构
struct sockaddr_in pin; //定义反馈数据的sockaddr结构

int sock_descriptor; //定义一个接收、监听套接字变量
int temp_sock_descriptor; //定义一个反馈信息套接字变量
int address_size;

char buf[16384]; //建立一个数据缓冲区

int i, len;

sock_descriptor = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP);
//创建一个sctp(1-to-1)套接字ID
if(sock_descriptor == -1){
perror("call to socket");
exit(1);
}

bzero(&sin, sizeof(sin) ); //初始化接收数据的sockaddr结构
sin.sin_family = PF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
printf("hostIP: %d",sock_descriptor);
sin.sin_port = htons(PORT);

if(bind(sock_descriptor, (struct sockaddr *)&sin, sizeof(sin)) == -1){
perror("call to bind"); //建立一个sctp(1-to-1)套接字
exit(1);
}

if(listen(sock_descriptor, 20) == -1){ //监听套接字
perror("call to listen");
exit(1);
}

printf("Accepting connections …\n");

while(1){
temp_sock_descriptor = accept(sock_descriptor, (struct sockaddr *)&pin, &address_size);
//建立一个反馈信息套接字ID
if(temp_sock_descriptor == -1){
perror("call to accept");
exit(1);
}

if(recv(temp_sock_descriptor, buf, 16384, 0) == -1){
perror("call to recv"); //从监听套接口收到数据存入缓冲区
exit(1);
}

printf("received from client : %s\n", buf);

len = strlen(buf);
for(i = 0; i < len; i++) buf[i] = toupper(buf[i]);
if(send(temp_sock_descriptor, buf, len, 0) == -1){
perror("call to send"); //将反馈信息通过反馈套接口发送出去
exit(1);
}

close(temp_sock_descriptor);
}

return 0;
}




//客户端程序
//客户端程序将用户输入的一个字符串发送给服务器程序,然后等待接收由服务器返回的信息,如果用户没//有输入字符串,程序将会发送一个默认的字符串给服务器程序。
//设服务器的IP地址是192.168.0.132 端口号为 8000
//client.c
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <arpa/inet.h>
#include <netdb.h>

#define PORT 8000

char * host_name = "192.168.0.132";

int main(int argc, char * argv[])
{
char buf[8192];
char message[256];
int socket_descriptor;
struct sockaddr_in pin;
struct hostent * server_host_name;

char * str = "Hello SCTP !"; //设定程序默认字符串

if(argc < 2){
printf("Usage:’test \"not test string\"\n");
printf("We will send a \"Hello SCTP\" test string\n");
}else{
str = argv[1];
}

if((server_host_name = gethostbyname(host_name)) == 0){
perror("Error resolving loca host\n");
exit(1);
}

bzero(&pin, sizeof(pin));
pin.sin_family = PF_INET;
pin.sin_addr.s_addr = htonl(INADDR_ANY);
pin.sin_addr.s_addr = ((struct in_addr *)(server_host_name -> h_addr)) -> s_addr;
pin.sin_port = htons(PORT);

if((socket_descriptor = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP)) == -1){
perror("Error opening socket\n"); //建立一个sctp套接字ID
exit(1);
}
printf("\n%d\n", socket_descriptor);
if(connect(socket_descriptor, (void *)&pin, sizeof(pin)) == -1){
perror("Error connecting to socket\n"); //连接服务器端程序
exit(1);
}

printf("Sending message %s to server…\n", str);

if(send(socket_descriptor, str, strlen(str), 0) == -1){
perror("Error in send\n"); //向服务器端发送数据
exit(1);
}

printf("..sent message.. wait for reponse…\n");

if(recv(socket_descriptor, buf, 8192, 0) == -1){
perror("Error in receiving response from server\n");
exit(1); //从服务器端接收数据
}

printf("\nResponse from server:\n\n%s\n", buf);

close(socket_descriptor);

return 0;
}

sctp协议(1-to-1)编程的过程和系统调用与传统的TCP协议程序设计十分相似。

主要区别在于:
tcp_socket = socket(PF_INET, SOCK_STREAM, 0); //传统的TCP套接口建立
sctp_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP); //sctp套接口

其次:
在底层帧的结构上sctp与TCP存在很大差异

由此sctp协议1-to-1模式的应用相对于1-to-many模式显得不够灵活,也没有体现出sctp独有的新特性。所以在实际应用中sctp 1-to-1模式并不普遍。


2. 利用sctp实现一对多建立连接的消息传输程序。此模式类似UDP数据传输流程,但他与UDP数据传输模式不同的是sctp是建立连接的。



2. Sctp建立连接的一对多消息传输。
用sctp实现一对多消息传输首先要明确几个概念,sctp的消息传送与UDP的消息传送虽然在形式上比较相似但是本质是完全不同的,首先sctp是建立在连接基础之上,而UDP不需要建立连接,sctp消息传输是可靠的,UDP消息传输是不可靠的。

此程序是将客户端发送来的消息内容替换,再反馈给客户端,循环执行。

//server.c
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>

#define PORT 8000 //设服务器端口号为8000

int main()
{
int sctp_socket, i =0;
struct sockaddr_in server_addr; //定义一个套接字结构
struct msghdr recv_mesage; //定义一个消息结构
struct iovec recv_iov; //定义一个消息数据单元结构
int ret;

char a[54]; //定义一个接收缓冲区

if( (sctp_socket = socket(PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP)) < 0 ){
perror("sctp socket:"); //建立一个sctp一对多套接口ID
return -1;
}else
printf("sctp socket OK!\n");

bzero( &server_addr, sizeof(server_addr) ); //初始化套接字结构
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(PORT);
if( bind(sctp_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0){
perror("sctp bind:"); //将套接字结构和套接字ID进行关联
return -1;
}else
printf("sctp bind OK!\n");

if( listen(sctp_socket, 10) < 0 ){ //监听此套接口
perror("sctp listen:");
return -1;
}else
printf("sctp listen OK!\n");

while(1){

bzero( &a, sizeof(a) ); //初始化接收数据缓冲区

bzero( &recv_iov, sizeof(recv_iov) ); //初始化数据单元结构

recv_iov.iov_base = (void *)a;
recv_iov.iov_len = sizeof(a);

bzero( &recv_mesage, sizeof(recv_mesage) ); //初始化消息结构
recv_mesage.msg_name = &server_addr;
recv_mesage.msg_namelen = sizeof(server_addr);
recv_mesage.msg_iov = &recv_iov;
recv_mesage.msg_iovlen = 1; //设置消息单元数量

if((ret = recvmsg(sctp_socket, &recv_mesage, 0)) < 0 ){
perror("sctp recvmsg:"); //接收消息
return -1;
}else{
printf("sctp recvmsg OK!, ret = %d\n", ret);
printf("NO: %d message is c: %s\n\n", i, (char *)recv_mesage.msg_iov -> iov_base);
}
recv_mesage.msg_iov -> iov_base = "ok!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";
if((ret = sendmsg(sctp_socket, &recv_mesage, 0)) < 0 ){
perror("sctp sendmsg:"); //反馈消息
return -1;
}else{
printf("sctp sendmsg OK!, ret = %d\n", ret);
printf("NO: %d message is c: %s\n\n", i++, (char *)recv_mesage.msg_iov -> iov_base);
}
}

return 0;
}


此程序向服务器端发送一条消息,再等待并接收服务器端的反馈消息,循环执行。

//client.c
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>

#define PORT 8000 //设置服务器端端口号为 8000

int main()
{
int sctp_socket, i = 0;
struct sockaddr_in client_addr; //定义一个套接字结构
struct msghdr send_mesage; //定义一个消息结构
struct iovec send_iov, recv_iov; //定义一个发送消息数据单元结构和一个接收消息数据单元结构
int ret;

char * msg_a = "Hello SCTP !!!!!!!!!!!!!!!!!!!!!\a"; //声明要发送的字符串
char msgbuf[1024]; //定义一个接收数据缓冲区

if( (sctp_socket = socket(PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP)) < 0 ){
perror("sctp socket:"); //建立一个sctp套接字ID
return -1;
}else
printf("sctp socket OK!\n");

while(1){

bzero( &send_iov, sizeof(send_iov) ); //初始化消息数据单元
send_iov.iov_base = (void *)msg_a;
send_iov.iov_len = strlen(msg_a);

bzero( &client_addr, sizeof(client_addr) ); //初始化套接字结构
client_addr.sin_family = AF_INET;
client_addr.sin_addr.s_addr = ((struct in_addr *)(gethostbyname("192.168.0.132") -> h_addr)) -> s_addr;
client_addr.sin_port = htons(PORT);

bzero( &send_mesage, sizeof(send_mesage) ); //初始化消息结构
send_mesage.msg_name = (void *)&client_addr;
send_mesage.msg_namelen = sizeof(client_addr);
send_mesage.msg_iov = &send_iov;
send_mesage.msg_iovlen = 1; //设置消息数据单元数量

if( (ret = sendmsg(sctp_socket, &send_mesage, 0)) < 0 ){
perror("sendmsg:"); //发送消息
return -1;
}else{
printf("send ret = %d\n", ret);
printf("sendmessage %d msg_c: %s\n\n", i,(char *)send_mesage.msg_iov -> iov_base);
}

bzero(msgbuf, sizeof(msgbuf)); //初始化接收缓冲区
bzero(&recv_iov, sizeof(recv_iov));
recv_iov.iov_base = (void *)msgbuf;
recv_iov.iov_len = 1024;
send_mesage.msg_iov = &recv_iov;
send_mesage.msg_iovlen =1;
if( (ret = recvmsg(sctp_socket, &send_mesage, 0)) < 0 ){
perror("recvmsg:"); //接收服务器反馈消息
return -1;
}else{
printf("recv ret = %d\n", ret);
printf("recvmessage %d msg_c: %s\n\n", i++,(char *)send_mesage.msg_iov -> iov_base);
}
sleep(1);
}

close(sctp_socket);

return 0;
}






应用sctp协议开发一对多网络传输程序的关键是对sctp消息的理解和运用,sctp消息中封装了关于消息传输所需的信息,其中包括对方主机IP地址,消息中数据的长度,消息数据单元的数量等等。

消息结构代码原型:
struct msghdr
{
void *msg_name; //与此消息相关联的套接字结构指针
socklen_t msg_namelen; //与此消息相关联的套接字结构长度

struct iovec *msg_iov; //此消息所要挟带的数据单元
size_t msg_iovlen; //此消息所要挟带的数据单元长度

void *msg_control; //此消息的相关控制结构
size_t msg_controllen; //此消息的相关控制结构长度

int msg_flags; //此消息的状态标志
};

//消息结构中的数据单元结构代码原型
struct iovec
{
void iov_base; //消息所要传送的数据指针,可以是任何类型数据
size_t iov_len; //消息所要传送的数据长度
}
消息数据单元可以是一个结构数组,一次可以将许多不同的数据加载到同一个消息结构当中。接收时可以通过算法将不同类型数据分开存储,也可以存为一个整体数据快。

iovec结构中存有将要被发送出去的数据或接收数据的缓冲区,而消息结构msghdr中除了数据单元外还有套接口的信息和控制信息。我们可以一次定义多个指向不同IP地址和端口的消息结构,同时在服务器端也可以用同样的方法定义并关联多个消息结构,这样一来就可以设计出根据不同的变化把同一个消息
发送至不同的对端,也可以利用sctp消息实现服务器的单机、多机热备份(冗余应用)。

总结: 利用sctp开发网络程序的基本步骤。

#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/sctp.h>

sctp 1-to-1
服务器端:
sctp_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP);
bind();
listen();
sccept();
close();
客户端:
sctp_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP);
connect();
close();
sctp 1-to-many
服务器端:
sctp_socket = socket(PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
bind(); //可以关联多个不同网络端口(本地,其他主机)
listen(); //可同时监听多个不同的网络端口(本地,其他主机)
recvmsg();
sendmsg();
close();
客户端:
sctp_socket = socket(PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
sendmsg();
recvmsg();
close();

2006年03月01日

Develop your own filesystem with FUSE

No kernel programming required

Document options

Document options requiring JavaScript are not displayed

Sample code



Rate this page

Help us improve this content


Level: Introductory

Sumit Singh (sumising@in.ibm.com), Software Engineer, IBM

28 Feb 2006

With Filesystem in Userspace (FUSE), you can develop a user space filesystem framework without understanding filesystem internals or learning kernel module programming. Follow this simple, step-by-step guide to install, customize, and enable FUSE and AFS, so you can create your own fully functional filesystem in user space in Linux®.

A filesystem is a method for storing and organizing computer files and directories and the data they contain, making it easy to find and access them. If you are using a computer, you are most likely using more than one kind of filesystem. A filesystem can provided extended capabilities. It can be written as a wrapper over an underlying filesystem to manage its data and provide an enhanced, feature-rich filesystem (such as cvsfs-fuse, which provides a filesystem interface for CVS, or a Wayback filesystem, which provides a backup mechanism to keep old copies of data).

Before the advent of user space filesystems, filesystem development was the job of the kernel developer. Creating filesystems required knowledge of kernel programming and the kernel technologies (like vfs). And debugging required C and C++ expertise. But other developers needed to manipulate a filesystem — to add personalized features (such as adding history or forward-caching) and enhancements.

Introducing FUSE

FUSE lets you develop a fully functional filesystem that has a simple API library, can be accessed by non-privileged users, and provides a secure implementation. And, to top it all off, FUSE has a proven track record of stability.

With FUSE, you can develop a filesystem as executable binaries that are linked to the FUSE libraries — in other words, this filesystem framework doesn’t require you to learn filesystem internals or kernel module programming.

When it comes to filesystems, the user space filesystem is not a new design. A sampling of commercial and academic implementations of user space filesystems include:

  • LUFS is a hybrid user space filesystem framework that supports an indefinite number of filesystems transparently for any application. It consists of a kernel module and a user space daemon. Basically it delegates most of the VFS calls to a specialized daemon that handles them.
  • UserFS allows user processes to be mounted as a normal filesystem. This proof-of-concept prototype provides ftpfs, which allows anonymous FTP with a filesystem interface.
  • The Ufo Project is a global filesystem for Solaris that allows users to treat remote files exactly as if they were local.
  • OpenAFS is an open source version of the Andrew FileSystem.
  • CIFS is the Common Internet FileSystem.

Unlike these commercial and academic examples, FUSE brings the capabilities of this filesystem design to Linux. Because FUSE uses executables (instead of, say, shared objects as LUFS uses), it makes debugging and developing easier. FUSE works with both kernels (2.4.x and 2.6.x) and now supports Java™ binding, so you aren’t limited to programming the filesystem in C and C++. (See Resources for more userland filesystems that use FUSE.)

To create a filesystem in FUSE, you need to install a FUSE kernel module and then use the FUSE library and API set to create your filesystem.




Back to top



Unpack FUSE

To develop a filesystem, first download the FUSE source code (see Resources) and unpack the package: tar -zxvf fuse-2.2.tar.gz. This creates a FUSE directory with the source code. The contents of the fuse-2.2 directory are:

  • ./doc contains FUSE-related documentation. At this point, there is only one file, how-fuse-works.
  • ./kernel contains the FUSE kernel module source code (which, of course, you don’t need to know for developing a filesystem with FUSE).
  • ./include contains the FUSE API headers, which you need to create a filesystem. The only one you need now is fuse.h.
  • ./lib holds the source code to create the FUSE libraries that you will be linking with your binaries to create a filesystem.
  • ./util has the source code for the FUSE utility library.
  • ./example, of course, contains samples for your reference, like the fusexmp.null and hello filesystems.




Back to top



Build and install FUSE

  1. Run the configure script from the fuse-2.2 directory: ./configure. This creates the required makefiles, etc.

  2. Run ./make to build the libraries, binaries, and kernel module. Check the kernel directory for the file ./kernel/fuse.ko — this is the kernel module file. Also check the lib directory for fuse.o, mount.o, and helper.o.

  3. Run ./make install to complete the installation of FUSE.

    Alternative: Skip this step if you want to install the module in the kernel yourself using insmod. For example: /usr/local/sbin/insmod ./kernel/fuse.ko or /sbin/insmod ./kernel/fuse.ko. Remember to install the required module with root privileges.

You can do the above steps in just one step if you want. From the fuse-2.2 directory, run ./configure; make; make install;.

Important: When making FUSE, you need to have the kernel headers or source code in place. To keep things simple, make sure that the kernel source code is in the /usr/src/ directory.




Back to top



Customize the filesystem

Now let’s create a filesystem so you can access your AFS space on a Linux box with latest kernel, using an older Linux kernel. You will have two processes: one server process running on a older Linux kernel, and the FUSE client process running on a Linux box with the latest kernel. Whenever a request comes to your FUSE client process, it contacts the remote server process. For communication purposes, this filesystem uses RX RPC code that is part of AFS, so you need to build OpenAFS. (Figure 1 gives an overview of this AFS filesystem.)


Figure 1. Overview of AFS-FUSE filesystem
Overview of AFS-FUSE filesystem

Build OpenAFS

  1. Download the OpenAFS Linux sources and untar the source.

    In the directory where you have untarred the source, run ./make ./configure --enable-transarc-paths. If ./configure cannot understand the sysname for build, then use the --with-afs-sysname option with the appropriate sysname.

    For a build on the Linux 2.4 kernel, use following command: ./configure --enable-transarc-paths --with-afs-sysname=i386_linux24.

  2. Run ./make, and then run ./make dest. Check for any errors during build.

    If the build went okay, then your AFS source tree is ready to work with. At this stage, you need to prepare a development directory named afsfuse. In that directory, create two more directories:

    • The include directory will contain the include headers from OpenAFS and FUSE.
    • The lib directory will contain the libraries from OpenAFS and FUSE.
  3. Copy the headers and libraries.

    First copy the AFS headers from the OpenAFS directory by copying the directories and files from the dest\i386_linux24\include into the include directory. Then copy the FUSE headers from the fuse-2.2 directories into this directory. Repeat the same steps for libraries into the lib directory.

  4. Create the structure of the application.

    You need two sets of files for two sets of processes. Name the client process files using the naming scheme afsfuse_client.*; name the server process files afsfuse_server.*.

    You will thus have an afsfuse_client.c file that will contain the FUSE process code, an afsfuse_server.c file that will contain the server code for the process running on a remote box, a makefile, and an rxgen file for creating the RPC header (like afsfuse.xg).

    The afsfuse_client.c file will create afsfuse_client process code that will be called by the FUSE filesystem to create your filesystem (use the example fuse-2.2/example/fusexmp.c to create this file).

Define necessary functions

To create a filesystem with FUSE, you need to declare a structure variable of type fuse_operations and pass it on to the fuse_main function. The fuse_operations structure carries a pointer to functions that will be called when the appropriate action is required. Listing 1 shows the fuse_operations structure.


Listing 1. Necessary functions in fuse_operation structure



struct fuse_operations {
    int (*getattr) (const char *, struct stat *);
    int (*readlink) (const char *, char *, size_t);
    int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t);
    int (*mknod) (const char *, mode_t, dev_t);
    int (*mkdir) (const char *, mode_t);
    int (*unlink) (const char *);
    int (*rmdir) (const char *);
    int (*symlink) (const char *, const char *);
    int (*rename) (const char *, const char *);
    int (*link) (const char *, const char *);
    int (*chmod) (const char *, mode_t);
    int (*chown) (const char *, uid_t, gid_t);
    int (*truncate) (const char *, off_t);
    int (*utime) (const char *, struct utimbuf *);
    int (*open) (const char *, struct fuse_file_info *);
    int (*read) (const char *, char *, size_t, off_t, struct fuse_file_info *);
    int (*write) (const char *, const char *, size_t, off_t,struct fuse_file_info *);
    int (*statfs) (const char *, struct statfs *);
    int (*flush) (const char *, struct fuse_file_info *);
    int (*release) (const char *, struct fuse_file_info *);
    int (*fsync) (const char *, int, struct fuse_file_info *);
    int (*setxattr) (const char *, const char *, const char *, size_t, int);
    int (*getxattr) (const char *, const char *, char *, size_t);
    int (*listxattr) (const char *, char *, size_t);
    int (*removexattr) (const char *, const char *);
};


None of these operations are absolutely essential, but many are needed for a filesystem to work properly. You can implement a full-featured filesystem with the special-purpose methods .flush, .release, or .fsync. (This article doesn’t cover any xattr functions.) The functions shown in Listing 1 are as follows:

  • getattr: int (*getattr) (const char *, struct stat *);
    This is similar to stat(). The st_dev and st_blksize fields are ignored. The st_ino field is ignored unless the use_ino mount option is given.
  • readlink: int (*readlink) (const char *, char *, size_t);
    This reads the target of a symbolic link. The buffer should be filled with a null-terminated string. The buffer size argument includes the space for the terminating null character. If the linkname is too long to fit in the buffer, it should be truncated. The return value should be "0" for success.
  • getdir: int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t);
    This reads the contents of a directory. This operation is the opendir(), readdir(), …, closedir() sequence in one call. For each directory entry, the filldir() function should be called.
  • mknod: int (*mknod) (const char *, mode_t, dev_t);
    This creates a file node. There is no create() operation; mknod() will be called for creation of all non-directory, non-symlink nodes.
  • mkdir: int (*mkdir) (const char *, mode_t);
    rmdir: int (*rmdir) (const char *);
    These create and remove a directory, respectively.
  • unlink: int (*unlink) (const char *);
    rename: int (*rename) (const char *, const char *);
    These remove and rename a file, respectively.
  • symlink: int (*symlink) (const char *, const char *);
    This creates a symbolic link.
  • link: int (*link) (const char *, const char *);
    This creates a hard link to a file.
  • chmod: int (*chmod) (const char *, mode_t);
    chown: int (*chown) (const char *, uid_t, gid_t);
    truncate: int (*truncate) (const char *, off_t);
    utime: int (*utime) (const char *, struct utimbuf *);
    These change the permission bits, owner and group, size, and access/modification times of a file, respectively.
  • open: int (*open) (const char *, struct fuse_file_info *);
    This is the file open operation. No creation or truncation flags (O_CREAT, O_EXCL, O_TRUNC) will be passed to open(). This should check if the operation is permitted for the given flags. Optionally, open() may also return an arbitrary filehandle in the fuse_file_info structure, which will be passed to all file operations.
  • read: int (*read) (const char *, char *, size_t, off_t, struct fuse_file_info *);
    This reads data from an open file. read() should return exactly the number of bytes requested, except on EOF or error; otherwise, the rest of the data will be substituted with zeroes. An exception to this is when the direct_io mount option is specified, in which case the return value of the read() system call will reflect the return value of this operation.
  • write: int (*write) (const char *, const char *, size_t, off_t, struct fuse_file_info *);
    This writes data to an open file. write() should return exactly the number of bytes requested except on error. An exception to this is when the direct_io mount option is specified (as in the read() operation).
  • statfs: int (*statfs) (const char *, struct statfs *);
    This gets filesystem statistics. The f_type and f_fsid fields are ignored.
  • flush: int (*flush) (const char *, struct fuse_file_info *);
    This represents flush-cached data. It is not equivalent to fsync() — it’s not a request to sync dirty data. flush() is called on each close() of a file descriptor, so if a filesystem wants to return write errors in close() and the file has cached dirty data, this is a good place to write back data and return any errors. Since many applications ignore close() errors, this is not always useful.

Note: The flush() method may be called more than once for each open(). This happens if more than one file descriptor refers to an opened file due to dup(), dup2(), or fork() calls. It is not possible to determine if a flush is final, so each flush should be treated equally. Multiple write-flush sequences are relatively rare, so this shouldn’t be a problem.

  • release: int (*release) (const char *, struct fuse_file_info *);
    This releases an open file. release() is called when there are no more references to an open file — all file descriptors are closed and all memory mappings are unmapped. For every open() call, there will be exactly one release() call with the same flags and file descriptor. It is possible to have a file opened more than once, in which case only the last release will count and no more reads/writes will happen on the file. The return value of release is ignored.
  • fsync: int (*fsync) (const char *, int, struct fuse_file_info *);
    This synchronizes file contents. If the datasync parameter is non-zero, then only the user data should be flushed, not the meta data.
  • setxattr: int (*setxattr) (const char *, const char *, const char *, size_t, int);
    getxattr: int (*getxattr) (const char *, const char *, char *, size_t);
    listxattr: int (*listxattr) (const char *, char *, size_t);
    removexattr: int (*removexattr) (const char *, const char *);
    These set, get, list, and remove extended attributes, respectively.

The resulting filesystem

Your filesystem will look something like this:


afsfuse_client   <--RX[RPC]-->   afsfuse_server


The afsfuse_client will forward the filesystem calls passed to it to the afsfuse_server residing on a different machine. The afsfuse_server will service all the requests sent to it by the client and return the results to the client. It does all the jobs necessary. The mechanism used for RPC is RX. There is no caching involved for either data or metadata.




Back to top



Define the RX RPC layer

Before going further, you need to define your RX RPC layer. To do that, create an .xg file for rxgen, to describe your proxy and stub code that will be linked with your afsfuse_client.c and afsfuse_server.c. Listing 2 shows how to create an afsfuse.xg file with the following contents:


Listing 2. Creating an afsfuse.xg file



#define MYMAXPATH 512
%#include <rx/rx.h>
%#include </rx_null.h >
%#define SAMPLE_SERVER_PORT 5000
%#define SAMPLE_SERVICE_PORT 0
/* i.e. user server's port */
%#define SAMPLE_SERVICE_ID 4 /* Maximum number of requests that will be handled by this
                                service simultaneously */
/* This number will also be guaranteed to execute in parallel if no services' requests
   are being processed */
%#define SAMPLE_MAX 2 /* Minimum number of requests that are guaranteed to be handled
                         immediately */
%#define SAMPLE_MIN 1 /* Index of the "null" security class in the sample service. This
                         must be 0 (there are N classes, numbered from 0. In this case,
                         N is 1) */
%#define SAMPLE_NULL 0 /********************** fuse4_file_info taken from fuse.h the
                        rxgen does not understands fuse.h  mystat taken from man 2
                        mystat these are required again rxgen does not understand the
                        struct paras and will bump.. **********************/
struct my_file_info { /** Open flags. Available in open() and release() */
                     int flags; /** File handle. May be filled in by filesystem in
                                    open(). Available in all other file operations */
                     unsigned int fh; /** In case of a write operation indicates if
                                          this was caused by a writepage */
                     int writepage;
                    };
struct mystatfs {
                    afs_uint32 f_type; /* type of filesystem (see below) */
                    afs_uint32 f_bsize; /* optimal transfer block size */
                    afs_uint32 f_blocks; /* total data blocks in file system */
                    afs_uint32 f_bfree; /* free blocks in fs */
                    afs_uint32 f_bavail; /* free blocks avail to non-superuser */
                    afs_uint32 f_files; /* total file nodes in file system */
                    afs_uint32 f_ffree; /* free file nodes in fs */
                    afs_uint32 f_fsid1; /* file system id */
                    afs_uint32 f_fsid2; /* file system id */
                    afs_uint32 f_namelen; /* maximum length of filenames */
                    afs_uint32 f_spare[6]; /* spare for later */
                };
struct mystat {
                    afs_uint32 st_dev; /* device */
                    afs_uint32 st_ino; /* inode */
                    afs_uint32 st_mode; /* protection */
                    afs_uint32 st_nlink; /* number of hard links */
                    afs_uint32 st_uid; /* user ID of owner */
                    afs_uint32 st_gid;/* group ID of owner */
                    afs_uint32 st_rdev; /* device type (if inode device) */
                    afs_uint32 st_size; /* total size, in bytes */
                    afs_uint32 st_blksize; /* blocksize for filesystem I/O */
                    afs_uint32 st_blocks; /* number of blocks allocated */
                    afs_uint32 st_atim; /* time of last access */
                    afs_uint32 st_mtim; /* time of last modification */
                    afs_uint32 st_ctim; /* time of last change */
                };
struct my_dirhandle{
                    afs_uint32 type;
                    afs_uint32 inode;
                    char name[MYMAXPATH];
                };
typedef my_dirhandle bulkmydirhandles<>;
 /*********************phase 1 functions *********************************************/
rxc_getattr(IN string mypath<MYMAXPATH>, IN int dummy) split = 1;
rxc_getdirWrapper(IN string path<MYMAXPATH>, OUT bulkmydirhandles *handles) = 2;
rxc_read(IN string path<MYMAXPATH>;, IN afs_uint32 size, IN afs_uint32 offset,
         IN struct my_file_info *fi) split = 3;
rxc_open(IN string path<MYMAXPATH>, IN int flags, OUT u_int *hd) = 4;
rxc_write(IN string path<MYMAXPATH>,IN afs_uint32 size, IN afs_uint32 offset,
          IN struct my_file_info *fi) split = 5;
rxc_chmod(IN string path<MYMAXPATH>, IN afs_uint32 mode) = 6;
rxc_chown(IN string path<MYMAXPATH>, IN afs_uint32 uid, IN afs_uint32 gid) = 7;
rxc_utime(IN string path<MYMAXPATH>, IN afs_uint32 at,IN afs_uint32 mt) = 8;
rxc_mknod(IN string path<MYMAXPATH>, afs_uint32 mode, afs_uint32 rdev) = 9 ;
rxc_mkdir(IN string path<MYMAXPATH>, IN afs_uint32 mode) = 10;
rxc_unlink(IN string path<MYMAXPATH>) = 11 ;
rxc_rmdir(IN string path<MYMAXPATH>) = 12;
rxc_rename(IN string from<MYMAXPATH>, IN string to<MYMAXPATH>) = 13;
rxc_truncate(IN string path<MYMAXPATH>, IN afs_uint32 size) = 14;
rxc_release(IN string path<MYMAXPATH>, IN struct my_file_info *fi) = 15;
rxc_readlink(IN string path<MYMAXPATH>, IN afs_uint32 size,OUT string
             data<MYMAXPATH>) = 16;
rxc_symlink(IN string from<MYMAXPATH>, IN string to<MYMAXPATH>) = 17;
rxc_link(IN string from<MYMAXPATH>, IN string to<MYMAXPATH>) = 18;
rxc_statfs(IN string path<MYMAXPATH>, OUT struct mystatfs *stbuf) = 19;
rxc_fsync(IN string path <MYMAXPAT>, IN int isdatasync, IN struct my_file_info
          *fi) = 20 ;
rxc_flush(IN string path <MYMAXPATH>, IN struct my_file_info *fi) = 21 ;


When defining the RX RPC layer, note these points:

  • You’ve defined mystatfs, mystat, and my_file_info as a wrapper over statfs, stat, and fuse_file_info structures. These will be transformed over wire using the generated XDR code. (XDR, External Data Representation, allows data to be wrapped in an architecture-independent manner so data can be transferred between heterogeneous computer systems.)
  • You’ve defined nearly one function for every member of structure fuse_operations with nearly the same parameters since the job of the afsfuse_client is just to take the calls from the FUSE filesystem and pass them on to the afsfuse_server.
  • You’ve hard-coded some values like MYMAXPATH, which you should obtain from the system — hard-coding was done for the sake of simplicity.




Back to top



Create client and stub files

Next compile the afsfuse.xg file with rxgen to create client and stub files. From the directory containing the source for your afsfuse_server and afsfuse_client, run the command openafs-1.2.13/i386_linux24/dest/bin/rxgen afsfuse.xg. This creates the following files:

  • afsfuse.cs.c is the client stub code to be linked with the afsfuse_client.c.
  • afsfuse.h is the header containing various definitions for your FUSE RX code.
  • afsfuse.ss.c is the server stub code (proxy code) to be linked with your afsfuse_server code.
  • afsfuse.xdr.c contains code to marshall the three structures you defined in your afsfuse.xg.

Now add some code to the afsfuse_client.c and afsfuse_server.c to do the real work. Most of the calls will look like this:

  • Our_call_in_afs_fuse_client(). Marshall the parameters and prepare for RPC. Call the afsfuse_server application over RX [RPC]. Demarshall the parameters. Copy the values to the formal parameters passed to this function.
  • Our_call_in_afs_fuse_server(). Demarshall the parameters. Call the local filesystem or AFS-specific functions. Marshall the parameters and prepare for RPC. Make the RX RPC call.

The afsfuse_client.c call looks like this:


int afsfuse_readlink(const char *path, char *buf, size_t size){
    rx_connection *local& int ret& char *buffer = malloc (512)&
    memset(buffer,0,512)& memset(buf,0,size)& local = getconnection()&
    ret = rxc_rxc_readlink(local,path,512,&buffer) // rpc call
         relconnection(local)&
         strncpy(buf,buffer,512-1)&
        //<- demarshall the parametrs
        return ret&
    }


The afsfuse_server.c call looks like this:


Listing 3. afsfuse_server.c call



int rxc_rxc_readlink( struct rx_call *call, char * path, afs_uint32 size, char**data)
    { int ret& char lbuff[512] ={0}&
    translatePath(path,lbuff)& //<- make filesystem call
     *data = malloc(512)&
     res = readlink(lbuff, *data, 512-1)&
     if(res == -1) return -errno& (*data)[res] = '\0'& return 0&
    }


Similarly, you can add code in other functions to enhance your filesystem.

You still need to create a makefile to compile your code. Remember to include the following options while compiling code for the afsfuse_client: -D_FILE_OFFSET_BITS=64 and -DFUSE_USE_VERSION=22.


Listing 4. Generating the makefile to compile client code



SRCDIR=./ LIBRX=${SRCDIR}lib/librx.a
LIBS=${LIBRX} ${SRCDIR}lib/liblwp.a
#CC = g++
CFLAGS=-g -I. -I${SRCDIR}include -I${SRCDIR}include/fuse/ -DDEBUG ${XCFLAGS}
    -D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=22
afsfuse_client: afsfuse_client.o afsfuse.xdr.o ${LIBS} bulk_io.o afsfuse.cs.o
    ${CC} ${CFLAGS} -o afsfuse_client afsfuse_client.o ${SRCDIR}lib/fuse/fuse.o
    ${SRCDIR}lib/fuse/mount.o ${SRCDIR}lib/fuse/helper.o
    ${SRCDIR}lib/fuse/fuse_mt.o bulk_io.o afsfuse.cs.o afsfuse.xdr.o ${LIBS}
afsfuse_server: afsfuse_server.o afsfuse.xdr.o afsfuse.ss.o bulk_io.o ${LIBS}
    ${CC} ${CFLAGS} -o afsfuse_server afsfuse_server.o bulk_io.o afsfuse.ss.o
    afsfuse.xdr.o ${LIBS}
#afsfuse_client.o: afsfuse.h
#afsfuse_server.o: afsfuse.h
bulk_io.o: ${CC} -c -g -I${SRCDIR}include bulk_io.c afsfuse.cs.c afsfuse.ss.c
    afsfuse.er.c afsfuse.h afsfuse.xdr.c: afsfuse.xg rxgen afsfuse.xg
afsfuse.xdr.o: afsfuse.xdr.c ${CC} -c -g -I{SRCDIR}include afsfuse.xdr.c
all: afsfuse_server afsfuse_client
clean: rm *.o rm afsfuse_client rm afsfuse_server


Remember, you still need to use librx.a and liblwp.a to link to RX and LWP code for RX. And fuse/fuse.o, fuse/helper.o, and fuse/mount.o are the FUSE libraries you need to link your code to.




Back to top



Conclusion

In this article, you’ve learned how to install FUSE and OpenAFS and how to use them to create and customize your own user space filesystem, a fully functional, stable filesystem in Linux that doesn’t require you to patch or recompile the active kernel — you don’t even have to be a kernel module programmer. You’ve seen details of the two key concepts in enabling a FUSE filesystem: how to install and configure the FUSE kernel module and how to leverage the power of the FUSE libraries and APIs.





Back to top



Download

Description Name Size Download method
AFSFuse filesystem sample code l-fuse.zip 9KB HTTP
Information about download methods Get Adobe® Reader®




Back to top



Resources

Learn


Get products and technologies


Discuss




Back to top



About the author

Sumit Singh is a Software Engineer in the enterprise filesystem group at IBM. His major work involves providing L3 support for AFS.

2006年02月24日


建立搜索引擎
没有全文检索,企业内部的知识管理系统就不能成为成功的系统。构建一个类似 GOOGLE 的全文检索系统的是否要花费巨大呢?看看 Google 的搜索引擎软件目录吧。

我对其中的两个开放源码的搜索引擎进行了测试。htdig 是一个不错的搜索引擎软件,可惜不支持中文的检索;ASPseek 接着走入我的视线,这个软件对中文的支持非常之好,就连CGI的界面、CGI传递参数都和 GOOGLE 非常类似。

ASPseek 由三个部分组成:前端的 cgi 程序 s.cgi 提供查询界面和返回查询结果;后端的守护程序 searchd 接收cgi程序的查询请求,执行数据库查询,返回结果;后台数据库的维护则由程序 index 完成。

相关链接:


Google的搜索引擎软件目录

参见:http://dir.google.com/alpha/Top/ … net/Servers/Search/

另一个搜索引擎软件目录:

Search Tools for Web Sites and Intranets :http://www.searchtools.com/tools/tools.html

ASPseek 网站

ASPseek.org:http://www.aspseek.org/

ASPseek论坛

关于ASPseek的求助信息,可以访问ASPseek论坛:http://forum.aspseek.org/

2.1. 安装 ASPSeek
ASPseek 安装过程比较简单,需要注意的是 ASPseek 的安装和运行需要先安装和配置 MySQL。下面是一般的安装过程(假设MySQL已经正确的安装在路径 /usr/local/mysql/ 下):

root>; tar zxvf aspseek-1.2.10.tar.gz
root>; cd aspseek-1.2.10
root>; ./configure –with-mysql=/usr/local/mysql –prefix=/usr/local/aspseek
root>; make && make install
root>; /usr/local/aspseek/sbin/aspseek-mysql-postinstall
root>; cp /usr/local/aspseek/bin/s.cgi <WWWROOT>;/cgi-bin/
root>; useadd aspseek
root>; su – aspseek
aspseek>; /usr/local/aspseek/sbin/index  
aspseek>; /usr/local/aspseek/sbin/searchd -D  



指出 mysql 的安装路径和设置 ASPseek 的安装路径

初始化 ASPseek 数据库设置。创建数据库 aspseek12,访问该数据库的用户名和口令保存在配置文件 /usr/local/aspseek/etc/db.conf 中

将cgi程序 s.cgi 程序拷贝到WEB服务器的cgi-bin目录中

为确保系统安全,创建用户 aspseek,并使用该用户的身份,进行数据索引的维护和启动搜索引擎服务程序

以 aspseek 用户的身份,进行数据索引的维护

以 aspseek 用户的身份,启动搜索引擎服务程序
2.2. 数据库维护
index 程序完成的功能包括网站爬虫、网页下载、解析、数据库维护。

2.2.1. 配置文件: aspseek.conf
aspseek.conf 是 index 程序的配置文件,告诉 index 程序为哪个网址建立索引,如果建立索引等等。

Include db.conf
UtfStorage yes
Include ucharset.conf  
Period 1d
Server        URL



包含 db.conf 配置文件,设置连接 MySQL 数据库的用户名、口令等。例如:DBAddr mysql://aspseek12ASSWOR-IS-HERE@localhost/aspseek12/

设定网页重建索引的间隔,作用域到下一个 Period 命令或者文件结尾。对作用域内的 Server 指定的网站有效,因此可以对不同的网站设置不同的更新频率

以 UTF-8 格式存储 MySQL 数据库中信息

配置字符集。若需要能够对中文进行检索,需要打开 CharsetTableU2 和 Dictionary2 的配置

最重要的设置。告诉 index 为哪些网站建立索引,可通过多个 Server 配置设置多个服务器。注意:如果在URL中包含路径并不能将索引限制在该目录下,仍然会对整个网站建立索引。如果想限制某些路径,使用 Disallow 配置,例如下面的配置将对网站的索引限制在 url: http://members.aol.com/midlandsda 下。Server http://www.aol.com/
Allow ^http://members.aol.com/midlandsda
Disallow ^http://www.aol.com/


2.2.2. 用 index 程序定期更新搜索引擎数据库

index -a

为所有网页重新建立索引。不使用该参数,则参考配置中的 Period 参数,只对早于这个时间的网页重建索引。

index -S

显示数据库的统计信息

通过 crontab 设置定时启动 index 重建检索

0 0 * * * su -c ‘/usr/local/aspseek/sbin/index’ aspseek



注意要以 aspseek 用户身份执行。


2.3. searchd 后台数据库检索
searchd 是 ASPseek 的守护进程,用来接收 cgi 程序(s.cgi)的查询请求,执行查询动作(搜索由 index 程序创建的数据库),将结果反馈给 cgi 程序(s.cgi)。

2.3.1. searchd.conf
searchd 程序的配置文件。

# Port 12345
Include db.conf
UtfStorage yes
Include ucharset.conf  



设置 searchd 侦听的端口。确省为 12345

包含 db.conf 配置文件,设置连接 MySQL 数据库的用户名、口令等。例如:DBAddr mysql://aspseek12ASSWOR-IS-HERE@localhost/aspseek12/

以 UTF-8 格式存储 MySQL 数据库中信息

配置字符集。若需要能够对中文进行检索,需要打开 CharsetTableU2 和 Dictionary2 的配置
2.3.2. 运行 searchd
配置开机自动执行 searchd。

#!/bin/sh
# FileName: /etc/rc.d/rc3.d/S99aspseek
# Script to control aspseek
#

case "$1" in
’start’)
        echo "starting aspseek server …  "
        su aspseek -c "/usr/local/aspseek/sbin/searchd -D -R"
        echo done
        ;;
’stop’)
        echo "stopping news server …  "
        killall -9 searchd
        echo done
        ;;
*)
        echo "usage: news.sh {start | stop}"
        ;;
esac


2.4. s.cgi: 具有类似GOOGLE查询界面的cgi程序
搜索引擎的界面是由 CGI 提供的。ASPseek 的CGI程序叫做 s.cgi,当然可以改成其它名字。配置则非常简单,除了要将 Apache 配置为支持 cgi 外,只需要将 s.cgi 从 /usr/local/aspseek/bin/ 目录下拷贝到 Apache 的 cgi-bin 目录下即可。配置 Apache 可能非常简单,也许一句 "ScriptAlias /cgi-bin/ /PATH/cgi-bin/" 就足够了。

我感打赌,s.cgi 一下子就会抓住你的眼球,因为 s.cgi 程序提供的一流的查询界面,和伟大的 Google 太类似了,尤其是那一排字母 "e"。



ASPseek 查询界面


s.cgi 还提供了定制界面的方案:只需要修改模板文件 /usr/local/aspseek/etc/s.htm 即可。下面是 s.htm 定制的示例(只显示重要的改动):


注意:如果将 s.cgi 改名,相应的模板也需要改名。例如 cgi 改名为 search.cgi,则相应的模板文件为 search.htm。


<!–top–>;
<HTML>;
<HEAD>;
  <META http-equiv="Content-Type" content="text/html; charset=gb2312">;  
  <LINK REL="STYLESHEET" TYPE="text/css" HREF="/inc/css/main.css"/>;
<title>;ASPseek: $Q</TITLE>;
</HEAD>;
<BODY BGCOLOR="#FFFFFF">;
  <SCRIPT language= "javascript" src="/inc/jscript/header.js" type=text/javascript>;</script>;  

<FORM METHOD=GET ACTION="$A">;
<TABLE width="100%" align="center" valign="center">;
<TR>;
  <TD VALIGN=bottom>;<IMG SRC="/img/aspseek-big.png" WIDTH="168" HEIGHT="66" ALT="ASPseek" BORDER="0" ALIGN="left" HSPACE="0">;</TD>;
  <TD VALIGN=center ALIGN=center width="*">;
   <INPUT TYPE="hidden" NAME="cs" VALUE="gb2312">;  
   搜索
   <INPUT TYPE="text" NAME="q" SIZE=30 VALUE="">;
   <INPUT TYPE="submit" VALUE="查询知识库">;
  </TD>;
  <TD width="100">;
  </TD>;
</TR>;
</TABLE>;
</FORM>;

… …
… …

<center>;
<script language= "javascript" src="/inc/jscript/footer.js" type=text/javascript>;</script>;
<script language= "javascript">; write_footer("Template: $Id: searchengine.xml,v 1.1 2004/02/03 05:24:10 jiangxin Exp $"); </script>;
</center>;

<DIV ALIGN=right>;
<A HREF="http://www.aspseek.org/">;<IMG SRC="http://www.aspseek.com/i/pow_aseek.png" WIDTH=88 HEIGHT=31 BORDER=0 ALT="Free search engine software: ASPseek $AV">;</A>;
</BODY>;
</HTML>;
<!–/bottom–>;




将cgi查询的输出界面(HTML)的语言编码设置为中文

引用外部的样式表文件,这样可以根据需要改变查询界面而尽量少的修改模板文件。一个简单的样式表示例:p {font-size:9pt}
h1 {font-size:20pt;line-height:130%;font-weight:"bold";align:"center";}
td,li,select,input {font-size:9pt}
.sect1 {font-size:9pt;line-height:150%;color:#333333;background-color:#E1E1E1;font-weight:bolder;}
.datetime {font-size:9pt;color="red"}
.star  {font-size:9pt;color="red"}
.gray {font-size:9pt;color="gray"}
.cvskw {font-size:9pt}
.footer           {font-size:9pt;font-weight:bolder}
.footer A:link    {font-size:9pt;font-weight:bolder}
.footer A:active  {font-size:9pt;font-weight:bolder}
.footer A:visited {font-size:9pt;font-weight:bolder}
.footer A:hover   {font-size:9pt;font-weight:bolder}
A:link {color: #000000;}
A:visited {color: #000000;}
A:active,A:hover {color : #000000}
HTML BODY { LINE-HEIGHT: 1.2; MARGIN: 0 0 2em 0 }
UL { list-style-image: url("/images/dot.gif") }

.em           {font-size:"9pt";color="red";font-weight:"bolder";font-style:"normal";letter-spacing:"2px";}
.em A:link    {color: "red";letter-spacing:"4px";}
.em A:active  {color: "red";letter-spacing:"4px";}
.em A:visited {color: "red";letter-spacing:"4px";}
.em A:hover   {color: "red";letter-spacing:"4px";font-size:"12pt";}



引用外部 javascript,显示头部信息,避免过多对该模板的修改。一个 header.js 示例:<!–
document.write("      <table width=750 border=0 cellspacing=0 cellpadding=0>;");
document.write("        <tr valign=bottom>;");
document.write("              <td width=’*'>;");
document.write("                <table width=’100%’ height=50 border=0 cellspacing=0 cellpadding=0>;");
document.write("            <tr>;");
document.write("              <td align=’center’ valign=’center’>;<h1>;<A HREF=’/'>;Johnson’s Homepage</A>;</h1>;</td>;");
document.write("            </tr>;");
document.write("                </table>;");
document.write("        </td>;</tr>;");
document.write("      </table>;");
//–>;



通过设置cgi的cs字段,用以支持中文查询

q 是真正的查询字段。看看 GOOGLE 的查询网页,看看是不是非常类似?

引用外部 javascript,显示脚注信息,避免过多对该模板的修改。一个 footer.js 示例:<!–
function write_footer($str)
{
        document.write("      <TABLE align=’center’ border=’0′ cellpadding=’0′ cellspacing=’0′ width=’750′>;");
        document.write("        <TR>;");
        document.write("          <td align=center>;");
        document.write("          <hr>;");
        if ($str)
                document.write("<font class=’cvskw’>;" + $str + "</font>;<br>;");
        document.write("          <font class=’footer’>;CopyLeft 2003, <a href=’mailto:johnson.AT.worldhello.net’>;Johnson</a>;</font>;<br>;");
        document.write("          </td>;");
        document.write("        </TR>;");
        document.write("      </TABLE>;");
}
//–>;


2.5. ASPseek对中文的支持
中文、日文、韩文等多字节文字不同于英文等单字节语言,是多字节语言。我们都知道英文是依靠空格和标点符号将单词分割开,搜索引擎只要依据空格和标点就可以分割出词表。对一些检索意义不大的单词,则将这些词列在所谓 stopwords 词表(又称为 badwords中),如: "a, an, and, the, …",避免因为对这些词建立检索而耗费过多的资源。这些 stopwords 保存在目录 /usr/local/aspseek/etc/stopwords/ 中。

而中文则不能造此办理,没有空格开区分词和词组,因此需要建立相应的词表。这些词表保存在目录 /usr/local/aspseek/etc/tables/ 中。

为能够对中文文档进行检索,需要检查是否在配置文件 aspseek.conf 和 searchd.conf 配置了 "CharsetTableU2" 和 "Dictionary2"选项。这两个选项是在配置文件 ucharset.conf 中定义的,用语句 "Include ucharset.conf" 包含入配置文件 aspseek.conf 和 searchd.conf。 ucharset.conf 中"CharsetTableU2" 和 "Dictionary2"的配置如下:

########################################################################
# Unicode charset definition for multibyte charsets
# (please comment all not needed charsets):
# CharsetTableU2 <charset>; <lang>; <table>; [<lang_map>;]
#
CharsetTableU2 big5 ch tables/big5.txt
CharsetTableU2 gb2312 ch tables/gb2312.txt

########################################################################
# Dictionary for tokenizing of text in Chinese, Japanese and Korean languages
# Dictionary2 <lang>; <file>; [<file encoding>;]
# If file encoding is omitted, then file is assumed to be in unicode
# Must be set after encoding definition (CharsetTableU2)
# <lang>; parameter must match <lang>; in CharsetTableU2 directive.
Dictionary2 ch tables/chinese.txt big5

PHP 开发工具

看到一篇介绍PHP开发工具的比较好的文章,转之
作者 Harry Fuecks  来源 sitepoint.com  2004-06-21

PHP开发工具资源
 
本文摘录自Harry Fuecks在sitepoint的一篇帖子,Easy按照软件开发的流程简单的整理了一下,希望大家能有所收获。
 
设计工具
 
UML 和相关设计工具
- Argo UML
UML绘图工具,支持PHP stub生成。 (commercial spin off is Posideon) –Java编写。
- Umbrello UML
UML绘图工具,支持PHP stub生成。 需要Unix / KDE。
- Dia
支持UML 的绘图工具 -使用AutoDia 生成PHP。
- XMI 2 PHP
从XMI文档生成PHP代码,用XML描述UML的一种形式。
 
编码工具
 
推荐的 IDE / 编辑器

- PHP Eclipse
Eclipse IDE的PHP插件
- PHP Edit
可能是Windows下最好的免费IDE了
- JEdit
支持PHP的IDE (plus loads more)。Java编写,所以平台独立。
- Jext
JEdit的孪生兄弟。
- gPHPEdit
Gnome / Linux下最好的(?)PHP编辑器。
- SciTE
跨平台编辑器
- PHP Mode for Emacs
Unix EMACS IDE的PHP Mode
 
测试工具
 
Debuggers Profilers
- XDebug (推荐)
出色的 debugger 和profiler 扩展
- Advanced PHP Debugger
George Schlossnagle 的debugger
- PEAR::Benchmark
用PHP写的Benchmarking 和 profiling 工具
- DBG
PHP Debugger
单元测试框架
- Simple Test (推荐)
关于mock objects出色的文档和支持
- PEAR::PHPUnit
 
部署工具
 
构建/部署工具
- PEAR Package Manager (推荐)
允许你安装PEAR packages (通过网络) ,还能将你的代码打包用于安装。在命令行下执行http://pear.php.net/go-pear 运行。PHP编写。
- PEAR::PackageFileManager
自动生成Package Manager使用的package.xml 文件。PHP编写。
- Phing
PHP的构建工具,相当于Apache ANT。在构建大型项目时值得研究。 PHP编写。
- ZZ/OSS Installer
基于PHP的安装向导,用于专业的PHP模块化应用的发布。
 
加速器
- Turck MMCache (强烈推荐)
集成OPCODE Cache, script encoder, profiler 和动态内容缓存(read persistence)于一体 。提供Windows版本。
- PHP Accelerator (推荐)
OPCODE Cache
 
管理工具
 
文档生成工具

- phpDocumentor (推荐)
用源代码注释中生成API文档(像Javadoc)。输出可以被“模版化”,还支持 HTML, PDF和 CHM格式。PHP编写。
- PHPXref (推荐)
创建源代码的“交叉引用”,使你能够看见一个变量/方法/函数在哪里声明以及在哪里被引用。Perl编写。
 
版本控制工具(此部分为Easy添加)
CVS
开放源代码的版本控制系统,很多大型项目,包括PHP本身,都用它管理代码。

CVSNT
用于Windows NT(XP也可以)的CVS服务器程序。