2013年12月

这篇指南介绍了怎么样在 RedHat、 CentOS、 FedoraDebianUbuntuLinux MintXubuntu 等这些系统中安装 Teamviewer 9Teamviewer 是一款流行的应用软件,用于远程辅助、桌面共享、计算机之间互传文件、网络会议及在线会议等方面,并且它是一款专业应用程序。而且,个人用户可以免费使用。Teamviewer可以运行在 Windows、Linux、Mac OS、Android 系统以及 iPhone 设备上,它使用它自己集成的 WINE 环境来运行,所以我们用的时候不需单独安装 WINE 程序了。 Teamviewer 并不是原生的 Linux 应用程序。

最新的稳定版本 TeamViewer 9 近期已经发布了,有了些新的功能和性能的改进。在 TeamViewer 9 中增加的一些新功能特性,其要点如下:

Windows、Linux 和 Mac 系统下的功能特性

  • 在不同的选项卡中打开多个链接
  • 支持局域网唤醒
  • 支持为 TeamViewer 帐户添加双因子身份验证
  • 支持 Windows 8.1 和 Mac OS X Mavericks 系统
  • 能保存自定义模块,如uickSupport、QuickJoin等等
  • 集成了应用程序编程接口(API)
  • 更强的 Teamviewer 账户安全
  • 通过桌面快捷方式快速连接
  • 可视化通知信息
  • 不同计算机间复制和粘贴文件和文本
  • 不同计算机间的初始化文件传输
  • 视频传输更快

在 RedHat、 CentOS、 Fedora 上安装 Teamviewer 9

你可以在 teamviewer\_linux.rpm 上下载到基于 Linux 发行版本的 rpm 包。

# wget http://www.teamviewer.com/download/teamviewer_linux.rpm 

然后开始安装。进入你的下载包所在的目录,执行如下的 yum 命令来安装,它将会自动安装需要的依赖包。

# yum install teamviewer_linux.rpm

如果出现公钥缺失错误,你可以用如下命令来下载,并导入之。

# wget http://www.teamviewer.com/link/?url=354858
# rpm --import TeamViewer_Linux_PubKey.asc

在导入公钥后,请再一次运行 “ yum install ” 命令来安装 Teamviewer rpm 包。

要启动运行 Teamviewer 应用,从终端中运行如下命令。

# teamviewer

Teamviewer 应用程序正运行在我的 Fedora 18 系统上。

Running TeamViewer in Fedora 18

Fedora 18 系统上运行的 TeamViewer

在 Ubuntu, Linux Mint, Xubuntu 上安装 Teamviewer 9

你可以在 teamviewer linux .deb 上下载到基于 32-位 系统或 64-位 系统的 teamviewer 安装包,或者你可以用如下所示的 wget 命令来下载安装包。

## 32 位系统 ##
$ sudo wget http://www.teamviewer.com/download/teamviewer_linux.deb

## 64 位系统 ##
$ sudo wget http://www.teamviewer.com/download/teamviewer_linux_x64.deb

一旦下载好,就可以进入你下载的 Teamviewer 包所在的目录,然后运行如下命令来安装。

## 32 位系统 ##
$ sudo dpkg -i teamviewer_linux.deb

## 64 位系统 ##
$ sudo dpkg -i teamviewer_linux_x64.deb

如果出现有缺失依赖包错误这种情况,请使用如下命令来安装这些依赖包。

sudo apt-get install -f

一旦全部都安装成功,在 Ubuntu 系统中要启动 Teamviewer,打开 Dash 主窗口,输入 teamviewer ,然后点击出现的 teamviewer 图标,程序就启动运行了。

Running TeamViewer in Ubuntu 13.10

Ubuntu 13.10 系统上运行的 TeamViewer

Teamviewer 应用程序正运行在我的 Ubuntu 13.10 系统上。

TeamViewer 9 Under Ubuntu 13.10

在 Ubuntu 13.10 下的 TeamViewer 9

要在 Linux Mint 上启动,进入 菜单 >> 网络 >> Teamviewer, 并点击 接受许可协议 来启动运行 TeamViewer。

Teamviewer 应用程序正运行在我的 Linux Mint 15 系统上。

Running TeamViewer in Linux Mint 15

Linux Mint 15 系统上运行的 TeamViewer


via: http://www.tecmint.com/how-to-install-teamviewer-on-linux-distributions/

译者:runningwater 校对:Caroline

本文由 LCTT 原创翻译,Linux中国 荣誉推出

Novell的网络协议IPX通常用于Windows系统和NetWare服务器(The IPX protocol)。IPX代表网间分组交换(Internetwork Packet Exchange)。这是一个网络层协议通常与传输层的SPX协议同时使用。

为了使NetWare服务器在服务的网络中有相同的IPX地址,启用下一个特性(IPX: Full internal IPX network)。不然,每个网络都会看到服务器一个不同的IPX地址。

注意:IPX协议使用IPX寻址,而不是IP寻址。IP地址不是计算机网络中唯一的网络地址。

对于在Apple网络中的Linux系统,需要启用Appletalk(Appletalk protocol support)。苹果计算机和苹果打印机通常使用Appletalk在网络间通信。Appletalk不需要一台中心路由器/服务器并且网络系统是即插即用的。

在Appletalk网络中Linux系统需要使用IP需要"Appletalk interfaces support"(AppleTalk接口支持)。

下一个特性允许用户在Appletalk中使用IP隧道(Appletalk-IP driver support)。

接下来,这个特性允许IP包被封装成Apppletalk帧(IP to Appletalk-IP Encapsulation support)。在网络中,帧是一种标记包的开始和结束的特殊序列位。这个特性会将IP包放在Appletalk包内部。

这个特性允许为先前的特性解包(Appletalk-IP to IP Decapsulation support)。解包器会将IP包从Appletalk包中拿出。

这是另外一个协议层称为"X.25" (CCITT X.25 Packet Layer)。这个协议层通常用于非常大的网络,就像国家公网。许多银行使用这个在他们的扩展网络系统里。X25(拼成"X25"或"X.25")网络拥有将进入数据包打包的包分组交换机。X25正在被更简单的IP协议代替。X25是一个不如TCP/IP有效率的旧协议,但是一些公司发现它在大型、复杂的网络中很有用。

LAPB是用于X.25的数据链路层(LAPB Data Link Driver)。如果上面的启用了,那么这也应该同时启用。LAPB代表的是"Link Access Procedure Balanced"(链路访问过程平衡)。LAPB同样也用于以太网和X.21网卡中(这里没有打错)。X.21是用于物理层(硬件),X.25用于网络层。LPAB会检查错误并确保包被放回正确的序列中。

Nokia调制解调器使用的电话网络协议通常称作"PhoNet"(Phonet protocols family)。Linux计算机远程控制Nokia电话机需要这个特性。

下一个网络通常是用于不同自动设备间的小型无线连接(IEEE Std 802.15.4 Low-Rate Wireless Personal Area Networks support)。802.15.4是一种需要很少电量的简单低数据率协议。这个无线协议最大可扩展到10米。这在通过无线网络连接机器人传感器时是很有用的。任何不该有线缆的机械可能都会从这个代替了绳子的本地无线网络中获益。

如果启用了上面的特性,那么最好明智地启用这个IPv6 压缩特性(6lowpan support over IEEE 802.15.4)。

支持物理层 IEEE 802.15.4协议的SoftMac设备可以启用这个特性(Generic IEEE 802.15.4 Soft Networking Stack (mac802154))。

当有许多包需要传输时,内核必须决定先发送哪一个(它们不能一次全部发送),所以这个特性帮助内核区分包的优先级(QoS and/or fair queuing)。如果不启用这个,那么内核会使用"first come, first serve approach"("谁先到,谁先服务")。这可能意味着紧急的网络消息需要等待才能轮到它们传输。

在有数据中心服务器的网络中,这个特性强烈建议启用(Data Center Bridging support)。这个特性增强了以太网对数据中心网络的连接。

DNS查询可以在下一个选项中启用(DNS Resolver support)。大多数存储DNS缓存的系统允许计算机无需DNS服务器的辅助下执行DNS查询。

接下来是另一个用于多跳专用网状网络(B.A.T.M.A.N. Advanced Meshing Protocol)。"B.A.T.M.A.N."代表"better approach to mobile ad-hoc networking"(更好接入移动专用网络)。这个工作与有线和无线网络。专用网络没有中心像路由器这类中心设置。每台网络上的设备就像个一台路由器。网状网络是一个简单的概念。每个节点必须路由发送给它的数据。在这个网状网络中,每台计算机连接到全部或几乎全部其他网络设备。当这样的网络画在纸上成为一张地图时,这个网络看上去就像一张网。

当许多网状节点连接到相同的LAN和网时,一些网络信号可能会回环(Bridge Loop Avoidance)(避免桥回环)。这个特性可以避免此类的回环。这些回环可能永远不会结束或者降低性能。避免这样的回环被称为"Bridge Loop Avoidance (BLA)"。

分布式ARP表(Distributed ARP Tables (DAT))被用于增强ARP在稀疏无线网状网络的可靠性(Distributed ARP Table)。

BATMAN协议有些开发者需要用到的调式特性(B.A.T.M.A.N. Debugging)。对于任何调试特性,通常最好禁用它来节省空间以及得到一个更好优化后的内核。

虚拟化环境可以从"Open vSwitch"中得益。这是一个多层以太网交换机。Open vSwitch支持大量的协议。

虚拟机、hypervisor、主机之间的网络连接需要"virtual socket protocol"。这个类似于TCP/IP.这些套接字就像其他网络套接字,但是它们针对虚拟机。这允许客户机系统拥有一个与主机的网络连接。

这是一个可以管理网络优先级的cgroup子系统(Network priority cgroup)。这允许控制组(cgroup)根据发送应用设置网络流量优先级。

BPF过滤器由解释器处理,但是内核可以执行原生BPF过滤通过这个(enable BPF Just In Time compiler)。BPF代表的是"Berkeley Packet Filter"(伯克利报过滤器)。这允许计算机系统支持原生链路层包。

下面,我们有两个网络测试工具。第一个是"Packet Generator"(包生成器),这用于测试网络时注射数据包(制造空包)。第二个,允许设置一个警报系统,当数据包丢失时警告用户/系统(Network packet drop alerting service)。

Linux内核可以用于无线电系统或者远程控制它们。"Amateur Radio AX.25 Level 2 protocol"用于计算机通过无线电通信。这个无线电协议可以在其他许多的协议中支持TCP/IP。

为了放置在AX.25网络中冲突,启用DAMA(AX.25 DAMA Slave support)。至今为止,Linux还不能作为DAMA的服务器,但是可以作为DAMA的客户端。DAMA代表"Demand Assigned Multiple Access"(按需分配多址访问)。DAMA分配网络流量到特定的信道中去。

NET/ROM是AX.25的路由层。(Amateur Radio NET/ROM protocol)。

NET/ROM的一个替代是"Packet Layer Protocol (PLP)"(包层协议),它可以运行在AX.25的顶端(Amateur Radio X.25 PLP (Rose))。

控制器局域网络(Controller Area Network (CAN))总线需要这个驱动(CAN bus subsystem support)。CAN总线是一种用于不同目的的串行协议。

使用这个特性(Raw CAN Protocol (raw access with CAN-ID filtering)),CAN总线可以通过BSD套接字API访问

内核中有用于CAN协议的广播管理(Broadcast Manager CAN Protocol (with content filtering))。这个管理提供了很多控制,包括内容过滤。

为了让Linux盒子成为一个CAN路由器和/或者网关,需要这个特性(CAN Gateway/Router (with netlink configuration))。

注意:网关是两个或者更多网络的接口设备,它提供不同的协议。一个简单的定义可以是"网关是一个协议转换器。"

注意:路由器转发网络流量和连接使用相同协议网络。

如果启用了(一些选项),Linux内核可以支持很多CAN设备(主要是控制器)和接口。所有的CAN驱动都是对于这些设备的不同品牌和型号。在配置工具中,它们有以下这些标题。

  • Virtual Local CAN Interface (vcan)
  • Serial / USB serial CAN Adaptors (slcan)
  • Platform CAN drivers with Netlink support
  • Enable LED triggers for Netlink based drivers
  • Microchip MCP251x SPI CAN controllers
  • Janz VMOD-ICAN3 Intelligent CAN controller
  • Intel EG20T PCH CAN controller
  • Philips/NXP SJA1000 devices
  • Bosch CCAN/DCAN devices
  • Bosch CC770 and Intel AN82527 devices
  • CAN USB interfaces
  • Softing Gmbh CAN generic support
  • Softing Gmbh CAN pcmcia cards

像Linux中的其他许多特性,CAN设备同样可以启用调试能力(CAN devices debugging messages)。再说一次,记住你内核的目的,你需要调试还是需要性能?

Linux内核同样支持红外线信号协议IrDA (infrared) subsystem support)。IrDa代表的是 "Infrared Data Associations"(红外数据协会);这是红外信号的标准。

许多人如今想要蓝牙特性(Bluetooth subsystem support)。

RxRPC会话套接字可以启用(RxRPC session sockets)。这些套接字使用RxRPC协议运载网络连接。RxRPC运行于UDP的顶部。

如果启用的话,Linux内核可以支持"RxRPC dynamic debugging"(RxRPC 动态调试)。

RxRPC拥有kerberos 4和AFS kaserver安全特性可以启用(RxRPC Kerberos security)。Kerberos是一种每个网络设备在传输任何数据前都被需要证明彼此的身份的验证协议。

对于电脑的无线网络设备像Wifi,配置工具需要启用无线局域网(802.11)设备(cfg80211 - wireless configuration API)。cfg80211代表"Configuration 802.11"(配置 802.11)。802.11是一种无线规范。

"nl80211 testmode command"是用于校准并且/或验证的实用工具,它无线设备芯片上执行这些任务。

下一个设置允许用户"enable developer warnings"(启用开发者警告)对于cfg80211设备。

下面,"cfg80211 regulatory debugging"(cfg80211调控调试)可以启用。

下面的设定是"cfg80211 certification onus"(cfg80211证书义务)。

应该为cfg80211兼容设备启用省电特性(enable powersave by default)。

cfg80211支持debugfs入口(cfg80211 DebugFS entries)。

无线设备有它们遵守的调整规则;这些被存储在数据库中(use statically compiled regulatory rules database)(使用静态编译的调整规则数据库)

一些使用基于cfg80211的驱动扩展可能需要使用一个老的用户空间。这个特性允许这个行为(cfg80211 wireless extensions compatibility)(cfg80211 无线扩展兼容)。

lib80211可以提供调试特性(lib80211 debugging messages)。

独立于硬件的IEEE 802.11标准可以启用(Generic IEEE 802.11 Networking Stack (mac80211))。mac80211是一种用于编写softMAC无线设备驱动的框架。SoftMac允许很好地控制和配置设备。

下一个特性允许mac80211使用PID控制器管理TX(发送)速率(PID controller based rate control algorithm)(PID控制器基于速率控制算法)。TX单位是BFS(Bits per minute)(位/秒)。特别地,这个特性是用于控制数据流速率的算法。

另外一个相同特性的算法叫做"Minstrel"。这是一个比TX速率管理算法更精确和有效的算法。

Minstrel同样支持802.11n(Minstrel 802.11n support)。

由于有两种TX速率控制算法,但只能使用一种。所哟必须设备一个默认的(Default rate control algorithm (Minstrel))。通常地,最好选择Minstrel作为默认。

802.11s网状网络草案可以在内核中启用(Enable mac80211 mesh networking (pre-802.11s) support)。802.11s草案是网状网络的无线标准。

对于支持这个特性的设备,对于不同包流量时间的LED除法器特性可以启用(Enable LED triggers)。在我的以太网设备商上,当端口是活跃时LED灯会点亮。这些驱动可以是这些LED在包流量时间下工作。

mac80211同样支持debugfs特性(Export mac80211 internals in DebugFS)。

这是一个独立于典型日志系统收集mac80211调试信息的特性(Trace all mac80211 debug messages)。

这是另外一组mac80211调试特性,但是这些使用的是典型日志系统(Select mac80211 debugging features --->)。在这个菜单,选择你需要的调试特性。

在下一篇文章中,我们还有更多的需要配置。


via: http://www.linux.org/threads/the-linux-kernel-configuring-the-kernel-part-9.4568/

译者:geekpi 校对:wxy

本文由 LCTT 原创翻译,Linux中国 荣誉推出

UNIGINE,是一个实时的 3D 引擎,它能够在所有主流的平台上运行,包括 Linux,并刚刚升级到新的版本,带给了我们一些重要的新特性。

Unigine 引擎正是由 Unigine 公司开发的, 同时这公司还开发了 Heaven DX11 基准测试软件。 这公司开发的技术总是越来越好,并且随着他们最近在 Linux 平台上的扩展,我们真的很高兴看到这引擎在最近时间作出的重大的更新。

在 UNIGINE 引擎最近作出的更新中,最大的更新是通用图像生成器接口 (Common Image Generator Interface/CIGI) 协议。

据引擎的开发者说,这个接口在模拟行业中,是一种用于主机设备与图像生成器 (IG) 之间通信的标准方法来的。

新款 UNIGINE 引擎的亮点

  • 在笛卡尔坐标系中增加了对 WGS84,ECF 和 NED 坐标系的支持(这会帮助开发者更好地在用 Unigine 开发的项目中使用实时的 GIS 数据);
  • 实施了游戏框架,这样使得游戏更加容易地创建,同时这种特性包括实体与节点的自动链接、层次与世界的自动链接、实体对象管理、贯穿所有层次的游戏全局上下文、事件处理系统、最佳的实体更新等等。
  • 增加渲染时帧率的稳定性。
  • 两个新的选项,2D 噪音和 3D 噪音(编辑器中的状态选项卡),已被添加到 meshleafbase 材质中。
  • 一个新的参数,遮挡屏蔽,已经被添加到所有的材质中。
  • 密杂草丛的高度现已实现同步。
  • 修复了在渲染非 Flash 闪屏时崩溃的漏洞。

所有平台的完整新特性列表,可以在官方的公告中找到。.

要记住 UNIGINE 引擎只针对商业企业,并不向广大用户提供试用版。


via: http://news.softpedia.com/news/UNIGINE-Is-Probably-the-Best-Gaming-Engine-on-Linux-404484.shtml

译者:hyaocuk 校对:wxy

本文由 LCTT 原创翻译,Linux中国 荣誉推出

我日常使用Linux shell(Bash),但是我经常忘记一些有用的命令或者shell技巧。是的,我能记住一些命令,但是肯定不会只在特定的任务上使用一次,所以我就开始在我的Dropbox账号里用文本文件写下这些Linux shell的小技巧,现在我决定共享它给你。这个表我以后还会更新。记住,这里的一些贴士需要在你的Linux发行版上安装额外的软件。

在bash中检查远程端口是否打开:

echo >/dev/tcp/8.8.8.8/53 && echo "open"

将进程挂起:

Ctrl + z 

将进程移到前台:

fg

(译注,挂起的进程是不执行的,如果希望在后台执行,可以使用bg命令,并且指定通过jobs命令获得的任务号。)

生成随机16进制数字,n是字符的数量:

openssl rand -hex n

在当前shell中执行一个文件中的命令(译注:这个文件不是一个bash脚本,比如.bashrc、bash\_profile等):

source /home/user/file.name

提取字符串的前5个字符:

${variable:0:5}

打开SSH调试模式(译注:当你遇到SSH连接问题时很有用):

ssh -vvv user@ip_address

使用pem key的进行SSH连接:

ssh user@ip_address -i key.pem

用wget获取完整目录列表到本地目录:

wget -r --no-parent --reject "index.html*" http://hostname/ -P /home/user/dirs

同时创建多个目录:

mkdir -p /home/user/{test,test1,test2}

以树状列出进程及子进程:

ps axwef

创建war文件:

jar -cvf name.war file

测试磁盘写速度:

dd if=/dev/zero of=/tmp/output.img bs=8k count=256k conv=fdatasync; rm -rf /tmp/output.img

测试磁盘读速度:

hdparm -Tt /dev/sda

获取文本的md5值:

echo -n "text" | md5sum

检测xml语法:

xmllint --noout file.xml

将tar.gz文件解压到指定目录:

tar zxvf package.tar.gz -C new_dir

用curl获取HTTP头:

curl -I http://www.example.com

修改一些文件或目录的时间戳 (格式为:YYMMDDhhmm):

touch -t 0712250000 file

使用wget从ftp下载:

wget -m ftp://username:password@hostname

生成随机密码 (本例中16位字符长):

LANG=c < /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-16};echo;

快速创建一个文件的备份(扩展名是.bkp):

cp some_file_name{,.bkp}

访问Windows共享:

smbclient -U "DOMAIN\user" //dc.domain.com/share/test/dir

运行history中的命令 (这里在history中的第100个):

!100

unzip到目录中:

unzip package_name.zip -d dir_name

输入多行文字 (按 CTRL + d 退出):

cat > test.txt

创建空白的文件或者清空已存在的文件:

> test.txt

从Ubuntu NTP服务器上更新日期:

ntpdate ntp.ubuntu.com

netstat 显示所有IPv4的TCP监听的端口:

netstat -lnt4 | awk '{print $4}' | cut -f2 -d: | grep -o '[0-9]*'

将qcow2的镜像转化成raw格式:

qemu-img convert -f qcow2 -O raw precise-server-cloudimg-amd64-disk1.img \
                                 precise-server-cloudimg-amd64-disk1.raw

重复运行命令并显示它的输出 (默认2秒重复一次):

watch ps -ef

显示所有用户:

getent passwd

以读写模式挂载根文件系统:

mount -o remount,rw /

挂载目录 (适合于符号链接不能工作的情况下):

mount --bind /source /destination

发送DNS动态更新给DNS:

nsupdate <

递归grep所有目录

grep -r "some_text" /path/to/dir

列出10个最大的系统中已打开的文件:

lsof / | awk '{ if($7 > 1048576) print $7/1048576 "MB "$9 }' | sort -n -u | tail

以MB显示空余内存:

free -m | grep cache | awk '/[0-9]/{ print $4" MB" }'

打开vim并跳转到文件最后:

vim + some_file_name

git clone特定branch (本例是master分支):

git clone [email protected]:name/app.git -b master

git切换到另外一个branch (本例是develop分支):

git checkout develop

git删除一个branch(本例是myfeature):

git branch -d myfeature

Git删除一个远程branch:

git push origin :branchName

Git push 新的branch到远程:

git push -u origin mynewfeature

打印history中最后的cat命令

!cat:p

运行history中的最后的cat命令:

!cat

找出在/home/user中的所有空子目录:

find /home/user -maxdepth 1 -type d -empty

得到test.txt中50到60行的文本:

< test.txt sed -n '50,60p'

以sudo权限重新运行上一个执行的命令 (如果是: mkdir /root/test, 下面会运行: sudo mkdir /root/test)(译注:当你执行一个命令忘记sudo时,可以这样重新执行,而不必再把完整命令敲一遍):

sudo !!

创建临时RAM文件系统 - ramdisk (请先创建 /tmpram 目录):

mount -t tmpfs tmpfs /tmpram -o size=512m

Grep完整的单词(译注:而不是其它单词的一部分):

grep -w "name" test.txt

提升权限后在一个文件后追加文本:

echo "some text" | sudo tee -a /path/file

列出所有支持的kill信号:

kill -l

生成随机密码 (本例中16个字符长):

openssl rand -base64 16

在bash历史中不记录最后的会话:

kill -9 $$

扫描网络来找出开放的端口:

nmap -p 8081 172.20.0.0/16

设置git email:

git config --global user.email "[email protected]"

如果你有未提交的commit,与master同步:

git pull --rebase origin master

将文件名中含有txt的所有文件移动到/home/user:

find -iname "*txt*" -exec mv -v {} /home/user \;

按行将两个文件中的对应行合并显示:

paste test.txt test1.txt

shell中的进度条:

pv data.log

用netcat发送数据给服务器:

echo "hosts.sampleHost 10 `date +%s`" | nc 192.168.200.2 3000

转换tab为空格:

expand test.txt > test1.txt

跳过bash历史:

<<空格>>cmd

回到之前的工作目录:

cd -

切割大的tar.gz文件为几个文件 (每个100MB),并还原:

split –b 100m /path/to/large/archive /path/to/output/files
cat files* > archive

用curl获取HTTP状态值:

curl -sL -w "%{http_code}\\n" www.example.com -o /dev/null

当 Ctrl + c 没用时:

Ctrl + \

获取文件所有者:

stat -c %U file.txt

列出块设备:

lsblk -f

找出文件中带有末尾空格的文件:

find . -type f -exec egrep -l " +$" "{}" \;

找出用tab缩进的文件:

find . -type f -exec egrep -l $'\t' "{}" \;

用"="打印水平行

printf '%100s\n' | tr ' ' =

更新: 2013年11月25日


via: http://www.techbar.me/linux-shell-tips/

译者:geekpi 校对:wxy

本文由 LCTT 原创翻译,Linux中国 荣誉推出

开篇

学习内核,每个人都有自己的学习方法,仁者见仁智者见智。以下是我在学习过程中总结出来的东西,对自身来说,我认为比较有效率,拿出来跟大家交流一下。​

内核学习,一偏之见;疏漏难免,恳请指正。

为什么写这篇博客

刚开始学内核的时候,不要执着于一个方面,不要专注于一个子系统就一头扎到实际的代码行中去,因为这样的话,牵涉的面会很广,会碰到很多困难,容易产生挫败感,一个函数体中(假设刚开始的时候正在学习某个方面的某个具体的功能函数)很可能掺杂着其他各个子系统方面设计理念(多是大量相关的数据结构或者全局变量,用于支撑该子系统的管理工作)下相应的代码实现,这个时候看到这些东西,纷繁芜杂,是没有头绪而且很不理解的,会产生很多很多的疑问,(这个时候如果对这些疑问纠缠不清,刨根问底,那么事实上就是在学习当前子系统的过程中频繁的去涉足其他子系统,这时候注意力就分散了),而事实上等了解了各个子系统后再回头看这些东西的话,就简单多了,而且思路也会比较清晰。所以,要避免 “只见树木,不见森林”,不要急于深入到底层代码中去,不要过早研究底层代码。

我在大二的时候刚开始接触内核,就犯了这个错误,一头扎到内存管理里头,去看非常底层的实现代码,虽然也是建立在内存管理的设计思想的基础上,但是相对来说,比较孤立,因为此时并没有学习其它子系统,应该说无论是视野还是思想,都比较狭隘,所以代码中牵涉到的其它子系统的实现我都直接跳过了,这一点还算聪明,当然也是迫不得已的。

我的学习方法

刚开始,我认为主要的问题在于你知道不知道,而不是理解不理解,某个子系统的实现采用了某种策略、方法,而你在学习中需要做的就是知道有这么一回事儿,然后才是理解所描述的策略或者方法。

根据自己的学习经验,刚开始学习内核的时候,我认为要做的是在自己的脑海中建立起内核的大体框架,理解各个子系统的设计理念和构建思想,这些理念和思想会从宏观上呈献给你清晰的脉络,就像一个去除了枝枝叶叶的大树的主干,一目了然;当然,肯定还会涉及到具体的实现方法、函数,但是此时接触到的函数或者方法位于内核实现的较高的层次,是主(要)函数,已经了解到这些函数,针对的是哪些设计思想,实现了什么样的功能,达成了什么样的目的,混个脸熟的说法在这儿也是成立的。至于该主函数所调用的其它的辅助性函数就等同于枝枝叶叶了,不必太早就去深究。此时,也就初步建立起了内核子系统框架和代码实现之间的关联,关联其实很简单,比如一看到某个函数名字,就想起这个函数是针对哪个子系统的,实现了什么功能。

我认为此时要看的就是LKD3,这本书算是泛泛而谈,主要就是从概念,设计,大的实现方法上描述各个子系统,而对于具体的相关的函数实现的代码讲解很少涉及(对比于ULK3,此书主要就是关于具体函数代码的具体实现的深入分析,当然,你也可以看,但是过早看这本书,会感觉很痛苦,很枯燥无味,基本上都是函数的实现),很少,但不是没有,这就很好,满足我们当前的需求,还避免我们过早深入到实际的代码中去。而且本书在一些重要的点上还给出了写程序时的注意事项,算是指导性建议。主要的子系统包括:内存管理,进程管理和调度,系统调用,中断和异常,内核同步,时间和定时器管理,虚拟文件系统,块I/O层,设备和模块。(这里的先后顺序其实就是LKD3的目录的顺序)。

我学习的时候是三本书交叉着看的,先看LKD3,专于一个子系统,主要就是了解设计的原理和思想,当然也会碰到对一些主要函数的介绍,但大多就是该函数基于前面介绍的思想和原理完成了什么样的功能,该书并没有就函数本身的实现进行深入剖析。然后再看ULK3和PLKA上看同样的子系统,但是并不仔细分析底层具体函数的代码,只是粗略地、不求甚解地看,甚至不看。因为,有些时候,在其中一本书的某个点上,卡壳了,不是很理解了,在另外的书上你可能就碰到对同一个问题的不同角度的描述,说不准哪句话就能让你豁然开朗,如醍醐灌顶。我经常碰到这种情况。

并不是说学习过程中对一些函数体的实现完全就忽略掉,只要自己想彻底了解其代码实现,没有谁会阻止你。我是在反复阅读过程中慢慢深入的。比如VFS中文件打开需要对路径进行分析,需要考虑的细节不少(.././之类的),但是其代码实现是很好理解的。再比如,CFS调度中根据shedule latency、队列中进程个数及其nice值(使用的是动态优先级)计算出分配给进程的时间片,没理由不看的,这个太重要了,而且也很有意思。

ULK3也会有设计原理与思想之类的概括性介绍,基本上都位于某个主题的开篇段落。但是更多的是对支持该原理和思想的主要函数实现的具体分析,同样在首段,一句话综述函数的功能,然后对函数的实现以1、2、3,或者a、b、c步骤的形式进行讲解。我只是有选择性的看,有时候对照着用source insight打开的源码,确认一下代码大体上确实是按书中所描述的步骤实现的,就当是增加感性认识。由于步骤中掺杂着各种针对不同实现目的安全性、有效性检查,如果不理解就先跳过。这并不妨碍你对函数体功能实现的整体把握。

PLKA介于LKD3和ULK3之间。我觉得PLKA的作者(看照片,真一德国帅小伙,技术如此了得)肯定看过ULK,无论他的本意还是有意,总之PLKA还是跟ULK有所不同,对函数的仔细讲解都做补充说明,去掉函数体中边边角角的情况,比如一些特殊情况的处理,有效性检查等,而不妨碍对整个函数体功能的理解,这些他都有所交代,做了声明;而且,就像LKD3一样,在某些点上也给出了指导性编程建议。作者们甚至对同一个主要函数的讲解的着重点都不一样。这样的话,对我们学习的人而言,有助于加深理解。另外,我认为很重要的一点就是PLKA针对的2.6.24的内核版本,而ULK是2.6.11,LKD3是2.6.34。在某些方面PLKA比较接近现代的实现。其实作者们之所以分别选择11或者24,都是因为在版本发行树中,这两个版本在某些方面都做了不小的变动,或者说是具有标志性的转折点(这些信息大多是在书中的引言部分介绍的,具体的细节我想不起来了)。

Intel V3,针对X86的CPU,本书自然是系统编程的权威。内核部分实现都可以在本书找到其根源。所以,在读以上三本书某个子系统的时候,不要忘记可以在V3中相应章节找到一些基础性支撑信息。

在读书过程中,会产生相当多的疑问,这一点是确信无疑的。 大到搞不明白一个设计思想,小到不理解某行代码的用途。各个方面,各种疑问,你完全可以把不理解的地方都记录下来(不过,我并没有这么做,没有把疑问全部记下来,只标记了很少一部分我认为很关键的几个问题),专门写到一张纸上,不对,一个本上,我确信会产生这么多的疑问,不然内核相关的论坛早就可以关闭了。其实,大部分的问题(其中很多问题都是你知道不知道有这么一回事的问题)都可以迎刃而解,只要你肯回头再看,书读百遍,其义自现。多看几遍,前前后后的联系明白个七七八八是没有问题的。我也这么做了,针对某些子系统也看了好几遍,切身体会。

当你按顺序学习这些子系统的时候,前面的章节很可能会引用后面的章节,就像PLKA的作者说的那样,完全没有向后引用是不可能的,他能做的只是尽量减少这种引用而又不损害你对当前问题的理解。不理解,没关系,跳过就行了。后面的章节同样会有向前章节的引用,不过这个问题就简单一些了 ,你可以再回头去看相应的介绍,当时你不太理解的东西,很可能这个时候就知道了它的设计的目的以及具体的应用。不求甚解只是暂时的。比如说,内核各个子系统之间的交互和引用在代码中的体现就是实现函数穿插调用,比如你在内存管理章节学习了的内存分配和释放的函数,而你是了解内存在先的,在学习驱动或者模块的时候就会碰到这些函数的调用,这样也就比较容易接受,不至于太过茫然;再比如,你了解了系统时间和定时器的管理,再回头看中断和异常中bottom half的调度实现,你对它的理解就会加深一层。

子系统进行管理工作需要大量的数据结构。子系统之间交互的一种方式就是各个子系统各自的主要数据结构通过指针成员相互引用。学习过程中,参考书上在讲解某个子系统的时候会对数据结构中主要成员的用途解释一下,但肯定不会覆盖全部(成员比较多的情况,例如task\_struct),对其它子系统基于某个功能实现的引用可能解释了,也可能没做解释,还可能说这个变量在何处会做进一步说明。所以,不要纠结于一个不理解的点上,暂且放过,回头还可以看的。之间的联系可以在对各个子系统都有所了解之后再建立起来。其实,我仍然在强调先理解概念和框架的重要性。

等我们完成了建立框架这一步,就可以选择一个比较感兴趣的子系统,比如驱动、网络,或者文件系统之类的。这个时候你再去深入了解底层代码实现,相较于一开始就钻研代码,更容易一些,而且碰到了不解之处,或者忘记了某个方面的实现,此时你完全可以找到相应的子系统,因为你知道在哪去找,查漏补缺,不仅完成了对当前函数的钻研,而且可以回顾、温习以前的内容,融会贯通的时机就在这里了。

《深入理解linux虚拟内存》(2.4内核版本),LDD3,《深入理解linux网络技术内幕》,几乎每一个子系统都需要一本书的容量去讲解,所以说,刚开始学习不宜对某个模块太过深入,等对各个子系统都有所了解了,再有针对性的去学习一个特定的子系统。这时候对其它系统的援引都可以让我们不再感到茫然、复杂,不知所云。

比如,LDD3中的以下所列章节:构造和运行模块,并发和竞态,时间、延迟及延缓操作,分配内存,中断处理等,都属于驱动开发的支撑性子系统,虽说本书对这些子系统都专门开辟一个章节进行讲解,但是详细程度怎么能比得上PLKA,ULK3,LKD3这三本书,看完这三本书,你会发现读LDD3这些章节的时候简直跟喝白开水一样,太随意了,因为LDD3的讲解比之LKD3更粗略。打好了基础,PCI、USB、TTY驱动,块设备驱动,网卡驱动,需要了解和学习的东西就比较有针对性了。这些子系统就属于通用子系统,了解之后,基于这些子系统的子系统的开发---驱动(需进一步针对硬件特性)和网络(需进一步理解各种协议)---相对而言,其学习难度大大降低,学习进度大大加快,学习效率大大提升。说着容易做来难。达到这样一种效果的前提就是:必须得静下心来,认真读书,要看得进去,PLKA,ULK3厚得都跟砖头块儿一样,令人望之生畏,如果没有兴趣,没有热情,没有毅力,无论如何都是不行,因为需要时间,需要很长时间。我并不是说必须打好了基础才可以进行驱动开发,只是说打好了基础的情况下进行开发会更轻松,更有效率,而且自己对内核代码的驾驭能力会更强大。这只是我个人见解,我自己的学习方式,仅供参考。

语言

PLKA是个德国人用德语写的,后来翻译成英文,又从英文翻译成中文,我在网上书店里没有找到它的纸质英文版,所以就买了中文版的。ULK3和LKD3都是英文版的。大牛们写的书,遣词造句真的是简洁,易懂,看原版对我们学习计算机编程的程序员来说完全不成问题,最好原汁原味。如果一本书确实翻译地很好,我们当然可以看中文版的,用母语进行学习,理解速度和学习进度当然是很快的,不作他想。看英文的时候不要脑子里想着把他翻译成中文,没必要。

API感想

“比起知道你所用技术的重要性,成为某一个特别领域的专家是不重要的。知道某一个具体API调用一点好处都没有,当你需要他的时候只要查询下就好了。”这句话源于我看到的一篇翻译过来的博客。我想强调的就是,这句话针应用型编程再合适不过,但是内核API就不完全如此。

内核相当复杂,学习起来很不容易,但是当你学习到一定程度,你会发现,如果自己打算写内核代码,到最后要关注的仍然是API接口,只不过这些API绝大部分是跨平台的,满足可移植性。内核黑客基本上已经标准化、文档化了这些接口,你所要做的只是调用而已。当然,在使用的时候,最好对可移植性这一话题在内核中的编码约定烂熟于心,这样才会写出可移植性的代码。就像应用程序一样,可以使用开发商提供的动态库API,或者使用开源API。同样是调用API,不同点在于使用内核API要比使用应用API了解的东西要多出许多。

当你了解了操作系统的实现---这些实现可都是对应用程序的基础性支撑啊---你再去写应用程序的时候,应用程序中用到的多线程,定时器,同步锁机制等等等等,使用共享库API的时候,联系到操作系统,从而把对该API的文档描述同自己所了解到的这些方面在内核中的相应支撑性实现结合起来进行考虑,这会指导你选择使用哪一个API接口,选出效率最高的实现方式。对系统编程颇有了解的话,对应用编程不无益处,甚至可以说是大有好处。

设计实现的本质,知道还是理解

操作系统是介于底层硬件和应用软件之间的接口,其各个子系统的实现很大程度上依赖于硬件特性。书上介绍这些子系统的设计和实现的时候,我们读过了,也就知道了,如果再深入考虑一下,为什么整体架构要按照这种方式组织,为什么局部函数要遵循这样的步骤处理,知其然,知其所以然,如果你知道了某个功能的实现是因为芯片就是这么设计的,CPU就是这么做的,那么你的疑问也就基本上到此为止了。再深究,就是芯片架构方面的设计与实现,对于程序员来讲,无论是系统还是应用程序员,足迹探究到这里,已经解决了很多疑问,因为我们的工作性质偏软,而这些东西实在是够硬。

比如,ULK3中讲解的中断和异常的实现,究其根源,那是因为Intel x86系列就是这么设计的,去看看Intel V3手册中相应章节介绍,都可以为ULK3中描述的代码实现方式找到注解。还有时间和定时器管理,同样可以在Intel V3 对APIC的介绍中获取足够的信息,操作系统就是依据这些硬件特性来实现软件方法定义的。

又是那句话,不是理解不理解的问题,而是知道不知道的问题。有时候,知道了,就理解了。在整个学习过程中,知道,理解,知道,理解,知道……,交叉反复。为什么开始和结尾都是知道,而理解只是中间步骤呢?世界上万事万物自有其规律,人类只是发现而已,实践是第一位的,实践就是知道的过程,实践产生经验,经验的总结就是理论,理论源于实践,理论才需要理解。我们学习内核,深入研究,搞来搞去,又回到了芯片上,芯片是物质的,芯片的功用基于自然界中物质本有的物理和电子特性。追本溯源,此之谓也。

动手写代码

纸上得来终觉浅,绝知此事要躬行。只看书是绝对不行的,一定要结合课本给出的编程建议自己敲代码。刚开始就以模块形式测试好了,或者自己编译一个开发版本的内核。一台机器的话,使用UML方式调试,内核控制路走到哪一步,单步调试看看程序执行过程,比书上的讲解更直观明了。一定要动手实际操作。

参考书

LDD3 Linux Device Driver 3rd
LKD3 Linux Kernel Development 3rd
ULK3 Understanding the Linux Kernel 3rd
PLKA Professional Linux Kernel Architecture
UML User Mode Linux
Intel V3 Intel? 64 and IA-32 Architectures Software Developer’s Manual Volume 3 (3A, 3B & 3C): System Programming Guide

作者在写书的时候,都是以自己的理解组织内容,从自己的观点看待一个主题,关注点跟作者自身有很大的关系。出书的时间有先后,后来人针对同一个主题想要出书而又不落入窠臼,最好有自己的切入方式,从自己的角度讲解相关问题,这才值得出这本书,千篇一律是个掉价的行为,书就不值钱了。

尽信书不如无书。

http://lwn.net/Articles/419855/ 此处是一篇关于LKD3的书评,指出了其中的错误,当你读完的时候,不妨去找找,看一下自己在其中所描述的地方有什么特别的印象。
http://lwn.net/Articles/161190/此处是一篇对ULK3的介绍,我认为其中很关键的几句话就可以给本书定位:
Many of the key control paths in the kernel are described, step by step;
一步一步地讲述内核控制路径的实现。
The level of detail sometimes makes it hard to get a sense for the big picture, but it does help somebody trying to figure out how a particular function works.

对代码讲解的详细程度有时候很难让读者把握住它的主旨大意,但是确实有助于读者理解一个特定的函数到底是如何工作的。

Indeed, that is perhaps the key feature which differentiates this book. It is very much a "how it works" book, designed to help people understand the code.

事实上,这也正是本书与众不同的地方。更像一个“如何工作”的书,帮助读者理解代码实现。

It presents kernel functions and data structures, steps the reader through them, but does not, for example, emphasize the rules for using them. UTLK is a study guide, not a programming manual.

本书描述了内核函数和数据结构,引导读者穿行于其间,但是,并没有着重强调使用它们的法则。UTLK是一本学习指南,而不是编程手册。

这几句话对本书的描述非常到位。基于此,作为指导性原则,我们就可以很有效率地使用它了。

看一本技术书籍,书中的序言部分绝对是首先应该翻阅的,其次就是目录。我发现在阅读过程中我会频繁的查看目录,甚至是喜欢看目录。

结尾

兴趣的力量是无穷的。兴趣能带来激情,如果工作可以和兴趣结合到一起,工作起来才会有热情,那么工作就不只是工作了,更是一种享受。

Linux,我的兴趣,我的动力,我的方向,我的未来!

【转载】http://blog.chinaunix.net/uid-24669930-id-4039377.html