最近在看Beginning Linux Programming 4th Edtion(电子版), 自己觉得这本书写的不错,尤其对于我这个菜鸟来说。因此,打算把每一章总结扩充一下记录于此,以备以后复习学习之用。
第一章主要的主要内容为:Linux 简介,简介Linux 程序设计及其程序设计语言,怎样查找开发所需的资源,静态库和共享库。
GNU项目下开发出的主要工具举例:
1、GCC: GNU 的编译器集合,包括C 编译器;
2、G++:一个C++编译器,是GCC的一部分;
3、GDB: 一个源代码级的调试工具;
4、GNU make: GNU make utility to maintain groups of programs,The purpose of the make utility is to determine automatically which pieces of a large
program need to be recompiled, and issue the commands to recompile them.;
5、Bison:一个程序的词法分析工具;
6、bash: an sh-compatible command language interpreter that executes commands read from the standard input or from a file.;
7、GNU Emac: 一个文本编辑器;
8、gimp: gimp - an image manipulation and paint program. The GIMP is the GNU Image Manipulation Program. It is used to edit and manipulate images. It can
load and save a variety of image formats and can be used to convert between formats. GIMP can also be used as a paint program.
当然,GNU 开发出的工具还有很多,包括:电子表格,源代码管理工具,编译和解释程序,Internet
工具集,图形处理程序,还有两个完全基于对象的环境:GNOME 和 KDE.
有很多编程语言都可以再Linux系统开发程序比如:Lisp, Icon, Ada, C, C++, Java, Perl, Python, PHP, Ruby, Objective C, Bourne Shell等等。
Linux 应用程序主要有两种:可执行文件和脚本文件。可执行文件是直接可以再计算机上运行的程序,而脚本文件的执行却需要有另外的程序(即解释器)的支持。Linux 对于文件的名字和后缀没有什么特殊的要求,因为它的文件系统属性指示一个文件(程序)都是可以运行的。可执行文件和脚本文件程序对于用户来说完全没有任何区别的。完成相同功能的程序既可以是可执行文件程序也可以是脚本程序。
当用户登录系统后,用户与系统进行交互的方式:系统通过用户发出的命令在一个给定的目录集(路径)中查找和命令名字相同的文件,如果找到该文件就执行该文件。这个已给定的目录集存储在一个Shell变量PATH中。该变量可已由系统管理员进行设置。该变量中一般包括系统程序存储的目录,它们包括:
/bin: 用于系统启动的二进制文件;
/usr/bin: 用户标准程序,系统提供的通用程序包括程序开发工具;
/usr/local/bin: 本地二进制文件,安装程序;
管理员登录后该变量一般还包括系统管理程序的存放目录比如:/sbin 和 /usr/sbin.
系统可配置组件和第三方应用程序可能安装在子目录:/opt 下。
由系统管理员添加应用程序通常位于/usr/local/bin 或者/opt下。
PATH变量中用冒号(colon)(:) 分割各个目录。
比如执行一下命令查看PATH 中的内容:
$ echo $path
/usr/local/bin:/bin:/usr/bin/:/usr/X11R6/bin
从上面的输出可知Linux 使用正斜线符号(forward slash)(/)分割目录名。
Linux C编译器gcc
第一个程序hello.c
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("Hello World\n");
exit(0);
}
$ gcc -o hello hello.c
$ ./hello
Hello World
C语言的系统标准头文件一般位于/usr/include 对于某些特定的Linux系统可能位于/usr/include/sys 和/usr/include/linux目录下。编译器会在这些标准目录中查找头文件。
我们可以使用-I标志指示编译器在特定的目录中去查找头文件,如
$gcc -I/usr/openwin/include fred.c
以上命令将指示编译器到目录/usr/openwin/include中去查找头文件。
如果想知道某些特殊的定义和函数原型可以使用命令grep,如进入到/usr/include 目录下使用一些命令
$grep EXIT_ *.h
stdlib.h:#define EXIT_FAILURE 1 /* Failing exit status. */
stdlib.h:#define EXIT_SUCCESS 0 /* Successful exit status. */
库——为了方便完成某一功能的函数的重复使用而提前编译的函数的集合。
库文件总是已lib开头,然后的部分说明是哪一类的库,最够已.a (静态库)或者,so (共享库)结束。
比如数学函数库libm.a
编译程序时可以给出库的完全路径也可以使用简写使用-l 标志,如
$gcc -o fred fred.c /usr/lib/libm.a
与
$gcc -o fred fred.c -lm
以上两条命令的功能几乎相同。使用简写法的一个优势是编译器会优先搜索共享库(如果存在共享库)。
与前面提到的指示编译器搜头文件相似,可以使用-L标志指示编译器到指定的目录去搜索库文件,如
$gcc -o x11fred -L/usr/openwin/lib x11fred.c -lx11
编译器将在/usr/openwin/lib 目录下查找库libx11 用于连接程序x11fred
如果函数需要访问共享数据,则可以将这些共享数据放在一个源文件中并用static声明这些变量。
创建静态库举例
1、首先创建两个源文件fred.c 和 bill.c
the first fred.c
#include <stdio.h>
void fred(int arg)
{
printf("fred:we passed %d", arg);
}
the second bill.c
#include <stdio.h>
void bill(char *arg)
{
printf("bill:we passed %s\n", arg);
}
2、使用-c 编译两个源文件
$ gcc -c bill.c fred.c
$ ls *.o
bill.o fred.o
可将现在已经编译生成了两个目标文件
3、接着创建一个头文件lib.h
/*
This is lib.h. It declares the functions fred and bill for users
*/
void bill(char *);
void fred(int);
4、编写一个调用函数void bill(char *)的程序program.c
#include <stdlib.h>
#include "lib.h"
int main()
{
bill("Hello World\n");
exit(0);
}
5、现在可以编译该程序并测试。首先可以明确指示编译器程序需要哪些目标文件,如
$ gcc -c program.c
$ gcc -o program program.o bill.o
$ ./program
bill:we passed Hello World
$
如果编译program 需要分别用到很多目标文件时,这种方法就很不好了!
6、现在我们使用ar 创建一个库并使用它来编译program.
$ ar crv libfoo.a bill.o fred.o
r - bill.o
r - fred.o
$ ls *.a
libfoo.a
可见,现在已经创建了一个库libfoo.a
7、想成功使用库,有些系统比如发源于Berkeley UNIX的系统,需要该库的索引表。
命令ranlib产生归档文件索引,并将其保存到这个归档文件中。在索引中列出了归 档文件各成员所定义的可重分配目标文件。( ranlib generates an index to the contents of an archive and stores it in the archive. The index lists each symbol defined by a member of an archive that is a relocatable object file.)
$ ranlib libfoo.a
现在就可以使用创建的库来生成程序program了,
$ gcc -o program program.o libfoo.a
$ ./program
bill:we passed Hello World
$
当然,也可以使用-l 选项来编译我们的程序
]$ gcc -o program program.c -L. -lfoo
[qj.wang@cdoa02 chapter1]$ ./program
bill:we passed Hello World
$
其中-L. 指示编译器搜索库文件的目录是当前目录, -lfoo 指示使用libfoo.a库
为了克服静态库会占用大量的内存和磁盘空间的缺点(应为使用静态库,每一个应用程序会对使用到的静态库中的函数都将做一个代码和数据的拷贝),开发出来动态库。
可以使用工具ldd查看程序当中使用了哪些动态库,如上面的例子程序program
$ ldd program
libc.so.6 => /lib64/libc.so.6 (0x00000038a1800000)
/lib64/ld-linux-x86-64.so.2 (0x00000038a0800000)
最后给出寻求帮助的方法:
使用命令man 和 info 查询各个命令和库函数的功能和使用方法。