Linux运维趋势,主题:Linux开发


002 《Linux 运维趋势》投稿信箱: yangsai@51cto.com 杂志订阅 : http://os.51cto.com/art/201011/233915.htm 51CTO Linux 频道 :http://os.51cto.com/linux/ 目录 Index 002 目录 人物·People 003 对话Ubuntu Tweak作者:站在用户的角度 八卦·News 005 Linux令人惊奇的用处,你见过么? 专题·Special 007 Linux内核开发者是如何“炼成”的 009 Linux设备驱动程序之Helloworld 010 Linux图形编程用什么开发包? 011 用GTK开发Linux嵌入式GUI应用程序 013 Linux下调试core文件的方法 015 Linux内核/模块开发常见问题集 出版方 :51CTO系统频道(北京无忧创想信息技术有限公司) 本期责编 :李晶 杂志主编:杨赛 联系方法 :yangsai@51cto.com 010-68476606(分机 8035) 出版日期 :2011年 9 月 2 日 每月第 2 个星期五出版(本期为特别增刊) 订阅 :http://os.51cto.com/art/201011/233915.htm 003 《Linux 运维趋势》投稿信箱: yangsai@51cto.com 杂志订阅 : http://os.51cto.com/art/201011/233915.htm 51CTO Linux 频道 :http://os.51cto.com/linux/ 人物 People 003 对话Ubuntu Tweak作者:站在用户的角度 前 不 久,Ubuntu 上 流 行 的 优 化 软 件 Ubuntu Tweak 的开发者周鼎刚刚来到了北京,成为了 Ubuntu 背后的公司—— Canonical 公司的一位员 工。从一开始的第三方 Ubuntu 开发者到现在成 为 Canonical 员工,周鼎对于当下 Linux 桌面的 发展情况和 Ubuntu 在这个市场中的定位是如何 理解的?下面请看本次专访实录—— 51CTO :听你的介绍,你第一个接触的发行版 是 Fedora Core ? 周鼎 :对,不过一开始接触一个星期就放弃 了,开始用 Ubuntu 了。你猜猜是什么原因? 51CTO :因为找不到软件源么? 周 鼎 :恩,是 这 个 原 因。 因 为 06 年 那 时 候 Ubuntu 社区已经相当成熟了,在国内各大高校, 还有一些电信机房,都有源。cn99 你知道吧,实 际上就是现在的 163 源。那时候 Ubuntu 的源非 常多,中国南北都有,很容易找到一个离你比较 近、速度比较快的。在使用 Fedora 的时候,更新 这些太麻烦了,后来用到 Ubuntu 就轻松多了,装 个软件非常方便。 对于初学者来说,你发现装个软件都装不上, 就比较麻烦。这一点是最重要的。 51CTO :那之后一直使用Ubuntu 也是因为源 的关系么? 周鼎 :之后其实我尝试过很多其他发行版,比 如 Gentoo,ArchLinux,openSUSE。 用 的 时 间 最 长的其实是 Gentoo,用了整整一年多吧,仅次于 Ubuntu。用 Gentoo 其实真的能学到很多东西。 51CTO :那你 在 接 触 Linux 之 前,做过 开 发 么? 周鼎 :其实中学那会儿开始上网,最初就是因 为对 Web 开发感兴趣。但那个时候不懂,以为 做个静态页面就是 Web 开发了。 51CTO :那后来你在进行 Ubuntu Tweak 开发 的时候,和其他Ubuntu 开发者接触多么? 周鼎 :实际上从有这个想法到把它开发出来, 基本上都是一个人开发。等到用户多了,有一些 人感兴趣了,就有人来主动帮助你。其实都是这 样,你要先把东西做出来以后,才有人来关注你 帮助你,就这样才接触到 Ubuntu 社区里那些开 发者。刚开始很多东西都不懂,比如 ppa 你知道 吗,就是自动打包发布的比较方便的一个途径。 刚开始我是自己打包,自己发布,让别人再来下 载 ;后来就有人告诉我,去 Launchpad 注册,去搞 个 ppa,这样软件的发布和更新都比较方便。 51CTO :那你其实一开始还不是在 Launchpad 上,就是单包发布? 周鼎 :一开始我是在 Google Code 上做,后来 才转到 Launchpad 上。这些都是后来一些有经 验的人告诉我的,算是有个引路人吧。其实现在 如果有人对 Ubuntu 开发感兴趣的话,我肯定会 人物简介: 周鼎(TualatriX),浙江宁波人氏。在校期间创建了Ubuntu Tweak自由软件项目,此外还是HZLUG(杭州Linux用户组) 的组织者。热爱自由软件。专注于Linux的桌面开发及系统应 用,对图形技术及交互设计有所研究。使用Ubuntu Server做服 务器。工作之余喜欢电影、摄影、音乐、阅读和远足。 个人博客:http://imtx.me/ 采访/杨赛 004 《Linux 运维趋势》投稿信箱: yangsai@51cto.com 杂志订阅 : http://os.51cto.com/art/201011/233915.htm 51CTO Linux 频道 :http://os.51cto.com/linux/ 人物 People 004 告诉他这些步骤,不会让他走弯路。我一开始算 是走了不少弯路。这些东西都需要有人来引导 比较好。 51CTO :那你一开始是在邮件列表里发布,然 后其他人在邮件里给你指导么? 周鼎 :不是在邮件列表里面。那时我注册了 个域名,搞了个 Ubuntu Tweak 的英文官方网站。 我觉得这个比较重要,因为你开发的东西,如果 不用英文的,国内开发这方面的人比较少(当然 现在多一些了),就不容易推广。我当时虽然说 英语比较差,各方面都不懂,但我还是用英语发 布出来,现在想来是非常正确的选择。 51CTO :那你后来跟其他项目的人是怎么认 识的?比如 Debian 的 Aron Xu,和红帽的Caspar Zhang 他们? 周鼎 :好像也不是因为 Ubuntu Tweak 这个项 目认识的。因为我除了开发 Ubuntu Tweak 之外, 还玩很多 Linux 其他方面的东西。比如 09 年、 10 年那会儿,喜欢研究图形方面的新技术,玩了 之后基本都会写一篇文章,跟中国这边的社区主 要是通过这种方式交流。基本上写了文章,人家 会来你这里留言,然后就互相加好友,也会讨论 一些技术之类的。 最简单的总结其实就两个字 :分享。我把我 知道的分享出去,然后感兴趣自然的也就找上来 了。 51CTO :那么就你所知,其他 Canonical 的员 工是不是也有很多像你这样的情况,一开始是 Ubuntu 第三方开发者的? 周鼎 :那个 Compiz 你知道吗? Compiz 的开 发者 smspillaz 之前也是一个独立开发者,现在 也是 Canonical 的员工。 51CTO :接下来这个问题是很多人一直以来 对 Ubuntu 的质疑。有些人说 Ubuntu 对 Linux 内 核的代码贡献少,再就是Debian社区的人说 Ubuntu 开发的二进制包跟 Debian 不兼容之类的。 对于这一点,你是怎样看的? 周鼎 :对第一个问题,我觉得这是非常工程师 的想法。一想起 Ubuntu 不好就说它对内核贡献 少,我觉得这完全没有从用户的角度去想。实际 上市场是非常重要的,你觉得呢? 据 我 所 知,我 们 很 多 玩 Linux 的 朋 友,都 会 有一个共识。用一句比较流行的话来说就是, “Ubuntu 是我们的初恋”。就是说,即使他现在在 用 Fedora,或者在用 Debian,或者已经在红帽或 其他家工作了,但是我周围玩 Linux 的这些朋友, 基本都是一开始因为 Ubuntu 而喜欢上 Linux,从 而最终把它当作自己的职业的。所以说你觉得 这是不是贡献? 51CTO :那么 关 于 Debian 社 区 那 边 的 想 法 呢? 周鼎 :你说二进制不兼容的问题啊。这个问 题主要是因为两边的开发模式不同。你也知道 Debian 没 有 具 体 的 时 间 表。 当 然 Debian 倒 是 也有发布计划,比如一年,18 个月这样,但是它 跳票会比较严重。这就会造成一个情况,因为 Debian 它要保证很稳定,底层的库都会保持在一 个稳定的版本 ;但是 Ubuntu 会用一个比较新一 点的,就是从 Debian 测试版里面取出来的东西, 作为 Ubuntu 下一个版本的基础。所以说,因为 它是比较底层的库,然后 Ubuntu 上的很多软件 是在比较新的库上开发出来的,在底层库版本较 低的 Debian 稳定版上自然无法正常的跑起来。 所以这个问题是两个发行版开发模式不协 调造成的,不是说 Ubuntu 专门为了搞出来,不跟 Debian 兼容。其实 Ubuntu 上能共享的东西都是 尽量共享出来的。 我觉得这几年,Debian 跟 Ubuntu 的关系应该 比最初那几年好不少,没看到那么多争议了。再 过几年应该双方关系都会比较好,可以一起做些 什么东西。 51CTO :希望如此!那么本次专访就到此结 束,感谢周鼎接受我们的采访! 本文有删节,完整内容见原文 : os.51cto.com/art/201108/281538.htm 005 《Linux 运维趋势》投稿信箱: yangsai@51cto.com 杂志订阅 : http://os.51cto.com/art/201011/233915.htm 51CTO Linux 频道 :http://os.51cto.com/linux/ 八卦 News 005 Linux令人惊奇的用处,你见过么? 【Linux 摩 托 车】Mavizen 的 TTX02 是 首 个 配 置了计算机、USB 接口以及 IP 地址的比赛用摩 托车。维护人员可以通过 WLAN 调试摩托车, 时速可达 210 公里 / 小时,整个系统基于 Linux。 【Linux 咖 啡 机】在 德 国 Nurmberg 的 嵌 入 式 大会上的一个展示用咖啡机。这个咖啡机基于 Linux,采用 Qt 框架。 ——无所不在的Linux 【Linux 邮局】过去十年间,美国邮政局已经在 大量使用以 Linux 为核心的邮件处理系统。你也 可以在 Zazzle.com 上买到 Linux 主题邮票。 【Linux 红绿灯】 Peek Traffic 正在为 lowa,纽约以及洛杉矶的 部分地区提供交通灯,而其系统使用的是 Linux。 【Linux 机器人】2001 年的时候,Isamu 成为了 第一个运行在 Linux 上的拟人机器人。从那以后, 很多机器人都开始采用 Linux,从叫做 Pleo 的恐 龙玩具到叫做 Katana 的工业生产用机械臂。 【Linux 挤奶机】DeLaval 是一家农场器械制造 商。其制造的挤奶机基于 Linux,并且可以通过 无线远程控制器来操作。 内容来源 : os.51cto.com/art/201004/193251.htm 006 《Linux 运维趋势》投稿信箱: yangsai@51cto.com 杂志订阅 : http://os.51cto.com/art/201011/233915.htm 51CTO Linux 频道 :http://os.51cto.com/linux/ 专题 Special 006 本期专题:Linux的开发 主编的话 针对 Linux 20 周年这个特殊的时间,《Linux 运维趋势》专门就 Linux 开发这个话题制作了本 期特刊。Linux 开发与 Linux 运维的差别非常大, 虽然涉及到服务器管理的工作也会用到一些脚 本语言,但是这些跟“制作一个操作系统”完全 不是一个概念。 所以,本期《Linux 运维趋势》,其实完全脱离 了运维的范畴。制作这样一个特刊,主要是希望 让大家了解,这样一个复杂的操作系统是如何被 创造的。Linux 的创造过程包括内核、驱动模块 开发、图形开发等方面,而参与者们还需要了解 整个 Linux 社区的开发模式和协作方式,以及社 区的文化。 Linux 开发涉及太多方面,这里收集的资料非 常有限,很多文章时间比较久远,但相当经典。 如果您对 Linux 开发不感兴趣,可以直接等待《趋 势》下期发布 ;但如果您因此对 Linux 开发产生 了一点兴趣,那也算是对整个 Linux 事业产生了 一点点贡献啦。 007 《Linux 运维趋势》投稿信箱: yangsai@51cto.com 杂志订阅 : http://os.51cto.com/art/201011/233915.htm 51CTO Linux 频道 :http://os.51cto.com/linux/ 专题 Special 007 Linux内核开发者是如何“炼成”的 当新的功能加进内核的时候,通常建议作者把解释这个新功能的文档也加进内核。如果一个内核变动导致 了内核对用户空间界面的改变,建议你把这个信息或者一个解释了这个变动的manpage的补丁发送给手册页的 维护者 mtk-manpages@gmx.net。 你想知道如何成为一个 Linux 内核开发者么? 这篇文档的目的,就是描述你需要经历的过程, 并告诉你如何和社区一起工作。 内核几乎全是用 C 语言写成的。一些架构相 关的部分是用汇编语言写成的。熟练掌握 C 语 言是内核开发的必备条件。汇编语言(任何架构) 的知识不是必须的,除非你准备做某个架构的底 层开发。 内核开发采用 GNU C 和 GNU 工具链。虽 然它符合 ISO C89 标准,但还是使用了一些标 准中没有的扩展。也就是说,内核是自成体系的 C 环境,它并不依赖标准 C 库,所以某些 C 语言 标准是不支持的。 这些标准的知识都有很好的文档。不要期望 别人会遵照你或者你公司的行事方式。 法律问题 Linux 内核源代码依照 GPL 发布。请参考源 代码树下的 COPYING 文件,以获取有关这个许 可证的详细信息。如果你对这个许可证有疑问, 请联系你的律师,而不要在 Linux 内核邮件列表 里询问。邮件列表里的人们不是律师,你不应该 依赖于他们对于法律问题的解释。 文档 当新的功能加进内核的时候,我们建议作者 把解释这个新功能的文档也加进内核。如果一 个内核变动导致了内核对用户空间界面的改变, 建议你把这个信息或者一个解释了这个变动的 manpage 的补丁发送给手册页的维护者 mtk- manpages@gmx.net。 一个内核源代码树里通常包含如下需要阅读 的文件 : README Documentation/Changes Documentation/CodingStyle Documentation/SubmittingPatches Documentation/SubmittingDrivers - Email 内容 - Email 格式 -发送给谁 遵守所有这些规则并不能保证成功(对所有 的补丁都需要进行内容和风格的详细检查),但 是不遵守这些规则就一定不会成功。 成为一个内核开发者 如果你对 Linux 内核开发一无所知,你可以看 看 Linux KernelNewbies 项目 : http://kernelnewbies.org 这个网站有有关代码组织,子系统,当前项目 (代码树之内的和之外的)的基本信息。它也描 述了一些基本的“物流”信息,比如怎么样编译 内核和怎么样打补丁。 如果你不知道从何处起步,但是你想找一些 任务来做以加入内核开发社区,请看一下 Linux Kernel Janitor 项目 : http://janitor.kernelnewbies.org/ 这是一个很好的起步的地方。它描述了一些 相对来说简单的内核中需要清理的和解决的问 题。和负责这个项目的开发者一起工作,你会学 到如何令你的补丁进入 Linux 内核树的基本知 识,而且可能会为你指明下一步的发展方向。 如果你已经有了一段代码想要放到内核树 里,但 是 需 要 某 种 形 式 的 帮 助,那 么 kernel- 文/Greg KH 译/张乐 008 《Linux 运维趋势》投稿信箱: yangsai@51cto.com 杂志订阅 : http://os.51cto.com/art/201011/233915.htm 51CTO Linux 频道 :http://os.51cto.com/linux/ 专题 Special 008 内核开发者参与 Linux 内核邮件列表的讨论。如 何订阅和取消订阅这个列表的细节可以从这里 找到 : h t t p : / / v g e r . k e r n e l . o r g / v g e r - l i s t s . html#linux-kernel 和社区一起工作 内核社区的目标是提供可能提供的最好的内 核。当你提交了一个补丁等待被收录时,它会被 且仅被该领域的技术权威所检查。所以,你应该 期待什么呢?批评、评论、被要求改动、被要求解 释还是沉默? 记住,这是让你的补丁进入内核的一部分。 你必须能够接受对你的补丁的批评和评论,关于 一个补丁怎样的有用必定会存在不同的意见。 你应该采取合作的态度,愿意改变你的意见以适 应内核的需要。或者至少愿意证明的你的观点 有价值。记住,犯错误是可以接受的,只要你愿 意朝着正确的解决方案努力。 如果对于你的第一个补丁的回应只是一些要 求你改正的意见,这很正常。这并不意味着你的 补丁将不会被接受,这些意见也不是针对你本人 的。你要做的只是改正你的补丁然后重新发送。 本文有删节,完整内容见原文 : 英文原文 51CTO 转载的中文全文 mentors 项目就可以帮你的忙了。这是一个邮件 列表,可以在下面找到 : http://selenic.com/mailman/listinfo/ kernel-mentors 开发流程 Linux 内 核 开 发 流 程 当 前 包 括 一 些 主 内 核 分支,和很多不同的子系统专有的内核分支。 2.6.x 内核树是有 Linus Torvalds 维护的,可以 在 kernel.org 的 pub/linux/kernel/v2.6 目 录 里 找到。它的开发流程是这样的 : -当一个新的内核发布之后,一个为期两个 星期的窗口打开,在这段时间里维护者可以提交 大的补丁给 Linus,通常是已经在 -mm 内核中存 在了一定时间的补丁。推荐的提交补丁的方式 是通过 git(有关 git 的更多信息可以在 http:// git.or.cz/ 找到),但是普通的补丁也是可以的- 两个星期之后一个 -rc1 内核发布,然后现在只 可以再加入不会为内核添加新功能的补丁,因为 那样的补丁可能会影响这个内核的稳定性。请 注意这个时候一个整的新驱动(或者文件系统) 可以被接受。因为只要这个变动是自成一体的 并且不影响它之外的代码的话,就不会有产生回 归的危险。在 -rc1 发布之后,git 可以用来发送 补丁给 Linus,但是这些补丁也需要发到一个公 开的邮件列表里以备审查。 -当 Linus 确信当前的 git(内核代码管理工 具)树已经处于一个合理的健全状态,足够测试 时,一个新的 -rc 就会发布了。目标是每周发布 一个新的 -rc 内核。 -这个过程将会持续到内核被认为可以发布 为止,整个流程会持续大概 6 个星期。 打了此种补丁的内核不适用于追求稳定的系 统中,运行它们比运行其他任何分支都更具冒险 性。 如果你想帮助内核开发流程,请测试并使用 这些内核发布,并在 linux-kernel 邮件列表里提 供回馈,如果你发现任何问题的话,哪怕什么问 题也没有。 在所有其他实验性质的补丁之外,这些内核 补丁通常还会包含在发布时在主线 -git 内核中 已经包含的改动。 -mm 内核没有一个固定的发布计划,但是 通 常 在 每 两 个 -rc 内 核 发 布 间 歇 期 会 发 布 一 些 -mm 内核(1 到 3 个都很常见)。 报告Bug bugzilla.kernel.org 是 Linux 内核开发者追踪 内核 bug 的地方。我们鼓励用户在这个工具中 报告他们发现的所有 bug。 邮件列表 就像上面的一些文档所描述的,大多数核心 009 《Linux 运维趋势》投稿信箱: yangsai@51cto.com 杂志订阅 : http://os.51cto.com/art/201011/233915.htm 51CTO Linux 频道 :http://os.51cto.com/linux/ 专题 Special 009 Linux设备驱动程序之Helloworld 文/余涛 学程序语言,总是以一个 Hello world 开头, 咱们的故事当然要从这个 Hello world 开始。 (1)linux 开源当然少不了源代码的贡献,请 看 : 驱动程序说白了就是提供函数接口给用户空 间的程序调用。在 c 语言中都有 main() 入口, 那设备驱动程序的入口在哪儿呢?你猜对了,就 是 module_init(), 它的参数是一个函数指针,告 诉说咱们的入口在 hello_init()。明白这层意思, module_exit() 就不用多说了吧。 驱动程序说白了就是提供函数接口给用户空间的程序调用。在c语言中都有main()入口,那设备驱动程序的 入口在哪儿呢?你猜对了,就是module_init(),它的参数是一个函数指针,告诉说咱们的入口在hello_init()。明 白这层意思,module_exit()就不用多说了吧。 #include #include MODULE_LICENSE("Dual BSD/GPL"); static int hello_init(void) { printk(KERN_ALERT "Hello,world\n"); return 0; } static void hello_exit(void) { printk(KERN_ALERT "Goodbye, world\n"); } module_init(hello_init); module_exit(hello_exit); ifneq ($(KERNELRELEASE),) obj-m := hello.o else KERNELDIR :=/lib/modules/$(shell uname -r)/build PWD := $(shell pwd) all: $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules endif clean: rm -f *.o *.ko *.mod.c .hello* (3) 好了,下面 make 一番 : #make …… MODPOST 1 modules CC /root/device/hello.mod.o LD [M] /root/device/hello.ko …… 这是生成了 hello.ko 模块(如果没有,多半是 makefile 有问题),接下来可以看结果了。 首先再打开一个终端 B( 刚才 make 的那个不 要关了 , 叫它 A 吧 ),像这样 #tail -f /var/log/messages 然后在 A 终端输入 #insmod ./hello.ko 在 B 终端是不是看到了 localhost kernel : hello,world 然后在 A 终端输入 #rmmod hello 在 B 终端是不是看到了 localhost kernel : Goodbye, world 至此,一个最简单的 helloworld 的设备驱动 演示程序就完成了,是不是挺好玩? 本文有删节,完整内容见原文 : http://www.cnblogs.com/hanyan225/ archive/2010/10/01/1839826.html (2) 连 源 码 都 给 你 了,也 就 不 吝 啬 一 个 makefile 了 : 千万不要说不懂 makefile,大千世界,连地图 都不懂,也不知道咋混的。注意,$(MAKE) 一定 是大写 MAKE。 其中,$(MAKE) -C $(KERNELDIR) SUBDIRS = $(PWD) modules 这句话的意思就是说首先 改变目录到 -C 选项指定的目录 ( 即内核源代 码目录 ),其中保存了内核的顶层 makefile 文件。 SUBDIRS= 选项让该 makefile 在构造 modules 目 标返回之前到模块源代码目录。然后,modules 目标指向 obj-m 变量设定的模块。 010 《Linux 运维趋势》投稿信箱: yangsai@51cto.com 杂志订阅 : http://os.51cto.com/art/201011/233915.htm 51CTO Linux 频道 :http://os.51cto.com/linux/ 专题 Special 010 Linux图形编程用什么开发包? 文/fyplinux GUI 开 发 用 的 多 的 就 是 QT, GTK, WxWidgets. 做一些初级到点,线,面的编程,比如,游戏特 效, 就可以用到鼎鼎大名的 OpenGL 及其附属 库 : OpenGL support libraries(from wikipedia) GLUT -– The OpenGL utility toolkit. SDL - The Simple DirectMedia Layer. GLU - Some additional functions for OpenGL programs. GLee - The OpenGL Easy Extension library. GLEW - The OpenGL Extension Wrangler Library. GLUI - a GUI toolkit made with GLUT GLFW - a portable framework for OpenGL application development. Framebuffer Object - an off-screen rendering extension. GLM - C++ mathematics toolkit for OpenGL based on GLSL specification. SFML - Simple and Fast Multimedia Library. Glux - The OpenGL Utility & Auxiliary Library. GNOME/KDE 是一个桌面环境, 集成了这么 一些组件 (wikipedia): ATK——可达性工具包 Bonobo——复合文档技术 GObject——用于 C 语言的面向对象框架 GConf——保存应用软件设置 GNOME VFS——虚拟档案系统 GNOME Keyring——安全系统 GNOME Print——GNOME 软件打印文档 GStreamer——GNOME 软件的多媒体框架 GTK+——构件工具包 Cairo——复杂的 2D 图形库 Human Interface Guidelines——Sun 微系统公司提供的使得 GNOME 应用软件易于使用的研究和文档 LibXML——为 GNOME 设计的 XML 库 ORBit——使软件组件化的 CORBAORB Pango——i18n 文本排列和变换库 Metacity——窗口管理器 开发, 他们是图形系统中更高层次的抽象。比 方来说, GTK+ 从 2.8 起由 Cairo 来实现其组件 的绘制, 而 Cairo 正和 OpenGL 一样, 是更低层 次的图形库。 OpengGL 只是定义了一组接口, 具体的实现 一 般 由 各 显 卡 厂 商 提 供 (Nvidia,ATI,...),也 因此能更好的利用硬件的性能。所以, 我们可 以看到 OpenGL-compatible 这样标注的显卡。 这 也 从 一 个 侧 面 反 应 了 opengl 的 底 层 性。 仅 以画点,线,面来说,当性能要求高时,应当考虑 opengl。 一般的桌面应用 Gtk 应该够了。 我注意到 GNU Xaos( 一个分形演示软件 ) 用 的是 libx11-dev 来做图形绘制, 那么, libx11 和 gtk 又有什么联系? 拜 读 了 X Window System Architecture Overview HOWTO 以后, 我才明白这之间的关 系 : X window System(X11, Xlib) 提供最底 层的图形应用,Cairo 构建于 X System 上 , 而 GTK 又依赖于 Cairo, Gtk 又是 Gnome 的一部分 . 回 过 头 来, Cairo 和 OpenGl 都 是 比 Gtk+ 更 低层次的抽象, 但他们是同一层次的抽象吗? OpenGL 和 X window system 谁更底层 ? 这里说 : "In the X Window System, OpenGL rendering is made available as an extension to X in the formal X sense: connection and authentication are accomplished with the normal X mechanisms" 也就是说, X system 可以通过 OpenGL 来构 建。 原文 : http://blog.csdn.net/fyplinux/article/ details/3376243 但毫无疑问, GTK, QT 也应该可以画点, 画 线, 但他们设计的目的本来就在于图形界面的 011 《Linux 运维趋势》投稿信箱: yangsai@51cto.com 杂志订阅 : http://os.51cto.com/art/201011/233915.htm 51CTO Linux 频道 :http://os.51cto.com/linux/ 专题 Special 011 在 Linux 下开发GUI应用程序不像在Windows 下那样方便,因为要自己定好编译文件Makefile,就像开发 DOS 程序那样。又由于GUI的特点,必须定位显示在屏幕上控件的位置,而如果没有集成开发环境,光用程序 定位就十分烦琐,因此必须借助第三方的开发工具。 用GTK开发Linux嵌入式GUI应用程序 文/罗贤全 尚朝轩 高勤 一、用 GTK 开发嵌入式 GUI 应用程序 GTK 是 GIMP Toolkit 的缩写,是目前编写图 形界面比较流行的高层函数库之一。Linux 的主 流桌面系统之一的 GNOME 就是用 GTK 开发 出来的。GTK 本是在通用 PC 机上使用,不是 专为嵌入式系统开发的,但由于它的模块化设 计和全 C 编写的特性,兼容性好,运行稳定,且 它的库也比较小,GTK 加上 X 服务器仅占用 2.9M 的硬盘空间。兼顾考虑性能和存储空间, 它完全可以用于开发嵌入式的 GUI 应用程序, 且具有免费从网上获取源代码的优点。 要开发 GTK 应用程序,最先做的是当然是从 网上下载一份源代码并安装。安装步骤如下 : 1、 下载 GTK 源代码包,将其拷贝到开发平 台的指定目录下。 2、 进入 Linux 操作系统,打开终端应用程 序,在控制台下切换当前目录至 GTK 的源代码 包的目录下。 3、 键入以下命令 : gzip -cd gtk-1.2.10.tar.gz | tar xvf - # 在当前目录下解开源代码压缩包 cd gtk-1.2.10 # 进入 GTK 源代码包的最高层目录 ./configure # 产生 Makefile 文件 make # 编译 GTK 源代码 ( 以下必要时必须切换到 ROOT 管理权限 ) rm -rf /install-prefix/include/gtk / install-prefix/include/gdk # 删除旧版本的 GTK( 若有 ) make install # 进行安装 4、为 加 快 图 形 程 序 开 发 的 速 度,还 要 安 装 glade1.2 这个 GTK 开发的辅助工具。 GTK 需要的支持库主要有 GLIB 图形底层函 数库、GD 函数库及一些图形显示处理和数学 库。 二、用 GLADE 解决 GTK 界面布局问题 在 Linux 下 开 发 GUI 应 用 程 序 不 像 在 Windows 下那样方便,因为要自己定好编译文 件 Makefile,就像开发 DOS 程序那样。又由于 GUI 的特点,必须定位显示在屏幕上控件的位置, 而如果没有集成开发环境,光用程序定位就十分 烦琐,因此必须借助第三方的开发工具。 Glade 是专为开发 GTK 应用程序而设计的 辅助工具,它不像 Windows 下的 VB、VC++ 那 样本身带有编译调试系统,但是对布局 GTK 的 控件、调整界面的大小却十分有用,它可以生成 界面布局的源代码。 Glade 生 成 的 源 代 码 主 要 有 main.c, interface.c, callbacks.c, support.c 和相关的 编译所需的文件如 Makefile 等,这些代码生成 了整个应用程序的主要框架,其中 main.c 是 主引导程序很简单,主要完成初始化的工作。 interface.c 是界面布局程序,support.c 包含有 一些必要的支持函数,callbacks.c 是回调函数 文件,也是整个应用程序的主体,glade 只能生 成相关的函数名,绝大部分靠人工手写,它完成 了应用程序的主体功能。 用 Glade 新建一个工程,布局好控件界面后, 在控制台下切换到该工程所在的最高层目录, 入 ./autogen.sh 即可生成 Makefile,下次改程 012 《Linux 运维趋势》投稿信箱: yangsai@51cto.com 杂志订阅 : http://os.51cto.com/art/201011/233915.htm 51CTO Linux 频道 :http://os.51cto.com/linux/ 专题 Special 012 序时,只要在 callbacks.c 里面编辑即可。 编辑完程序后可以自己写 Makefile,那样比 glade 自动生成的要简洁得多。 三、 编写 Makefile 文件编译程序 程序写好后,要真正运行起来还有赖于编译 系统的编译。现在的 Linux 系统主要用的是 GNU MAKE 工具,由软件项目的 Makefile 文件 来实现。编译程序时,GNU MAKE 会读入其对 应的 Makefile 文件,该文件主要是指定各个目 标文件 ( 执行程序、二进制模块和动静态库 ) 是 从哪些源代码文件 ( 也称依靠文件 ) 产生,用什 么样的命令和规则来进行这个产生过程。 由 glade 产 生 的 Makefile 文 件 太 过 繁 杂,对 GTK+ 采用动态编译的方式,也可采用静态方式。 如本嵌入式系统 GTK 要用到 GDK_PIXBUF 函数 库就要用静态编译,因为嵌入式系统的 C 库版 本太低。如要编译的目标文件名为 initform,则 Makefile 文件内容本页下方所示。其中 -Wl,- Bstatic 是静态编译的选项,GTK 用默认的配置 程序 gtk-config libs 设置库和头文件的路 径,它使用动态编译方式。生成 Makefile 文件 后,在控制台下输入 make 命令,嵌入式的 GUI 应用程序就生成了。 本文有删节,完整内容见原文 : http://2.dx1.elecfans.com/l/elecfans. com-%D3%C3GTK%BF%AA%B7%A2Linux% C7%B6%C8%EB%CA%BDGUI%D3%A6%D3% C3%B3%CC%D0%F2.pdf #THE FOLLOWING IS MY MAKEFILE CC = gcc CFLAGS= -Wall -O3 -g GTK_CONFIG_CFLAGS=`gtk-config --cflags` -I/usr/include/gdk-pixbuf-1.0/ GTK_CONFIG_LIBS= `gtk-config --libs` -Wl,-Bstatic -lgdk_pixbuf initform: main.o support.o interface.o callbacks.o $(CC) main.o support.o interface.o callbacks.o -o initform $(GTK_CONFIG_LIBS) main.o: main.c support.h interface.h callbacks.h $(CC) $(CFLAGS) -c main.c -o main.o $(GTK_CONFIG_CFLAGS) support.o: support.c support.h $(CC) $(CFLAGS) -c support.c -o support.o $(GTK_CONFIG_CFLAGS) interface.o: interface.c interface.h support.h callbacks.h $(CC) $(CFLAGS) -c interface.c -o interface.o $(GTK_CONFIG_CFLAGS) callbacks.o: callbacks.c callbacks.h support.h interface.h $(CC) $(CFLAGS) -c callbacks.c -o callbacks.o $(GTK_CONFIG_CFLAGS) clean: rm -f *.o initform 013 《Linux 运维趋势》投稿信箱: yangsai@51cto.com 杂志订阅 : http://os.51cto.com/art/201011/233915.htm 51CTO Linux 频道 :http://os.51cto.com/linux/ 专题 Special 013 在 PC上调试开发板上产生的core文件,需要使用交叉编译器自带的gdb,并且需要在gdb中指定solib- absolute-prefix和 solib-search-path两个变量以保证gdb能够找到可执行程序的依赖库路径。有一种建立配置文件 的方法,不需要每次启动gdb都配置以上变量。 Linux下调试core文件的方法 文/tiechou 在开发和使用 Linux 程序时,引擎有时会莫名 其妙的 core 掉,在网上查了一下,整理了一个简 单的调试 core 文件的方法。 1、什么是core dump? Core,即 core memory,而 dump 就 是 堆 放 的 意思。core dump 又叫核心转储,当程序运行过 程中发生异常,程序异常退出时,由操作系统把 程序当前的内存状况存储在一个 core 文件中, 叫 core dump。 2、如何打开core dump支持? 有的操作系统并没有默认打开 core dump 支 持,需要用 ulimit -c unlimited 语句进行设置, core 文件生成的位置一般在程序运行的当前目 录下,文件名为 core. 进程号 ( 当然不同的系统 也许有所不同,可以查看相手册对路径和文件名 进行设置 ). 3、Core dump的使用方法 首先应该在用 gcc 进行编译时选择 -g 选项, 以便起动 debug 支持,生成可执行文件时 ex,./ ex 运行可执行文件,如果程序当掉,则会生成 一 个 core 文 件,假 设 为 core.1568,则 gdb ex core.1568 进入 gdb,然后再用 where 命令进行 查看即可。 先看看我用的是个什么机器 : $ uname -a 再看看默认的一些参数,注意 core file size 是个 0,程序出错时不会产生 core 文件了。 $ ulimit -a core file size (blocks, -c) 0 …… 写个简单的程序,看看 core 文件是不是会被 产生。 (代码略) $ gcc -Wall -g foo.c $ ./a.out Segmentation fault $ ls -l core.* ls: core.*: No such file or directory 没有找到 core 文件,我们改改 ulimit 的设置, 让它产生。1024 是随便取的,要是 core 文件大 于 1024 个块,就产生不出来了。 $ ulimit -c 1024 $ ulimit -a core file size (blocks, -c) 1024 …… $ ./a.out Segmentation fault (core dumped) $ ls -l core.* -rw------- 1 uniware uniware 53248 Jun 30 17:10 core.9128 注 意 看 上 述 的 输 出 信 息,多 了 个 (core dumped)。 确 实 产 生 了 一 个 core 文 件,9128 是 该进程的 PID。我们用 GDB 来看看这个 core。 $ gdb --core=core.9128 (输出信息略) (gdb) bt #0 0x08048373 in ?? () #1 0xbfffd8f8 in ?? () #2 0x0804839e in ?? () #3 0xb74cc6b3 in ?? () #4 0x00000000 in ?? () 此时用 bt 看不到 backtrace,也就是调用堆栈, 原来 GDB 还不知道符号信息在哪里。我们告诉 它一下 : (gdb) file ./a.out 014 《Linux 运维趋势》投稿信箱: yangsai@51cto.com 杂志订阅 : http://os.51cto.com/art/201011/233915.htm 51CTO Linux 频道 :http://os.51cto.com/linux/ 专题 Special 014 (gdb) bt #0 0x08048373 in sub () at foo.c:17 #1 0x08048359 in main () at foo.c:8 此时 backtrace 出来了。 在程序不寻常退出时,内核会在当前工作目 录下生成一个 core 文件(是一个内存映像,同时 加上调试信息)。使用 gdb 来查看 core 文件,可 以指示出导致程序出错的代码所在文件和行数。 其他总结 1.core文件的生成开关和大小限制 1)使用 ulimit -c 命令可查看 core 文件的生 成开关。若结果为 0,则表示关闭了此功能,不 会生成 core 文件。 2)使 用 ulimit -c filesize 命 令,可 以 限 制 core 文件的大小(filesize 的单位为 kbyte)。若 ulimit -c unlimited,则表示 core 文件的大小不 受限制。如果生成的信息超过此大小,将会被裁 剪,最终生成一个不完整的 core 文件。在调试 此 core 文件的时候,gdb 会提示错误。 2.core文件的名称和生成路径 core 文件生成路径 : 输入可执行文件运行命令的同一路径下。 若系统生成的 core 文件不带其他任何扩展名 称,则全部命名为 core。新的 core 文件生成将 覆盖原来的 core 文件。 1)/proc/sys/kernel/core_uses_pid 可 以 控 制 core 文件的文件名中是否添加 pid 作为扩展。 文件内容为 1,表示添加 pid 作为扩展名,生成的 core 文件格式为 core.xxxx ;为 0 则表示生成的 core 文件同一命名为 core。 可通过以下命令修改此文件 : echo “1″ > /proc/sys/kernel/core_uses_ pid 2)proc/sys/kernel/core_pattern 可 以 控 制 core 文件保存位置和文件名格式。 可通过以下命令修改此文件 : echo “/corefile/core-%e-%p-%t” > core_pattern,可 以 将 core 文 件 统 一 生 成 到 / corefile 目 录 下,产 生 的 文 件 名 为 core- 命 令 名 -pid- 时间戳 3.core文件的查看 core 文件需要使用 gdb 来查看。 gdb ./a.out core-file core.xxxx 使用 bt 命令即可看到程序出错的地方。 以下两种命令方式具有相同的效果,但是在 有些环境下不生效,所以推荐使用上面的命令。 1)gdb -core=core.xxxx file ./a.out bt 2)gdb -c core.xxxx file ./a.out bt 4. 开发板上使用 core 文件调试 在 PC 上调试开发板上产生的 core 文件,需 要使用交叉编译器自带的 gdb,并且需要在 gdb 中 指 定 solib-absolute-prefix 和 solib-search- path 两个变量以保证 gdb 能够找到可执行程序 的依赖库路径。有一种建立配置文件的方法,不 需要每次启动 gdb 都配置以上变量,即 :在待运 行 gdb 的路径下建立 .gdbinit。 配置文件内容 : set solib-absolute-prefix YOUR_CROSS_ COMPILE_PATH set solib-search-path YOUR_CROSS_ COMPILE_PATH set solib-search-path YOUR_DEVELOPER_ TOOLS_LIB_PATH handle SIG32 nostop noprint pass 注意 :待调试的可执行文件,在编译的时候需 要加 -g,core 文件才能正常显示出错信息!有 时候 core 信息很大,可以通过挂载到 PC 的方式 来规避这一点。 本文有删节,完整内容见原文 : http://tiechou.info/?p=10 015 《Linux 运维趋势》投稿信箱: yangsai@51cto.com 杂志订阅 : http://os.51cto.com/art/201011/233915.htm 51CTO Linux 频道 :http://os.51cto.com/linux/ 专题 Special 015 Linux内核/模块开发常见问题集 文/vatano 1. 请推荐一些好的Linux内核参考书? a.《Linux Device Drivers》 b.《Understanding the Linux Kernel》 c.《Linux 内核源代码情景分析》,分上下两 册 d.《边干边学- Linux 内核指导》 e.《Linux 内核 2.4 版源代码分析大全》 f.《Linux Kernel Development》 g.《IA-64 Linux Kernel: Design and Implementation》 2. 源代码问题 2.1 如 何 得 到 某 一 版 本 的 Linux 内 核 源 代 码? a. http://www.kernel.org ,这是 Linux 内 核版本的发布网站。 (本部分其余内容略) 3. 模块编程问题 3.1 模块编程需要注意什么? a. 在 gcc 编译选项中增加 -c b. 在 gcc 编 译 选 项 中 定 义 两 个 宏 :- DMODULE -D__KERENL__ 或直接在源文件中定义这两个宏 : #define MODULE #define __KERNEL__ c. 在源文件中包括 module.h 文件 : #include d. 假定你现在运行的内核的源码目录绝对 路 径 是 MyKernelSrcPath,在 gcc 编 译 时 增 加 选 项 : -I $MyKernelSrcPath/include ( 如 -I / usr/src/linux/include) 注意 MyKernelSrcPath 必须是指向与当前 运行的系统内核匹配的(版本一致)、能编译成功 的 ( 保证源代码目录的完整性 )、已经 config 过 的 ( 保证有 .config 和 include/linux/autoconf.h 文件 ) 内核源码目录 注意 :通常不要 -I /usr/include/linux e. 如果要用 inline 功能,需要在 gcc 编译选 项中增加 -O2 f. init_module() 函数必须 return 0,否则会 出现 Device or resource busy 错误。 3.2 为什么 insmod 一个模块时显示版本不 匹配? a. 见上面 3.1->d b. 某些时候用 insmod -f 能够成功加载,但 需谨慎使用。 3.3 为什么出现 Unresolved Symbol 错误? a. 首先查看文件 /proc/ksyms,看内核有没 有输出这个符号,不同的内核版本如 2.2 和 2.4 输出的符号会有些变化。 b. 如果内核输出的符号带有版本控制信息 如符号 printk_R12345678,则性质同问题 3.2。 c. 注意 :现在有很多版本都不输出 sys_call_ table 了,另想办法吧! 3.4 为什么出现 no license 错误? 在源文件加入下面一行(加在文件头部,尾部 均可): MODULE_LICENSE("GPL"); 3.5 为什么看不到用 printk 打印的信息? a. 打印消息受级别的限制 , 消息级别可以 通过 printk 设置 , 如 : printk("something"); /* 其 中 0<=n<=7 */ 假设控制台的消息级别为 m, 当 n /proc/sys/kernel/printk b. 用 dmesg 命令看。 c. 当系统运行 klogd 和 syslogd 时,内核消 息就会由 klogd 分发到 syslogd,syslogd 会根据 配置文件 /etc/syslog.conf 作相应处理,具体可 以查看 syslogd 和 syslog.conf 的 man 页。 4. 内核开发问题 4.1 怎么制作、使用 patch 文件? a. patch 文 件 是 由 diff 命 令 生 成 的 , 使 用 patch 文 件 用 patch 命 令,具 体 可 查 看 diff 和 patch 的 man 页和 info。 b. diff 命令的常用选项组合是 urN,如 : diff -urN linux/ my_linux/ >mypatch.diff 4.2 在内核中可以使用系统调用吗? a. 可以。内核源代码中就有使用系统调用 的例子,如 open()、execve() 等。 b. 在内核中使用系统调用必须要在源文件 中包括以下两行 : #define __KERNEL_SYSCALLS__ #include c. 内核中使用系统调用的相关定义可查看 文 件 include/asm/unistd.h。 如 果 要 用 的 系 统 调用该文件中没有定义,可以按照其格式自行添 加。 d. 如果要在模块中使用系统调用,必须要自 己定义 errno 如 : int errno; 内核在 lib/errno.c 中定义了 errno,但该符号 不导出,所以模块编程时需要自己定义 errno,用 以存放系统调用出错号。 4.3 在内核中怎么打开并操作一个文件? a. 直接用 open()、read() 等系统调用,见问 题 4.2。 b. 用 filp_open() 函数打开文件,得到 struct file * 的指针 fp。使用指针 fp 进行相应操作, 如 读 文 件 可 以 用 fp->f_ops->read。 最 后 用 filp_close() 函 数 关 闭 文 件。filp_open()、filp_ close() 函 数 在 fs/open.c 定 义,在 include/ linux/fs.h 中声明。 c. 自己写包装函数,可参照文件 fs/exec. c 中 的 open_exec() 和 kernel_read() 函 数。 在 LinuxForum 上有些代码可以参照。 4.4 在 内 核 中 读 写 文 件 时 为 什 么 会 出 现 EFAULT(-14) 错误? a. 内核文件系统提供的 read() 和 write() 之类的函数,期望是对用户态程序服务的,所以 它会验证读写缓冲区不超过用户空间的上限即 0xC000 0000。但现在内核中要读写文件,缓冲 区在内核中即地址会超过 0xC000 0000。 b. 在 读 写 文 件 前 先 得 到 当 前 fs :mm_ segment_t old_fs=get_fs(); 并设置当前 fs 为内 核 fs :set_fs(KERNEL_DS); 在读写文件后再恢复 原 先 fs: set_fs(old_fs) ;set_fs()、get_fs() 等 相关宏在文件 include/asm/uaccess.h 中定义。 4.5 怎么在系统中增加一个自己的系统调 用? 去 http://www.xenotime.net/linux/ syscall_ex/ 看看。 4.6 怎么在内核中加入自己的驱动程序? a. 去 IBMDW 看看,了解一下整个内核的配 置编译系统。 b. 在相应位置建立自己的源码目录、文件、 Makefile 等。 c. 修改上层 Makefile,把自己的程序加入到 内核编译系统中。 d. 修改上层 Config.in,把自己的程序加入到 内核配置系统中。 e. 确保自己的初始化函数被调用。有两种 方法,一是显式调用,另一种方法是用 initcall, 用宏 module_init 来申明你的初始化函数,操作 系统在初始化到一定阶段后会自动通过 init/ main.c 中的 do_initcalls() 函数来统一调用这些 初始化函数。 本文有删节,原文载于水木清华 BBS,转载地 址 :飘渺水云间 017 《Linux 运维趋势》投稿信箱: yangsai@51cto.com 杂志订阅 : http://os.51cto.com/art/201011/233915.htm 51CTO Linux 频道 :http://os.51cto.com/linux/ 专题 Special 017 友情推广:Linux 20周年线下活动总结 报道/51CTO系统频道 8 月 28 日,OpenSoSE 社区和中标软件在国内 北京、武汉、上海、苏州、南京等五大城市,联合各 地的学校和开源社区团体举办了针对 Linux 20 周年的线下庆祝会,各个城市的 Linux 爱好者和 开发者们聚在一起进行了分享。 51CTO 系统频道编辑去北京地区的活动观 摩了一番,四场讲座的内容都很不错,嘉宾相 当给力。对于其他四个城市的活动,也大概从 OpenSoSE 网站上放出的总结资料了解了一些。 虽然规模和内容上还及不上 Linux 基金会在日 本、巴西、北美地区举办的 LinuxCon 大会,但对 于国内的 Linux 开发者而言,这样的交流机会已 经相当不错。 下一个十年,中国将成为 Linux 的重要市场, Linux 厂商们已经纷纷进入中国,Linux 基金会也 已经成立了中国分支,相信以后这样的机会会越 来越多,LinuxCon 这样规模的会议在中国举办可 能也不会太遥远了。 下 面 分 享 一 下 庆 祝 会 上 几 位 嘉 宾 的 演 讲 PPT : LVS创始人章文嵩博士的感悟分享 GDB专家朱辉的现场演示 Ubuntu Tweak作者周鼎的回顾 Native Linux KVM Tool作者贺俊的技术分享 招募启事 《Linux 运维趋势》的建设需要您的加 入! 您可以通过如下方式参与我们杂志的 建设 : 1、推荐文章 无论是您在互联网上看到的好文章,还 是您自己总结 / 整理的资料 ;无论是英文 还是中文 ;无论是入门的还是高端的,都欢 迎推荐!您可以直接在技术圈中分享 : http://g.51cto.com/linuxops 2、投稿 如果您愿意与大家分享您技术经验的 热诚,那么欢迎您的投稿!原创或译文均 可,稿件在 51CTO 首发可领取稿酬 :) 投稿信箱 :yangsai@51cto.com 3、推广与意见 感谢各种推荐,欢迎各种意见反馈。 反馈可发送至《Linux 运维趋势》新浪 微群 : http://q.weibo.com/121303 或在新浪微博 @51CTO 系统频道 下期预告 下期主题为 : Linux 服务器故障排除,敬请期待! 本刊为月刊,预定每月发布日期为 : 每个月的第二个星期五 您可以通过如下方式检查新刊发布 : 1、电子邮件订阅 : os.51cto.com/art/201011/233915.htm 2、RSS 订阅 : www.51cto.com/php/rss.php?typeid=777 《Linux 运维趋势》是由 51CTO 系统频 道策划、针对 Linux/Unix 系统运维人员的 一份电子杂志,内容从基础的技巧心得、实 际操作案例到中、高端的运维技术趋势与 理念等均有覆盖。 《Linux 运维趋势》是开放的非盈利性电 子杂志,其中所有内容均收集整理自国内 外互联网(包含 51CTO 系统频道本身的内 容)。对于来自国内的内容,编辑都会事先 征求原作者的许可(八卦,趣闻 & 数字栏 目例外)。如果您认为本杂志的内容侵犯 到了您的版权,可发信至 yangsai@51cto. com 进行投诉。 往期回顾 2010.9,000 期, 运维自动化 2010.10,001 期, 监控与报警 2010.11,002 期, 可用性 2010.12,003 期, 运维与开发 2011.01,004 期, 瓶颈分析 2011.02,005 期, 内网开发环境 2011.03,006 期, 备份 2011.04,007 期, 迁移 2011.05,008 期, 双机操作 2011.06,009 期, Puppet 2011.07,010 期, 日志分析 2011.08,011 期, iptables 更多汇总见《Linux 运维趋势》专题 制作团队 本期责编 :李晶 封面制作 :魏峰 以及热心投稿、帮助审稿的热心网友们
还剩17页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 5 金币 [ 分享pdf获得金币 ] 0 人已下载

下载pdf

pdf贡献者

njrq

贡献于2012-05-21

下载需要 5 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf