13. 软件开发

问:如何编译程序?
问:如何将 XXX 移植到 Linux?
问:我可以在 386 上使用为 486 编译的代码或编译器吗?
问:gcc -O6 是做什么用的?
问:编译内核时出现错误该怎么办?
问:如何创建共享库?
问:为什么我的程序这么大?
问:如何防止链接带有数学函数的程序时出错
问:如何在 Linux 下编写 XYZ 程序
问:如何升级/重新编译内核
问:什么是 .gz 文件?什么是 .tgz 文件?什么是 .bz2 文件?还有...?
问:linux/*.hasm/*.h 在哪里?
问:配置 Emacs 的默认设置

问:如何编译程序?

答:大多数 Linux 软件是用 C 语言编写的,并使用 GNU C 编译器编译。GCC 是每个 Linux 发行版的一部分。最新的编译器版本、文档和补丁位于 ftp://ftp.gnu.org/pub/gnu/

用 C++ 编写的程序必须使用 GNU G++ 编译器编译,它也包含在 Linux 发行版中,并且可以从与 GCC 相同的位置获得。

要构建 2.0.x 版本的内核,您将需要大约 GCC 2.7.2.x 版本。尝试使用不同的编译器(如 GCC 2.8.x、EGCS 或 PGCC)构建早期的 Linux 内核可能会由于与 GCC 相关的代码依赖性而导致问题。内核版本 2.2、2.4 和 2.5 开发内核应该可以使用更新的编译器正确编译。

有关 EGCS 编译器的信息请访问 https://gnu.ac.cn/software/gcc/gcc.html

请注意,目前,内核开发人员不回复早期内核的错误请求,而是专注于开发 2.5.x 版本内核并维护 2.2.x 和 2.4.x 版本内核。

[J.H.M. Dassen, Axel Boldt]

问:如何将 XXX 移植到 Linux?

答:一般来说,*nix 程序几乎不需要移植。只需按照安装说明进行操作即可。如果您不知道并且不知道如何找到安装过程中提出的一些问题的答案,您可以猜测,但这往往会产生有缺陷的程序。在这种情况下,您最好请别人来做移植。

如果您有一个类似 BSD 的程序,您应该尝试在编译行的适当部分使用 -I/usr/include/bsd-lbsd

问:我可以在 386 上使用为 486 编译的代码或编译器吗?

答:可以,除非是内核。

GCC 的 -m486 选项用于为 x486 机器编译二进制文件,它仅更改某些优化。这会产生稍大的二进制文件,这些文件在 486 上运行速度稍快。它们在 386 上仍然可以正常工作,但性能会略有下降。

但是,从 1.3.35 版本开始,如果内核配置为 486 或 Pentium,则会使用 486 或 Pentium 特定的指令,因此在 386 上无法使用。

GCC 可以配置为 386 或 486;唯一的区别是,将其配置为 386 会使 -m386 成为默认值,而配置为 486 会使 -m486 成为默认值。在任何一种情况下,这些都可以在每次编译时或通过编辑来覆盖/usr/lib/gcc-lib/i*-linux/ n.n.n/specs.

有一个 GCC 的 alpha 版本,它知道如何针对 586 进行良好优化,但它非常不可靠,尤其是在高优化设置下。Pentium GCC 可以在 ftp://tsx-11.mit.edu/pub/linux/ALPHA/pentium-gcc/ 上找到。

据称,普通的 486 GCC 使用 -m386 为 Pentium 生成更好的代码,或者至少稍小一些。

问:gcc -O6是做什么用的?

答:目前,与 -O2 (GCC 2.5) 或 -O3 (GCC 2.6, 2.7) 相同。任何大于该数字的数字都执行相同的操作。较新内核的Makefile使用 -O2,您可能也应该这样做。

问:编译内核时出现错误该怎么办?

答:请参阅前面关于头文件的问题。

请记住,当您将补丁应用于内核时,您必须使用-p0-p1选项:否则,补丁可能会被错误地应用。有关详细信息,请参阅 patch 手册页。

ld: unrecognized option -qmagic意味着您应该从 ftp://tsx-11.mit.edu/pub/linux/packages/GCC/ 获取更新的链接器,文件为binutils-2.8.1.0.1.bin.tar.gz.

问:如何创建共享库?

答:对于 ELF

 $ gcc -fPIC -c *.c
 $ gcc -shared -Wl,-soname,libfoo.so.1 -o libfoo.so.1.0 *.o

对于a.out,获取tools-n.nn.tar.gztsx-11.mit.edu/pub/linux/packages/GCC/src/。它附带了文档,将告诉您该怎么做。请注意,a.out共享库是一项非常棘手的事情。考虑将您的库升级到 ELF 共享库。请参阅 ELF HOWTO,网址为 ftp://metalab.unc.edu/pub/Linux/docs/HOWTO/

问:为什么我的程序这么大?

答:对于 ELF 编译器(关于 ELF?glibc?),可执行文件过大的最常见原因是您正在使用的库之一缺少相应的 .so 库链接。应该有一个类似libc.so的链接,对于每个像libc.so.5.2.18.

这样的库。使用a.out编译器,可执行文件过大的最常见原因是 -g 链接器(编译器)标志。这会生成(以及输出文件中的调试信息)一个静态链接的程序,该程序包含 C 库的副本,而不是动态链接的副本。

其他值得研究的是 -O-O2,它们启用优化(检查 GCC 文档),以及 -s(或 strip 命令),它们从生成的二进制文件中剥离符号信息(使调试完全不可能)。

您可能希望在非常小的可执行文件上使用 -N(使用 -N 时小于 8K),但除非您了解其性能影响,否则不应这样做,并且绝对不要对守护程序这样做。

问:如何防止链接带有数学函数的程序时出错

答:旧版本的运行时库在 C 运行时库中包含了数学库。编译时不必单独指定数学库。如果编译器在链接使用数学函数的程序时生成如下消息

 /tmp/ccDUQM4J.o: In function "main":
 /tmp/ccDUQM4J.o(.text+0x19): undefined reference to "sqrt"
 collect2: ld returned 1 exit status 

您需要使用-lm选项与 GCC 链接以链接数学库

 # gcc -o program program.c -lm 

还要确保在源文件中使用语句#include <math.h>在源文件中。

[Florian Schmidt]

问:如何在 Linux 下编写 XYZ 程序

答:阅读手册或关于 Unix 的好书以及手册页(输入man man)。有很多 GNU Info 文档,它们通常作为教程更有用。运行 Emacs 并键入 F1-i,或者如果您没有或不喜欢 Emacs,则键入 info info。请注意,Emacs libc 节点可能无法准确描述最新的 Linux libc 或 GNU glibc2。但是 GNU 项目和 LDP 始终在寻找志愿者来升级其库文档。

无论如何,现有的 Texinfo 文档以及第 2 节和第 3 节中的手册页应该提供足够的信息来入门。

与所有自由软件一样,最好的教程是源代码本身。

Linux 手册页的最新版本、有用的 GNU Info 文档的集合以及与 Linux 编程相关的各种其他信息可以在metalab.unc.edu/pub/Linux/docs/man-pages/.

问:如何升级/重新编译内核

答:请参阅 Kernel HOWTOREADME文件,这些文件随内核版本一起发布在 ftp://ftp.cs.helsinki.fi/pub/Software/Linux/Kernel/ 和镜像站点上。请参阅 Linux FTP 存档在哪里?。您可能已经在系统上安装了内核源代码的版本,但如果它是标准发行版的一部分,则可能有些过时(如果您只想自定义配置的内核,这不是问题,但如果您需要升级,则可能是问题。)

对于较新的内核,您可以(并且应该)生成以下所有目标。不要忘记,您可以使用一个命令指定多个目标。

 $ make clean dep install modules modules_install 

另请记住更新模块依赖项。

 $ depmod -a 

此命令可以在启动时自动运行。在 Debian/GNU Linux 系统上,该命令是/etc/init.d/modutils脚本的一部分,并且可以在/etc/rcx.d/目录中适当地链接。有关 depmod 的更多信息,请参阅手册页。

确保您使用的是最新版本的 modutils 实用程序以及所有其他支持软件包。请参阅内核源代码树中的文件Documentation/Changes以获取具体信息,并务必查阅 modutils 软件包中的README文件。

请记住,要使新内核启动,您必须在将内核复制到根分区后运行 lilo。某些内核中的 Makefile 有一个特殊的zlilo目标用于此;尝试

 $ make zlilo 

但是,在当前系统上,您可以简单地复制zImagebzImage文件(在arch/i386/boot/中)到根文件系统上的/boot/目录,或使用 dd 命令复制到软盘。另请参阅问题:如何让 LILO 引导内核映像?

次版本号为奇数的内核版本(即 1.1.x、1.3.x)是测试版本;稳定的生产内核具有偶数次版本号(1.0.x、1.2.x)。如果您想尝试测试内核,您可能应该订阅 linux-kernel 邮件列表。请参阅 有哪些邮件列表?

网站 http://www.kernelnotes.org/ 包含大量信息和指向其他站点的链接,这些站点提供有关 Linux 内核更新的信息。

另请参阅 为什么升级内核后我的 PCMCIA 卡无法工作?如何让 LILO 引导内核映像? 的答案。

答:或者,在 Debian GNU/Linux 系统上,从 Debian 存档或 Debian GNU/Linux CD 获取内核源代码包。然后,按照README文件中的说明进行操作,该文件位于kernel-package子目录中。

问:什么是.gz文件?什么是.tgz?什么是.bz2?还有...?

答:.gz(和.z) 文件是使用 GNU gzip 压缩的。您需要使用 gunzip(它是 gzip 命令的符号链接,大多数 Linux 安装都附带该命令)来解压缩文件。

.taz, .tar.Z.tztar 文件(使用 tar 创建)并使用 compress 压缩。标准的 *nix compress 是专有软件,但存在像 ncompress 这样的免费等效软件。

.tgz(或.tpz) 是使用 gzip 压缩的 tar 文件。

.bz2.bz2

.lsm是一个 Linux 软件地图 条目,以简短文本文件的形式。有关 LSM 项目和 LSM 本身的详细信息,请访问 ftp://metalab.unc.edu/pub/Linux/docs/ 上的子目录。

.deb是一个 Debian 二进制软件包 - Debian GNU/Linux 发行版使用的二进制软件包格式。它使用 dpkgdpkg-deb 进行操作(在 Debian 系统上可用,也可从以下网址获取:http://ftp.debian.org/pool/main/d/dpkg/。如果您使用匿名 FTP,请连接到:ftp://ftp.debian.org/debian/pool/main/d/dpkg/)。

.rpm是一个 Red Hat RPM 软件包,在 Red Hat 和类似发行版中使用。

.sit是使用 StuffIt(一种商业程序)制作的压缩 Macintosh 存档。StuffIt 的制造商 Aladdin Systems Inc. 具有一个免费的解压缩实用程序,可以解压缩这些存档。您可以从 http://www.aladdinsys.com/expander/ 下载它。

file 命令通常可以告诉您文件是什么类型。

如果您发现当您尝试解压缩文件时 gzip 报错,您可能是错误地以 ASCII 模式下载了它。您必须以二进制模式下载大多数内容get,才能下载文件。

问:linux/*.hasm/*.h?

在哪里?答:文件/usr/include/linux//usr/include/asm//usr/src/kernel*/.

如果您没有内核源代码,请下载它们。请参阅 如何升级/重新编译内核 的答案。

然后,使用 rm 删除任何垃圾,并使用 ln 创建链接

 $ rm -rf /usr/include/linux /usr/include/asm
 $ ln -sf /usr/src/linux/include/linux /usr/include/linux
 $ ln -sf /usr/src/linux/include/asm-<architecture> /usr/include/asm

汇编语言文件驻留在特定于体系结构的目录中,因此您需要链接/usr/src/include/asm/usr/src/linux/include/asm-i386在 PC 兼容系统上,链接到/usr/src/linux/include/asm-sparc在 Sun Sparc 系统上,链接到/usr/src/linux/include/asm-ppc在 PPC 系统上,依此类推。

您还会发现您可能需要像在新解压的内核源代码树中一样执行“make config”来创建linux/autoconf.h.

问:配置 Emacs 的默认设置

答:在您的主目录中创建一个名为.emacs的文件,其中包含您希望每次 Emacs 启动时运行的 Emacs Lisp 命令。您不会在目录列表中看到该文件。(前导“.”告诉 ls 不要显示它,除非您将-a命令行开关与 ls 一起使用。)

任何类型的 Emacs Lisp 语句都可以在.emacs.emacs文件中工作,包括整个defuns.txt,添加以下语句。这来自 Emacs Texinfo 帮助文档( F1-i,然后 mEmacs 返回):

 (add-hook text-mode-hook
        '(lambda () (auto-fill-mode1)))

这添加了一个语句,每当为该缓冲区输入文本编辑模式时,都会调用一个钩子函数。text-mode-hook的值(它是一个变量)设置为auto-fill-mode(它是一个函数)。

如果您想关闭每个 Emacs 框架顶部的菜单栏,请添加以下语句

 (menu-bar-mode -1)

如果您想包含某人编写的 Emacs Lisp 程序,例如msb.el(一个增强的弹出缓冲区菜单),请确保 lisp 文件位于 Emacs 可以找到它的目录中(通常它将被命名为 Site-lisp),并在.emacs.emacs

 (require 'msb)
 (msb-mode 1) 

文件中添加以下语句.emacs文件中。有关更多信息,请查阅 Texinfo 文档。Emacs 也有一个 FAQ 列表(请参阅:Linux 还有哪些其他 FAQ?)。