显示标签为“Linux”的博文。显示所有博文
显示标签为“Linux”的博文。显示所有博文

2007-12-02

windows和linux混合系统的多重启动


windows和linux混合系统的多重启动从来都是一个启动加载器加载另一个系统的引导记录或启动加载器.
因此Vista,Linux的双重启动也是如此:

方法1:用Vista的bootMbr加载grub
方法2:把Grub装到mbr,用grub "chainloader (hd0,1)+1"

方法2和XP没什么好说的,现在说方法1.

Vista的bootMbr可以看成一个小的操作系统,加载几种不同的程序

先来看:bcdedit /?create 中的一段话:

/application <apptype> 指定新项必须是应用程序项。
<apptype> 指定应用程序类型。
<apptype> 可以是下列类型之一:
BOOTSECTOR
OSLOADER
RESUME
STARTUP

如果使用其他应用程序类型而不是这些类型, 则还必须指定已知的标识符。

再来看,我系统的实际的BCD记录:

Windows 启动管理器
--------------------
标识符 {bootmgr}
device partition=D:
description Windows Boot Manager
locale zh-CN
inherit {globalsettings}
default {current}
displayorder {ntldr}
{current}
{cdb7d744-a02e-11dc-a438-00115b1add5f}
toolsdisplayorder {memdiag}
timeout 30
Windows 启动加载器
-------------------
标识符 {current}
device partition=C:
path Windowssystem32winload.exe
description Microsoft Windows Vista
locale zh-CN
inherit {bootloadersettings}
osdevice partition=C:
systemroot Windows
resumeobject {91d7a191-a009-11dc-8f33-c08105f3e2d8}
nx OptIn
Windows 启动加载器
-------------------
标识符 {cdb7d741-a02e-11dc-a438-00115b1add5f}
device partition=D:
path ghldr
description GHLDR-O
从休眠状态恢复
---------------------
标识符 {91d7a191-a009-11dc-8f33-c08105f3e2d8}
device partition=C:
path Windowssystem32winresume.exe
description Windows Resume Application
locale zh-CN
inherit {resumeloadersettings}
filepath hiberfil.sys
pae No
debugoptionenabled No
Windows 内存测试程序
---------------------
标识符 {memdiag}
device partition=D:
path bootmemtest.exe
description Windows 内存诊断
locale zh-CN
inherit {globalsettings}
badmemoryaccess Yes
Windows 旧 OS 加载器
------------------------
标识符 {ntldr}
device partition=D:
path ntldr
description 早期版本的 Windows
实模式启动扇区
---------------------
标识符 {cdb7d744-a02e-11dc-a438-00115b1add5f}
device partition=D:
path NSTNeoGrub.mbr
description NeoGrub Bootloader
EMS 设置
------------
标识符 {emssettings}
bootems Yes
调试器设置
-----------------
标识符 {dbgsettings}
debugtype Serial
debugport 1
baudrate 115200
RAM 故障
-----------
标识符 {badmemory}
全局设置
---------------
标识符 {globalsettings}
inherit {dbgsettings}
{emssettings}
{badmemory}
启动加载器设置
--------------------
标识符 {bootloadersettings}
inherit {globalsettings}
恢复加载器设置
----------------------
标识符 {resumeloadersettings}
inherit {globalsettings}

可见vista的boorMbr(Windows 启动管理器)
可以加载:
OSLOADER(Windows 启动加载器)
BOOTSECTOR(实模式启动扇区)

也就是说,我们可以把Grub修改成上面两种程序中的一种,来让"Windows 启动管理器"来加载.

第一种的配置例如上面的:
Windows 启动加载器
-------------------
标识符 {cdb7d741-a02e-11dc-a438-00115b1add5f}
device partition=D:
path ghldr
description GHLDR-O
但这样的文件,ghldr,实现起来是比较麻烦的,因为缺少资料.

第二种:
实模式启动扇区
---------------------
标识符 {cdb7d744-a02e-11dc-a438-00115b1add5f}
device partition=D:
path NSTNeoGrub.mbr
description NeoGrub Bootloader
则已经有了产品:NeoGrub.mbr

这是我D:NST的文件:
d:NST>dir
驱动器 D 中的卷是 XPHOME 卷的序列号是 A05A-B1BB
d:NST 的目录
2007/12/02 02:16 <dir> .
2007/12/02 02:16 <dir> ..
2007/12/02 02:16 397 menu.lst
2007/06/15 05:19 8,192 NeoGrub.mbr
2 个文件 8,589 字节
2 个目录 393,293,824 可用字节
d:NST>type menu.lst
# NeoSmart NeoGrub Bootloader Configuration File#
# This is the NeoGrub configuration file, and should be located at D:NSTmenu.lst
# Please see the EasyBCD Documentation for information on how to create/modify entries:
# <a href="http://neosmart.net/wiki/display/EBCDhttp://neosmart.net/wiki/display/EBCD">http://neosmart.net/wiki/display/EBCD</a>
find --set-root --ignore-floppies /boot/grub/menu.lst
configfile /boot/grub/menu.lst
# All your boot are belong to NeoSmart!
d:NST>

这样,Grub就会按分区顺序寻找/boot/grub/menu.lst

也许你会问,到哪里去找这个NeoGrub呢?
上面的文件已经透露了:
请google "EasyBCD"

2007-06-22

Linux系统的构成和相互间的依赖(从LFS看Linux)

原题 : 换个角度看LFS——反向分析LFS


更新日志
2006-08-12:修改有歧义的句子一处。
2006-06-21:增加对结尾插图的说明。
2006-06-21:修改最后一副插图。
2006-06-21:修改笔误一处。

前言
  写了几篇关于LFS的制作过程中的文章,但分析性的文章还没怎么写过,论坛上也有一些分析性的文章,但大多数都是真对某个特定部分的,最近酝酿了一下,准备写点分析性质的文章调剂调剂。
  这次用的标题大概已经能说明本文分析的角度,按照LFS的顺序写,似乎总不能摆脱LFS的制作过程的牵制,总觉得像写制作教程,所以决定反过来写,利用一个大家熟悉的情景为开始反过来推出整个LFS的过程,本文不能算专业的分析文章,只是想简单的说明白LFS为什么要这样的过程。
  本文并不是要完全还原LFS,只是为了说明一种分析过程,因此文中部分内容和实际的LFS略有出入。
  限于水平的问题,我只能将我现在的理解来写,如果有什么错误或者不当的地方希望大家及时指出。
  本文的读者应该是一个已经经历过LFS至少一次的朋友,如果你从来没搞过LFS,建议亲自动手制作一遍后再看本文,应至少看过下面文章中的一篇:
  《Linux from scratch》英文版本
  《LFS-Book 6.1.1 中文正式版》
  《手把手教你如何建立自己的Linux系统(LFS速成手册)》

  更新,由于篇幅比较长所以难免出现一些错误或者笔误,也有可能加入新内容,因此难免会进行修正或增删一些内容,如果本文被转载您可以在本人的Blog或者www.linuxsir.org的LFS版中中查看最新版本。
  我的Blog:http://youbest.cublog.cn
  linuxsir:http://www.linuxsir.org/bbs/showthread.php?t=262010
  如须转载请注明作者为冲天飞豹(youbest),并请保持文章的完整和提供转载出处。

工作情景:
  我正在用VIM编辑一篇文件


分析:
  问:那么要完成这个任务我需要些什么呢?
  答:硬件(略),本文将不对硬件做任何分析。
    软件:VIM

  问:那么运行VIM又需要什么条件呢?
  答:一个Linux内核
    一组支持VIM运行的动态库,按照比较标准的组合,应该是glibc和ncurses这两个库来承担VIM的运行时动态库

  问:那么内核需要什么条件呢?
  答:符合内核运行的硬件环境。

  问:glibc又需要什么条件呢?
  答:于glibc相适应的Linux内核

  问:ncurses需要什么条件呢?
  答:合适的glibc

最后我们来画一副图来描述这个关系



  那么这个关系图基本上就可以描述一个VIM运行的环境需求,当然在启动VIM的过程中少不了一个shell的参与,通常我们用BASH来完成,那么这个任务的整个大致环境和关系大致如下图所示。


  清楚了这个问题,下面需要解决的就是这个运行环境从哪里来的呢?
  通常Linux下的软件都提供了源代码,我们可以用这些源代码来组合成我们自己需要的二进制程序。
  在这个例子中,我们想要有一个VIM,那么我们要先下载一份VIM的完整源代码,然后利用一组编译工具来完成VIM的编译。
  对于一个通常编译的过程大致如下图





  这其中最复杂的就是make阶段,make会调用目录中的Makefile来执行一系列的工作,其中包括创建必要的文件,以及调用gcc和binutils来编译源代码和链接目标文件,最终生成需要的可执行文件和附属文件。
  所以make过程中一般需要用到的是gcc,binutils,make和一些系统程序(不同的软件需求不同)。


这样我们再来画最开始的运行环境的图


  好了,这样我们就清楚了这个整个运行时候的环境是从哪里来的了。用红色虚线框起来的就是整个构造运行时环境的必要条件了,其实就是我们通常在LFS中最常见到的一个词汇:工具链。
  那么下面的一个问题就是这些工具运行的条件是什么?
  这些编译环境中的应用程序也和其它程序一样必须有运行的环境:
  GCC依赖于glibc
  binutils依赖于glibc
  make依赖于glibc
  头文件是在编译时候gcc所需要的,但本身都是一些文本文件,因此没有需要的运行环境。
  常用工具依赖于glibc和各种需要用到的动态库。

  这里的一个新问题就是编译环境中使用的glibc和Linux内核和“运行时环境”中的glibc与Linux内核是否是同一个。
  答案很显然,绝对不是,因为“运行时环境”中的glibc和Linux内核是依靠工具链中编译工具来完成的,所以工具链所依赖的glibc和Linux内核于目标系统的不可能是同一个(但版本什么的是可以一样的,这里说的不同是指已经编译成二进制的实体不同)。
说明:
  为了说明方便,下面将“运行时环境”称为目标系统。
  但就LFS而言目标就是要做一个通用的可自主扩展(编译)的系统,所以在完成目标系统的glibc后又编译了一整套工具链中的东西,目的是将工具链中的工具全部移植到目标系统中,以便在完成目标系统后可以抛弃工具链而又能够自主的进行编译,而这些工具依赖的环境就是目标系统的glibc了。
  内核这东西比较特殊,虽然运行任何程序都需要用的内核,但本身在制作目标系统过程中,目标系统的Linux内核却不需要先进行编译,因为使用 Linux内核并不像glibc那样是依靠动态链接库的方式被调用的,内核不是用动态库的方式被调用的,因此不需要先编译,只要提供对应的头文件即可,后面将不再探讨Linux内核的问题。
  作为LFS的另一个目标就是要建立一个“纯净”的系统,因此编译glibc的编译器和最后目标系统里的编译器应该保持一致,同时目标系统是完全依靠工具链编译出来的,而工具链应该是在目标系统建立完毕后可以很方便的剥离掉的,而且为了保持工具链的稳定工具链中的工具所依赖的glibc以及其它用到的动态库应该是不会被替换掉的。
  要解决上面这个问题,那么最好的方法就是将工具链放置在一个独立的目录中,LFS将其放在了/tools目录下,因此在用工具链建立目标系统的过程中将PATH设置为/bin:/usr/bin:/tools/bin来让bash调用命令时能首先调用目标系统中已经建立好的命令,如果没有则从工具链中调用。这样的话在目标系统还没有编译工具的情况下使用工具链来进行编译。
  好了,现在已经可以用工具链来完成目标系统的编译了,下面的问题就是这个工具链是如何来的呢?
  这个问题就要回到前面所提到的工具链运行时所依赖的环境,还是这个glibc,要编译这个glibc必须是在工具链的编译工具生成之前,而工具链的编译工具又依赖于glibc,那么这个glibc就不能是现在工具链中的编译工具编译出来的,那么是谁编译的呢?
  这个问题的答案:当然还是编译器编译的这个glibc和工具链里的编译工具,也就是说在工具链中的编译工具编译目标系统之前需要另一个编译器来编译这个在使用的工具链中的编译器和编译器所依赖的glibc。


  用蓝色的虚线框起来的部分就是生成工具链的工具链,我暂时称为“预工具链”。
  “预工具链”的存在则能完成工具链中的glibc,以及工具链中的编译工具,并且工具链中的工具将被编译成依赖于工具链中的glibc。
  那么现在要解决的问题就是这个“预工具链”是如何建立起来的。
  答案还是一样,需要一套编译工具来编译出这个“预工具链”。

  现在要提到的一个问题就是,用不同版本的gcc编译出来的程序可能不一样,而不同的gcc编译出来的目标文件要用能正确处理的binutils的版本来链接成可执行文件,因此我们现在已经能确定的gcc、binutils版本是工具链中的版本,那么用工具链编译出来的目标系统是符合我们的要求的。
  那么编译工具链中的glibc和gcc以及binutils的gcc和binutils的版本现在还没有确定,但根据LFS的“纯净”目标,也就是说 gcc和binutils也必须和工具链中的gcc和binutils相同才行。而其它的常用工具及make虽然参与,但不会对编译的二进制产生影响(前提是必须能正确处理它应该做的事情)。

  现在的问题就集中到“预工具链”中的gcc和binutils上了,只要能编译出和工具链中的gcc与binutils相同版本就可以了,也就是说只要一套编译环境能编译gcc和binutils就可以了。

  那么问题是这一套编译环境是怎么来的呢?
  如果还继续按照前面的套路,这个问题就成了无穷无尽的了,这个不是我们想做的,现在已经能“纯净”的建立一套符合条件的工具链就已经达到我们的目的了,因此编译“预工具链”的binutils和gcc的任务我们就采用一套能正确编译的发行版或者预制好的编译环境就可以了,我们可以称这个发行版或者预制好的编译环境为“主系统”。
  那么我们现在只要能用这个“主系统”编译出“预工具链”的binutils和gcc就可以了,“预工具链”中的其它部分就直接采用“主系统”里的就可以了。
  但这里有一个问题就是:“主系统”中的gcc和binutils与“预工具”中要求的gcc和binutils版本不同(通常会老些),但只要能正确编译binutils、gcc就行了,gcc具备自我编译的功能,因此建议编译不同版本的gcc采用bootstrap的方式比较好。当然“主系统”中的在参与编译过程中的其它工具也需要符合要求就成。
  最后用一副图来表达简单的表达整个过程,也算本文的结尾。
(转载请保持文章的完整性,请注明作者和出处)

                               作者:冲天飞豹(youbest)
                               Email:youbest@sina.com
                               2006年6月21日

希望大家能多写一些分析性的文章,共同提高。




说明:上图的内容实际上并不是标准的LFS编译关系,按照LFS的做法,应该在预工具链编译完成工具链中的glibc、gcc和binutils,工具链后续的部分是由工具链的gcc和binutils来完成的,但本文并不追求和LFS完全一致,只是为了说明整个过程是如何反向推出来的,而且我认为按照图里的方法也完全没问题,完全不影响目标系统的“纯净”度。
图中实际上也表现了一种可以用来编译不同平台上的工具链的方法,因为在编译整个工具链的过程中都由预工具链来完成的(此方法我自己没实验过,只是一个设计)。


更新日志:

2006年6月21日:
修改笔误一处
由linuxsir上的doom3d发现并报告

2006年6月21日:
在结尾的图片上加入gcc的bootstrap的标记。
由linuxsir上的doom3d建议

2006年6月21日:
对结尾的图片做出说明。

2006年8月12日:
修改有歧义的句子一处。

2007-06-02

xorg配置的一些看法

xorg配置的一些看法
以下是本人的一些看法,如有错误请指正:
--------------------------------------------------------------------------------
关于液晶显示器采用高的刷新频率而不是最佳刷新频率的问题:
如果是液晶显示器的话,很多是有一个显示效果最好的刷新频率,设高了,如果没超出显示器的范围,还是能工作的,但是显示器的显示效果反而不好。
这时候应该在你xorg.conf中有效的那一段Section "Monitor" 中添加或修改VertRefresh设置成VertRefresh (显示器底限) - (最佳频率+0.3到0.5)
因为X进行显示模式匹配的时候,同一分辨率的索引项,是安刷新频率从高到低排列的,也就是说合格的显示模式中,同一分辨率的,高刷新频率的模式会优先采用。
------------------------------------------------------------------------------------
关于X采用的刷新频率高于显示器的实际工作能力的问题:
X是跟据程序中Probe phase (硬件侦测)生成的数据和VertRefresh信息,HorizSync信息设定,进行显示模式索引的建立的。当VertRefres高限过高,或根本没提供VertRefresh信息时,能否正确进行显示模式索引的建立就依赖于Probe phase,Probe phase绝大部分情况下还是能很好工作的,但是程序毕竟不是万能的。就有可能采用的刷新频率高于显示器的实际工作能力。
另外HorizSync也是一个很有用的参数,因为显示器的刷新频率和分辨率是关联的,高分辨率时能工作的刷新频率就低。X就是根据HorizSync计算不同分辨率下的刷新频率的高限的。HorizSync不正确,即使VertRefres正确,也可能导致X在使用较高分辨率时刷新频率过高。
解决办法:(不太适用于不会在文本方式下工作的人)
1.先去掉所有的HorizSync VertSync 配置(Comment all HorizSync and VertSync values to use DDC)
2.1的方法不行的话,就需要收工指定HorizSync VertSync,在没有可靠资料的情况下:
如果是液晶显示器的话:VertRefresh高限设成 (最佳频率+0.3到0.5),一般最佳的是在60或65。 如果是CRT 17寸的话,VertRefresh 高限应该可以设到70。
如果同时装有windows的话,VertRefresh 高限设成你windows正在使用的刷新频率+0.3到0.5,同时Modes设成对应的Windows正在使用的分辨率。
3.2的办法不行的话把显卡驱动模块改成 "vga",去掉所有的HorizSync VertSync 配置,先提供一个图形界面供你上网,然后就google你的显示器型号,应该能找到一些资料吧。
-------------------------------------------------------------------------------------
还有的一些疑问,希望知道的告诉我:
现在还不清楚是xorg.conf中的配置和Probe phase是怎样配合的,有时候发现光靠Probe phase(就是xorg.conf不作配置)X能工作,这时xorg.conf添加了错误配置后反而不能工作,并不是设想的xorg.conf和Probe phase只要有一个能正确进行就能工作。这大概就是为什么有的xorg.conf的配置软件会在xorg.conf写入一行:
### Comment all HorizSync and VertSync values to use DDC:

2007-05-14

今天早晨醒来对梦的回忆

好像是在后悔,放弃了对zhcon在AUR上的维护。
没想到在我的潜意识里会对这件事情这么在意。
没办法,没有时间维护这个包了。及时放弃,让
别人接手是对的。
如果我有空再把自己的pkgbuid提交给新的维护者就好

开源世界,好像曾被人戏称为“共产主义”在软件开发上的试运行。

可惜现实世界还是市场模式。

开源的I&F的驱动模式还只是这个世界的一个很小的一个钉子

特别是生产力还不发达的发展中国家,驱动力更小。

2007-05-07

Subversion手册

http://svnbook.subversion.org.cn/

CUPS系统简介

Linux打印系统最早源于Unix打印系统,但Unix系统却一直缺乏统一的标准接口。由于历史原因,不同Unix平台使用着不同的打印系统。在各种Unix打印解决方案中,最流行的是Berkeley打印系统和 System V打印系统。一方面,不同打印系统需要不一样的打印驱动支持; 另一方面,Unix只拥有相对较小的客户群。这些因素使得很多打印机供应商完全放弃了对Unix平台的支持。统一打印接口的缺乏和底层驱动的不完善使打印在很长一段时间内成为了Linux平台的一大功能漏洞。

最终CUPS (Common Unix Printing System)的出现解决了上述窘境。CUPS是Unix/Linux上通用的打印系统。CUPS提供了一套CUPS API来完成Unix/Linux系统和打印机之间的交互。例如,用户可以通过CUPS获取打印机的信息,也可以通过CUPS设置打印机。CUPS提供了对Berkeley和System V打印命令的支持,这种兼容性使得之前的系统不用进行大规模修改就可被延续使用。同时,CUPS还提供一系列模块化的过滤接口。通过这些接口,打印机提供商只需要开发一个驱动程序就可以满足所有平台的需求。至今为止,CUPS已被所有Unix和Linux平台所支持。

CUPS 是Unix/Linux平台上的打印系统。CUPS的定义和实现是基于IPP(Internet Printing Protocol)协议的。IPP是通用的打印系统标准,它的功能和操作被一系列RFC(Request for Comments)所详细定义。这些具体功能和操作包括:建立IPP请求、应答IPP请求和设置IPP请求等等。和IPP相关的RFC包括 RFC1179、RFC2910、RFC2911、RFC3196等。在网络协议中,IPP位于HTTP(Hyper-Text Transport Protocol)协议之上。

深入分析Windows和Linux动态库应用异同

Linuxeden.com---自由文档 / 编程开发 / 深入分析Windows和Linux动态库应用异同 2005-09-21
------------------------------------------------------------------------------------------------------------------------
深入分析Windows和Linux动态库应用异同

摘要:动态链接库技术实现和设计程序常用的技术,在Windows和Linux系统中都有动态库的概念,采用动态库可以有效的减少程序大小,节省空间,提高效率,增加程序的可扩展性,便于模块化管理。

但不同操作系统的动态库由于格式 不同,在需要不同操作系统调用时需要进行动态库程序移植。本文分析和比较了两种操作系统动态库技术,并给出了将Visual C++编制的动态库移植到Linux上的方法和经验。

1、引言

动态库(Dynamic Link Library abbr,DLL)技术是程序设计中经常采用的技术。其目的减少程序的大小,节省空间,提高效率,具有很高的灵活性。

采用动态库技术对于升级软件版本更加容易。与静态库(Static Link Library)不同,动态库里面的函数不是执行程序本身的一部分,而是根据执行需要按需载入,其执行代码可以同时在多个程序中共享。

在Windows 和Linux操作系统中,都可采用这种方式进行软件设计,但他们的调用方式以及程序编制方式不尽相同。本文首先分析了在这两种操作系统中通常采用的动态库调用方法以及程序编制方式,然后分析比较了这两种方式的不同之处,最后根据实际移植程序经验,介绍了将VC++编制的Windows动态库移植到 Linux下的方法。

2、动态库技术

2.1 Windows动态库技术

动态链接库是实现Windows应用程序共享资源、节省内存空间、提高使用效率的一个重要技术手段。常见的动态库包含外部函数和资源,也有一些动态库只包含资源,如Windows字体资源文件,称之为资源动态链接库。通常动态库以.dll,.drv、.fon等作为后缀。

相应的windows静态库通常以.lib结尾,Windows自己就将一些主要的系统功能以动态库模块的形式实现。

Windows动态库在运行时被系统加载到进程的虚拟空间中,使用从调用进程的虚拟地址空间分配的内存,成为调用进程的一部分。DLL也只能被该进程的线程所访问。DLL的句柄可以被调用进程使用;调用进程的句柄可以被DLL使用。

DLL 模块中包含各种导出函数,用于向外界提供服务。DLL可以有自己的数据段,但没有自己的堆栈,使用与调用它的应用程序相同的堆栈模式;一个DLL在内存中只有一个实例;DLL实现了代码封装性;DLL的编制与具体的编程语言及编译器无关,可以通过DLL来实现混合语言编程。DLL函数中的代码所创建的任何对象(包括变量)都归调用它的线程或进程所有。

根据调用方式的不同,对动态库的调用可分为静态调用方式和动态调用方式。

(1) 静态调用,也称为隐式调用,由编译系统完成对DLL的加载和应用程序结束时DLL卸载的编码(Windows系统负责对DLL调用次数的计数),调用方式简单,能够满足通常的要求。通常采用的调用方式是把产生动态连接库时产生的.LIB文件加入到应用程序的工程中,想使用DLL中的函数时,只须在源文件中声明一下。

LIB文件包含了每一个DLL导出函数的符号名和可选择的标识号以及DLL文件名,不含有实际的代码。Lib文件包含的信息进入到生成的应用程序中,被调用的DLL文件会在应用程序加载时同时加载在到内存中。

(2)动态调用,即显式调用方式,是由编程者用API函数加载和卸载DLL来达到调用DLL的目的,比较复杂,但能更加有效地使用内存,是编制大型应用程序时的重要方式。在Windows系统中,与动态库调用有关的函数包括:

①LoadLibrary(或MFC 的AfxLoadLibrary),装载动态库。

②GetProcAddress,获取要引入的函数,将符号名或标识号转换为DLL内部地址。

③FreeLibrary(或MFC的AfxFreeLibrary),释放动态链接库。

在windows 中创建动态库也非常方便和简单。在Visual C++中,可以创建不用MFC而直接用C语言写的DLL程序,也可以创建基于MFC类库的DLL程序。每一个DLL必须有一个入口点,在VC++中, DllMain是一个缺省的入口函数。DllMain负责初始化(Initialization)和结束(Termination)工作。

动态库输出函数也有两种约定,分别是基于调用约定和名字修饰约定。DLL程序定义的函数分为内部函数和导出函数,动态库导出的函数供其它程序模块调用。通常可以有下面几种方法导出函数:

①采用模块定义文件的EXPORT部分指定要输入的函数或者变量。

②使用MFC提供的修饰符号_declspec(dllexport)。

③以命令行方式,采用/EXPORT命令行输出有关函数。

在windows动态库中,有时需要编写模块定义文件(.DEF),它是用于描述DLL属性的模块语句组成的文本文件。

2.2 Linux共享对象技术

在Linux 操作系统中,采用了很多共享对象技术(Shared Object),虽然它和Windows里的动态库相对应,但它并不称为动态库。相应的共享对象文件以.so作为后缀,为了方便,在本文中,对该概念不进行专门区分。Linux系统的/lib以及标准图形界面的/usr/X11R6/lib等目录里面,就有许多以so结尾的共享对象。

同样,在Linux下,也有静态函数库这种调用方式,相应的后缀以.a结束。Linux采用该共享对象技术以方便程序间共享,节省程序占有空间,增加程序的可扩展性和灵活性。Linux还可以通过LD-PRELOAD变量让开发人员可以使用自己的程序库中的模块来替换系统模块。

同Windows 系统一样,在Linux中创建和使用动态库是比较容易的事情,在编译函数库源程序时加上-shared选项即可,这样所生成的执行程序就是动态链接库。通常这样的程序以so为后缀,在Linux动态库程序设计过程中,通常流程是编写用户的接口文件,通常是.h文件,编写实际的函数文件,以.c或.cpp为后缀,再编写makefile文件。对于较小的动态库程序可以不用如此,但这样设计使程序更加合理。

编译生成动态连接库后,进而可以在程序中进行调用。在Linux中,可以采用多种调用方式,同Windows的系统目录(..\system32等)一样,可以将动态库文件拷贝到/lib目录或者在/lib目录里面建立符号连接,以便所有用户使用。

下面介绍Linux调用动态库经常使用的函数,但在使用动态库时,源程序必须包含dlfcn.h头文件,该文件定义调用动态链接库的函数的原型。

(1)_打开动态链接库:dlopen,函数原型void *dlopen (const char *filename, int flag); dlopen用于打开指定名字(filename)的动态链接库,并返回操作句柄。

(2)取函数执行地址:dlsym,函数原型为: void *dlsym(void *handle, char *symbol); dlsym根据动态链接库操作句柄(handle)与符号(symbol),返回符号对应的函数的执行代码地址。

(3)关闭动态链接库:dlclose,函数原型为: int dlclose (void *handle); dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。

(4)动态库错误函数:dlerror,函数原型为: const char *dlerror(void); 当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。

在取到函数执行地址后,就可以在动态库的使用程序里面根据动态库提供的函数接口声明调用动态库里面的函数。在编写调用动态库的程序的makefile文件时,需要加入编译选项-rdynamic和-ldl。

除了采用这种方式编写和调用动态库之外,Linux操作系统也提供了一种更为方便的动态库调用方式,也方便了其它程序调用,这种方式与Windows系统的隐式链接类似。其动态库命名方式为“lib*.so.*”。在这个命名方式中,第一个*表示动态链接库的库名,第二个*通常表示该动态库的版本号,也可以没有版本号。

在这种调用方式中,需要维护动态链接库的配置文件/etc/ld.so.conf来让动态链接库为系统所使用,通常将动态链接库所在目录名追加到动态链接库配置文件中。如具有X window窗口系统发行版该文件中都具有/usr/X11R6/lib,它指向X window窗口系统的动态链接库所在目录。

为了使动态链接库能为系统所共享,还需运行动态链接库的管理命令./sbin/ldconfig。在编译所引用的动态库时,可以在gcc采用 –l或-L选项或直接引用所需的动态链接库方式进行编译。在Linux里面,可以采用ldd命令来检查程序依赖共享库。

3、两种系统动态库比较分析

Windows和Linux采用动态链接库技术目的是基本一致的,但由于操作系统的不同,他们在许多方面还是不尽相同,下面从以下几个方面进行阐述。

(1) 动态库程序编写,在Windows系统下的执行文件格式是PE格式,动态库需要一个DllMain函数作为初始化的人口,通常在导出函数的声明时需要有 _declspec(dllexport)关键字。Linux下的gcc编译的执行文件默认是ELF格式,不需要初始化入口,亦不需要到函数做特别声明,编写比较方便。

(2)动态库编译,在windows系统下面,有方便的调试编译环境,通常不用自己去编写makefile文件,但在linux下面,需要自己动手去编写makefile文件,因此,必须掌握一定的makefile编写技巧,另外,通常Linux编译规则相对严格。

(3)动态库调用方面,Windows和Linux对其下编制的动态库都可以采用显式调用或隐式调用,但具体的调用方式也不尽相同。

(4) 动态库输出函数查看,在Windows中,有许多工具和软件可以进行查看DLL中所输出的函数,例如命令行方式的dumpbin以及VC++工具中的 DEPENDS程序。在Linux系统中通常采用nm来查看输出函数,也可以使用ldd查看程序隐式链接的共享对象文件。

(5)对操作系统的依赖,这两种动态库运行依赖于各自的操作系统,不能跨平台使用。因此,对于实现相同功能的动态库,必须为两种不同的操作系统提供不同的动态库版本。

4、动态库移植方法

如果要编制在两个系统中都能使用的动态链接库,通常会先选择在Windows的VC++提供的调试环境中完成初始的开发,毕竟VC++提供的图形化编辑和调试界面比vi和gcc方便许多。完成测试之后,再进行动态库的程序移植。

通常gcc默认的编译规则比VC++默认的编译规则严格,即使在VC++下面没有任何警告错误的程序在gcc调试中也会出现许多警告错误,可以在gcc中采用-w选项关闭警告错误。

下面给出程序移植需要遵循的规则以及经验。

(1) 尽量不要改变原有动态库头文件的顺序。通常在C/C++语言中,头文件的顺序有相当的关系。另外虽然C/C++语言区分大小写,但在包含头文件时, Linux必须与头文件的大小写相同,因为ext2文件系统对文件名是大小写敏感,否则不能正确编译,而在Windows下面,头文件大小写可以正确编译。

(2)不同系统独有的头文件。在Windows系统中,通常会包括windows.h头文件,如果调用底层的通信函数,则会包含 winsock..h头文件。因此在移植到Linux系统时,要注释掉这些Windows系统独有的头文件以及一些windows系统的常量定义说明,增加Linux都底层通信的支持的头文件等。

(3)数据类型。VC++具有许多独有的数据类型,如__int16,__int32, TRUE,SOCKET等,gcc编译器不支持它们。通常做法是需要将windows.h和basetypes.h中对这些数据进行定义的语句复制到一个头文件中,再在Linux中包含这个头文件。例如将套接字的类型为SOCKET改为int。

(4)关键字。VC++中具有许多标准C中所没有采用的关键字,如BOOL,BYTE,DWORD,__asm等,通常在为了移植方便,尽量不使用它们,如果实在无法避免可以采用#ifdef 和#endif为LINUX和WINDOWS编写两个版本。

(5) 函数原型的修改。通常如果采用标准的C/C++语言编写的动态库,基本上不用再重新编写函数,但对于系统调用函数,由于两种系统的区别,需要改变函数的调用方式等,如在Linux编制的网络通信动态库中,用close()函数代替windows操作系统下的closesocket()函数来关闭套接字。另外在Linux下没有文件句柄,要打开文件可用open和fopen函数,具体这两个函数的用法可参考文献[2]。

(6)makefile 的编写。在windows下面通常由VC++编译器来负责调试,但gcc需要自己动手编写makefile文件,也可以参照VC++生成的 makefile文件。对于动态库移植,编译动态库时需要加入-shared选项。对于采用数学函数,如幂级数的程序,在调用动态库是,需要加入-lm。

(7)其它一些需要注意的地方

①程序设计结构分析,对于移植它人编写的动态库程序,程序结构分析是必不可少的步骤,通常在动态库程序中,不会包含界面等操作,所以相对容易一些。

②在Linux中,对文件或目录的权限分为拥有者、群组、其它。所以在存取文件时,要注意对文件是读还是写操作,如果是对文件进行写操作,要注意修改文件或目录的权限,否则无法对文件进行写。

③ 指针的使用,定义一个指针只给它分配四个字节的内存,如果要对指针所指向的变量赋值,必须用malloc函数为它分配内存或不把它定义为指针而定义为变量即可,这点在linux下面比windows编译严格。同样结构不能在函数中传值,如果要在函数中进行结构传值,必须把函数中的结构定义为结构指针。

④路径标识符,在Linux下是“/”,在Windows下是“\”,注意windows和Linux的对动态库搜索路径的不同。

⑤编程和调试技巧方面。对不同的调试环境有不同的调试技巧,在这里不多叙述。

5、结束语

本文系统分析了windows和Linux动态库实现和使用方式,从程序编写、编译、调用以及对操作系统依赖等方面综合分析比较了这两种调用方式的不同之处,根据实际程序移植经验,给出了将VC++编制的Windows动态库移植到Linux下的方法以及需要注意的问题,同时并给出了程序示例片断,实际在程序移植过程中,由于系统的设计等方面,可能移植起来需要注意的方面远比上面复杂,本文通过总结归纳进而为不同操作系统程序移植提供了有意的经验和技巧。

各类开源协议介绍

Mozilla Public License

  MPL License,允许免费重发布、免费修改,但要求修改后的代码版权归软件的发起者。这种授权维护了商业软件的利益,,它要求基于这种软件得修改无偿贡献版权给该软件。这样,围绕该软件得所有代码得版权都集中在发起开发人得手中。但MPL是允许修改,无偿使用得。MPL软件对链接没有要求。

  BSD开源协议

  BSD开源协议是一个给于使用者很大自由的协议。可以自由的使用,修改源代码,也可以将修改后的代码作为开源或者专有软件再发布。 当你发布使用了BSD协议的代码,或则以BSD协议代码为基础做二次开发自己的产品时,需要满足三个条件:

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

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

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

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

  Apache Licence 2.0

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

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

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

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

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

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

GPL

  GPL许可证是自由软件的应用最广泛的软件许可证,人们可以修改程式的一个或几个副本或程式的任何部分,以此形成基於这些程式的衍生作品。必须在修改过的档案中附有明显的说明:您修改了此一档案及任何修改的日期。您必须让您发布或出版的作品,包括本程式的全部或一部分,或内含本程式的全部或部分所衍生的作品,允许第三方在此许可证条款下使用,并且不得因为此项授权行为而收费。

  LGPL

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

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

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

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

  Public Domain

  公共域授权。将软件授权为公共域,这些软件包没有授权协议,任何人都可以随意使用它。

  Artistic许可

  使作者保持对进一步开发的控制。

2007-03-18

想做一个magiclinux的动态的阶段报道

原来想做在这里,但后来决定做到
google 论坛上了,依托google的搜索功能,让更多的人看到。

但不知道能不能坚持。

2007-03-10

从社区获得帮助

可以自由修改,任意传播。
欢迎共同完成本文。


从社区获得帮助
Ver 070309Night

Linux是大集市式的环境下开发出来的,因此信息也是到处都是。
对于新手,如何获取信息来解决自己面临的问题,往往是最大的
障碍。
通过互连网上成百上千的BBS,邮件列表,Web论坛来求获取帮助是必备
的本事。
但要别人帮助你,需要自己有一定的基础,并能够提供有用的可靠的
信息。

一、寻求帮助前的准备工作。

1。先了解一下自己面临的问题的现状,自己最大的障碍点在那里。
有时是自己对问题的背景知识不够,无从下手。有时是只有具体的一个
细节有疑问。

2。整理一下思路,看看自己已经作了什么,已经排除了什么因素。

3。调整自己的逻辑方式,特别注意不要受你原有产品的逻辑设定影响。
比如:Linux和windows在网络配置方面有逻辑上的差别,这种差别是系统
设计带来的,一般情况下,没有谁优谁劣的问题。

4。尝试自己处理问题,比如Google现有的文档,查看man文档。查看帮助文件
到出问题的部件的项目主页看看现有的文档。以来加深对问题的理解。二来
这往往是最快最有效的办法。

二、收集信息。

要寻求帮助,需要的是提供有效的信息。
提供信息有两种方法:
一种是提供反映你系统现状的信息,如配置文件的内容,诊断工具的输出,
屏幕的截图,log文件等等。

二是提供你的超作流程,和现象。

三、常见问题的信息提供办法。

1.显示配置问题:
a) 提供硬件信息。

lspci > pciinfo.txt
lsusb > usbinfo.txt
dmesg > booting.tx

然后提供给社区生成的文件
目的:提供显卡鼠标等的信息。

b) 提供X系统的配置文件和log文件:
对于现在最常用的xorg
是:
/etc/X11/xorg.conf
/var/log/Xorg.0.log

c)问题的描述。

2.硬件无法驱动的问题:
a)硬件的主控制芯片的型号,设备ID,:
lspci > pciinfo.txt
lsusb > usbinfo.txt
dmesg > booting.txt

然后提供给社区生成的文件
目的:提供硬件的信息。

还有就是硬件上面,或包装的标识。

b)内核的信息
uname -a 的输出
lsmod的输出

c)问题的描述

3。网络配置问题
a) 网络接口信息
ifconfig -a 的输出

b)路由表的信息
route的输出

c)DNS配置文件的内容

d)网络的物理结构
最好可以用物理连接的示义图,或拓扑图表示。
也可以用文字描述。

e)问题的描述
最好带有几个关键ping 的输出

ping www.google.com
ping 网关IP
ping modem的IP
ping DNS的IP

四、其他
1.为什么使用文本界面的工具
因为文本界面的工具已经发展了很久了,不同版本间的差异很小,
而且输出的内容清楚明了。且输出结果为文本,便于交流。
还有就是这样的东西能直接放映本质的东西。且到处都可以找到。

2.应该把求助发到哪里
针对发行版特有的问题发到发行版的专门的论坛或邮件列表。
针对某个项目的问题发到项目的论坛或邮件列表。
总之要有针对性。
并注意礼貌。并积极参与问题的讨论。不要好像大家亏欠你似的。
不要表现得对别人过分得依赖,如果你让人觉得你什么都不愿想,
很难一起解决问题得话,大家就没有热情了。

2006-12-23

Bash脚本中的计算[转]

Bash脚本中的计算 [原先从论坛上收集的,已不明出处]
----------------------------------------------------------------------------
在bash script中,一般我们要进行计算都是用expr这个命令,虽然也很方便但是写起来比较麻烦,例如:

i=1
i=`expr $i + 1`

变量和运算符号中间必须有空格,两边还需要用反引号扩起来。

我发现有一种简单的方法,就是类似下面的写法:

i=$(($i+1))

就是用两层小括号把算是扩起来,外面再加个小括号就可以了,大家可以试试,挺好玩儿的,最有意思的是还可以做连续运算:

i=6
i=$(($i+4/2))
echo $i

结果是8;还支持括号:

i=6
j=4
i=$(($i*(2+$j)))
echo $i

结果是36;当然直接用数字也可以:

echo $((2+4))

结果是6;呵呵,这样以后写脚本需要运算就方便多了。

---------------------------------------------------
附:
GNU bash, version 3.2.5(1)-release
测试通过.

我的设备装到哪了?

我的设备装到哪了? [lanzinc@gmail.com]
用udev工具,简单分析udev动态建立设备文件的过程。
试验环境:Arch Linux 0.7.2 (Gimmick) 2.6.18-ARCH udev 103-1

有时候,我们把一个设备通过热拔插接入或脱离计算机的时候,KDE界面上一点反应也没用,这时就会考虑,是设备有问题呢,还是没有合适的驱动,还是只是KDE这样的上层建筑没有合适的配置来反应这个改变呢。
这时候应该如何着手解决这个问题呢?
还有时候,我们插如一条数据线,或者usb网卡,我们却不知到设备会别认成什么。

在现在的Linux系统里,一个设备通过热拔插接入计算机的时候,内核如果能够识别该设备,就加载相应的模块,并发布消息;udev从内核得到一组(或单条)消息(uevent),然后根据uevent按照事先建立好的规则(rules),进行一系列操作,(比如对消息进行编辑,生成新的消息,建立设备文件,建立符号链接,运行指定的脚本或程序)。


Usually udev runs as udevd(8) and receives uevents directly from the kernel if a device is added or removed form the system.
If udev receives a device event, it matches its configured rules against the available device attributes provided in sysfs to identify the device. Rules that match, may provide additional device information or specify a device node name and multiple symlink names and instruct udev to run additional programs as part of the device event handling.


udev软件包,提供了一套工具,来分析和管理udev:

[root@206studio ~]# pacman -Ql udev | grep bin
udev /sbin/
udev /sbin/migrate-udev
udev /sbin/scsi_id
udev /sbin/udevcontrol
udev /sbin/udevd
udev /sbin/udevsettle
udev /sbin/udevtrigger
udev /usr/bin/
udev /usr/bin/udevinfo
udev /usr/bin/udevtest
udev /usr/sbin/
udev /usr/sbin/udevmonitor
[root@206studio ~]#

现在来解决一个实际问题:
我的Nokia有一条数据线,可以和手机通信,现在把他接到linux上不知道能不能用?
我手头有几个软件,能够从手机上拷贝通信录和短信,但都是和串口通信的。
如果熟悉udev和设备,很快可以到/dev/tty中找到,不过这不影响我们用他来作例子。

首先,把数据线接到USB口
lsusb 看看是什么东西:

Bus 003 Device 005: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port

这个是新增加的(如果不熟悉,可以在插入数据先前先lsusb一下),就是数据线,lsusb能列出来,硬件应该没太多问题,至少是能“说话”的。

运行dmesg看看,内核能否认出来?
最后有几行:

usb 3-1: new full speed USB device using uhci_hcd and address 5
usb 3-1: configuration #1 chosen from 1 choice
pl2303 3-1:1.0: pl2303 converter detected
usb 3-1: pl2303 converter now attached to ttyUSB0

看来内核是认出来了,不过找不到她说的ttyUSB0的设备文件,怎么办呢?

把数据线拔了,
运行udevmonitor
(详细的udevmonitor信息请用man)
插入数据线
可以看到:

[root@206studio lanzinc]# udevmonitor
udevmonitor prints the received event from the kernel [UEVENT]
and the event which udev sends out after rule processing [UDEV]

UEVENT[1163352445.301250] add@/devices/pci0000:00/0000:00:10.2/usb3/3-1
UEVENT[1163352445.301608] add@/devices/pci0000:00/0000:00:10.2/usb3/3-1/usbdev3.6_ep00
UEVENT[1163352445.303713] add@/devices/pci0000:00/0000:00:10.2/usb3/3-1/3-1:1.0
UEVENT[1163352445.304027] add@/devices/pci0000:00/0000:00:10.2/usb3/3-1/3-1:1.0/ttyUSB0
UEVENT[1163352445.304246] add@/class/tty/ttyUSB0
UEVENT[1163352445.304417] add@/devices/pci0000:00/0000:00:10.2/usb3/3-1/3-1:1.0/usbdev3.6_ep81
UEVENT[1163352445.304602] add@/devices/pci0000:00/0000:00:10.2/usb3/3-1/3-1:1.0/usbdev3.6_ep02
UEVENT[1163352445.304786] add@/devices/pci0000:00/0000:00:10.2/usb3/3-1/3-1:1.0/usbdev3.6_ep83
UEVENT[1163352445.304974] add@/class/usb_device/usbdev3.6
UDEV [1163352445.337791] add@/devices/pci0000:00/0000:00:10.2/usb3/3-1
UDEV [1163352445.346145] add@/devices/pci0000:00/0000:00:10.2/usb3/3-1/usbdev3.6_ep00
UDEV [1163352445.484712] add@/devices/pci0000:00/0000:00:10.2/usb3/3-1/3-1:1.0
UDEV [1163352445.488357] add@/devices/pci0000:00/0000:00:10.2/usb3/3-1/3-1:1.0/ttyUSB0
UDEV [1163352445.498504] add@/devices/pci0000:00/0000:00:10.2/usb3/3-1/3-1:1.0/usbdev3.6_ep81
UDEV [1163352445.508543] add@/devices/pci0000:00/0000:00:10.2/usb3/3-1/3-1:1.0/usbdev3.6_ep02
UDEV [1163352445.517974] add@/devices/pci0000:00/0000:00:10.2/usb3/3-1/3-1:1.0/usbdev3.6_ep83
UDEV [1163352445.564777] add@/class/tty/ttyUSB0
UDEV [1163352445.611365] add@/class/usb_device/usbdev3.6

Ctrl+C退出来。
可以清楚的看到设备插入后,udev接收和发送的消息。

用你熟悉的编辑器,比如vi,把上面的内容变成下面这个样子,并存成一个脚本 a.sh
(我用的是kate的替换功能,把"UEVENT.* add@"正则表达式表示的内容替换成"udevtest ",udevtest的信息同样请教man)

udevtest /devices/pci0000:00/0000:00:10.2/usb3/3-1
udevtest /devices/pci0000:00/0000:00:10.2/usb3/3-1/usbdev3.6_ep00
udevtest /devices/pci0000:00/0000:00:10.2/usb3/3-1/3-1:1.0
udevtest /devices/pci0000:00/0000:00:10.2/usb3/3-1/3-1:1.0/ttyUSB0
udevtest /class/tty/ttyUSB0
udevtest /devices/pci0000:00/0000:00:10.2/usb3/3-1/3-1:1.0/usbdev3.6_ep81
udevtest /devices/pci0000:00/0000:00:10.2/usb3/3-1/3-1:1.0/usbdev3.6_ep02
udevtest /devices/pci0000:00/0000:00:10.2/usb3/3-1/3-1:1.0/usbdev3.6_ep83
udevtest /class/usb_device/usbdev3.6

然后运行sh a.sh &> b.txt

这样就得到一个文件b.txt
看看b.txt就知道udev都干了些什么了。

我关心的是udev建立了那些设备文件
运行cat b.txt | grep "creating device node" > c.txt
得到文件c.txt
内容:

[root@206studio ~]# cat c.txt
udev_node_add: creating device node '/dev/usbdev3.6_ep00', major = '442', minor = '4101', mode = '0660', uid = '0', gid = '0'
udev_node_add: creating device node '/dev/tts/USB0', major = '188', minor = '0', mode = '0660', uid = '0', gid = '5'
udev_node_add: creating device node '/dev/usbdev3.6_ep81', major = '442', minor = '4101', mode = '0660', uid = '0', gid = '0'
udev_node_add: creating device node '/dev/usbdev3.6_ep02', major = '442', minor = '4101', mode = '0660', uid = '0', gid = '0'
udev_node_add: creating device node '/dev/usbdev3.6_ep83', major = '442', minor = '4101', mode = '0660', uid = '0', gid = '0'
udev_node_add: creating device node '/dev/bus/usb/003/006', major = '189', minor = '261', mode = '0664', uid = '0', gid = '0'
[root@206studio ~]#


很明显应该使用/dev/tts/USB0

下面使用xgnokii进行试验:
首先修改配置文件:

[global]
port = /dev/tts/USB0
model = series60
initlength = default
connection = dku5

use_locking = yes

serial_baudrate = 19200

smsc_timeout = 10

[gnokiid]
bindir = /usr/sbin/

[connect_script]
TELEPHONE = 12345678
[disconnect_script]

[logging]

debug = on

rlpdebug = off

xdebug = on


运行xgnokii

[Sending Ack of type 1b, seq: 4]
Message received: 0x1b / 0x0032
01 31 00 08 00 01 58 2c 00 26 56 20 30 36 2e 30 | 1 X, &V 06.0
31 20 20 20 20 20 0a 31 38 2d 30 33 2d 30 35 0a | 1 18-03-05
52 48 2d 31 39 0a 28 63 29 20 4e 6f 6b 0a 52 00 | RH-19 (c) Nok R
00 00 |
Received message type 1b
Received revision V 06.01
model length: 5
Received model RH-19
Found model "RH-19"
Found model "RH-19"
Model: 3100
Product: RH-19
IMEI: 35565*******779
Revision: V 06.01
Phone connected. Starting monitoring...


成功!
GetFrom: lanzinc@gmail.com