wjping119 发表于 2005-1-13 13:13:10

离开了Debian的repository,我很怀疑hiweed的可用性。
话不能这样说,要是没有linux kenel,你用什么来着???
是吧?有跟没有是大不相同的

caihua 发表于 2005-1-13 13:32:33

:roll: “windows 经典”的界面?有啊,你没有发现么?

duotaiya 发表于 2005-1-13 13:56:17

:roll: “windows 经典”的界面?有啊,你没有发现么?
windows经典的界面是——蓝屏。

我也来说几句。
我机子上装的是hiweed0.3,只给了它2g。
不过话说回来,如果我没有装宽带,我就不会装hiweed

caihua 发表于 2005-1-13 13:59:33

:twisted: 装Magic

duotaiya 发表于 2005-1-13 14:10:18

:twisted: 装Magic
不,我弄套debian的光盘,嘿嘿。

caihua 发表于 2005-1-13 14:15:58

:shock:

KanKer 发表于 2005-1-13 14:34:56

我想从技术上提点个人感觉

windows的依赖性问题是靠动态链接库DLL解决的,就是说你缺什么DLL,直接靠到/windows/system32下就可以了。早期大家用VB开发的小软件,如果别人要用,就要拷两个VB的DLL库,相信大家都经历过吧?只用拷贝这个操作就可以用了啊,多简单!

linux的依赖性,说简单点是个什么情况呢?希望得到指点。


两个系统都是用的动态链接库,只是后缀不同罢了。win下的依赖问题在安装软件时可能不会提示,而使用时会报缺这个缺那个,而linux做的好的安装包是可以提示的,免得用户装好了用不了。至于缺少的那些动态链接库,两个系统都可以通过拷贝符合要求的库到系统库文件夹中来解决。

zhtaoist 发表于 2005-1-13 14:56:36

刚看到一篇关于动态库的文章,转过来,希望有用^_^

分析Windows和Linux动态库


   作者: 刘世栋 杨林
http://www.yesky.com/SoftChannel/72350107080589312/20040224/1771215.shtml

摘要:动态链接库技术实现和设计程序常用的技术,在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函数,具体这两个函数的用法可参考文献。

  (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下的方法以及需要注意的问题,同时并给出了程序示例片断,实际在程序移植过程中,由于系统的设计等方面,可能移植起来需要注意的方面远比上面复杂,本文通过总结归纳进而为不同操作系统程序移植提供了有意的经验和技巧。

发布人:会游泳的鱼 来自:www.yesky.com

KDE 发表于 2005-1-13 19:18:24

troll,
我越来越不懂,什么叫Debian的repository?
debian 是 GNU 自己的发行版,通过 apt/synaptic 来使用自己的软件仓库,爱好者为 debian 打了上万的软件包放进软件仓库里,hiweed 版也使用它。

KDE 发表于 2005-1-13 19:49:29

我曾经发过帖,叫“恼人的依赖关系”,的确 linux 下的依赖关系确实令人头疼,但不要忘记,不同的 linux 发行版实质上是不同的操作系统,这根 windows 就那么可数的几个版本完全不同,每个发行版本不仅外观不同,最要命的是设计思想都不同,面向客户不同,软件内容和版本不同,做到源代码兼容都不容易,二进制兼容更别提了。由于每个开发人员使用不同的发行版本,引入的依赖关系千奇百怪,你要安装他的软件,也必须安装这个软件依赖的软件,而它又可能依赖更广泛的软件,这样一来形成一张错综复杂的大网,绞缠不清,这其实正是自由软件的致命弱点之一,是极端自由的恶果。基于共同的一个 windows 开发的软件依赖关系相对单纯,基于不同的多个 GNU/linux 开发的软件依赖关系就会错综复杂。但是你总不能因为穿不进鞋子就把脚剁掉吧?所以别指望 linux 下就一个老大一统天下,那样的话开发人员就真的一劳永逸了。

http://www.linuxfans.org/nuke/modules.php?name=Forums&file=viewtopic&t=83243&highlight=%C4%D5%C8%CB%B5%C4%D2%C0%C0%B5%B9%D8%CF%B5

KDE 发表于 2005-1-13 19:59:39

自由软件的开发多数是小作坊式的,作者也不太注重自己产品的向下兼容性,这也引入不少麻烦。有时安装 a 需要 c1,安装 b 需要 c2,而 c1 和 c2 是同一个软件的不同版本,且互不兼容,而且同一个软件的不同版本几乎不可能共存于你的系统里同一个位置上,那么,你要么放弃安装 a 或 b,否则就要自己修改软件,使它们共同依赖 c1 或 c2。如果是二进制包就特别突出,如果是源代码,有时可以通过把 c1 和 c2 安装到不同位置上,然后安装 b 的时候在 configure 参数上指定 c2 的位置来避开这一问题,但这不是 100% 都能成功的。

KDE 发表于 2005-1-13 20:06:48

LSB 并不能完全解决二进制兼容问题。因为 GNU 构建系统是随遇而安的,也就是说有什么吃什么,如果你打的包是在你安装某个软件之后,很可能它就会依赖这个软件,导致它不能在同一个发行版别人的机器上运行。这就是为什么 magiclinux 开发人员必须统一开发平台的原因。

KDE 发表于 2005-1-13 20:11:28

LSB 要求软件使用通用的库,这些库拥有共同的函数、功能等等以便做到二进制接口兼容,软件依赖的其他库都必须自己绑定,但是如果用户自己修改、升级了一些库,很可能这种兼容性就如水中花、镜中月,成了虚名。软件依赖的其他库必须自己绑定,这本身实现起来就比较难,因为这会使软件臃肿。

http://refspecs.freestandards.org/LSB_2.0.1/LSB-Core-IA32/LSB-Core-IA32.html

atfa 发表于 2005-1-14 00:15:28

连我这个忠实的debian用户都看不下去了

magic就是magic,hiweed就是hiweed,设计初衷都不一样,怎么能比呢?

还好没有听到有人说建议fanx也做个精简版,kao! :lol:

dzy 发表于 2005-1-14 08:25:35

KDE,你说的可能是对的。
但在我看起来,好像是要大伙从此再也不要用LINUX了。

我伤心哪!
页: 1 2 3 [4] 5
查看完整版本: Magiclinux能不能向hiweed-debian学习?