网络操作系统-Linux基础 主讲人:王柯wangk@swnu.edu.cn 西南师范大学计算机科学系2005年春 Red Hat Linux 编程基础 第23章-第25章 第23章Linux 基础编程 ? 23.1 GNU计划的实用程序 ? 23.2 编程环境 ? 23.2 GCC介绍 ? 23.4 GNU make介绍 ? 23.5 gdb调试工具 ? 23.6 编程语言 1. 下载源代码包 foo-1.0.tar.gz 2. tar xvzf foo-1.0.tar.gz 3. cd foo-1.0 4. ./configure 5. make 6. (su) make install 问题 1:配置脚本 configure 是怎么生成的? 问题 2: configure脚本怎么知 道该如何生成 Makefile 幕后英雄 —— GNU Auto Tools: autoconf, automake, libtool, autoscan, autoheader…… GNU Package的典型安装 All in One Solution? ? GNU Auto Tools是上个世纪 90年代开始发展起 来的一系列辅助开发、打安装包的自动化工具。 ? 各种工具分别开发,但是协同工作得很好。比 如 autoconf, automake, libtool等等。 ? 但是,连开发者自己也承认,这套工具虽然好 用,但是学习曲线很陡峭。 ? 困难在于:一套新的思路和习惯,一套自定义 的宏和规则,使用者的交流。 工作原理 autoscan configure.scan configure.in Makefile.am Makefile.in Makefile automake edit aclocal.m4 aclocal configure autoconf ? Autoconf:根据用户提供的 configure.in文件,生成一 个名为 configure的脚本。该脚本可以搜集有关移植性 的平台相关信息,这些信息被用来生成 Makefiles,配 置头文件和其它平台相关的文件。 ?Automake:根据用户提供的一个高层次的生成规则 Makefile.am,生成 Makefile文件的模板 Makefile.in。 Automake生成的 Makefiles符合 GNU的 Makefile标准, 用户无需再手工编写 Makefile文件。 ? Libtool:使得生成内存位置无关的代码且让共享库在 不同平台间移成为可能。它可以不依赖 autoconf和 automake单独运行,另一方面, automake和 libtool可 以无缝地集成使用。 Hello World – Step by Step ? 1. hello.c #include <stdio.h> int main() { printf(“Hello World!\n”); return 0; } ? 2. Makefile.am bin_PROGRAMS = hello hello_SOURCES = hello.c ? 3. configure.in AC_INIT(hello.c) AM_INIT_AUTOMAKE(hello, 0.1) AC_PROG_CC AC_OUTPUT(Makefile) ? 4. aclocal ? 5. autoconf ? 6. automake --add-missing --foreign ? 7. ./configure ? 8. make (make install 安装, make dist 产生安装包 ) configure.in(1) ? 是 configure脚本的输入文件,为了解决在不同 unix变种之间移植程序的问题:库名可能不同, 应用程序名可能不同,结构和常量的定义可能 不同 …… ? configure脚本完成 autoconf与 automake的初始化 工作,为不同的平台定义相应的宏,检测并指 定适当的程序名、库名、结构和常量名等等, 指定要为哪些目录输出 Makefile文件。总之, 为编译程序做好一切准备工作。 configure.in(2) configure.in的八股文 1. 基本初始化部分:包括 AC_INIT (必须 第一个出现 ), AM_INIT_AUTOMAKE(程序包名,版 本号 ), AC_CONFIG_HEADER 2. 可选宏:如 AC_ARG_ENABLE 3. 检测某些程序的存在性 4. 检查程序用到的库 configure.in(3) 5. 检查某些头文件是否存在。 6. 检查 Typedefs and structures。 7. 检查 Functions。 8. 指定在哪些目录输出 Makefile。 Seems troublesome, mmm? Don’t worry, autoscan will do most of the work for you. Makefile.am(1) ? 一种比 Makefile更高层次的规则。只指定要生 成什么目标,它由什么源文件生成,要安装到 什么目录。 ? Just simple and stupid! ? ? 可执行文件: bin_PROGRAMS = foo foo_SOURCES = foo1.c foo1.h foo2.c foo_LDADD = foo3.o -lm foo4.a foo_LDFLAGS = -L<lib_path> foo_DEPENDENCIES = Makefile.am(2) ? 对静态库: lib_LIBRARIES = libfoo.a foo_a_SOURCES = foo_a_LDADD = foo_a_LIBADD = foo_a_LDFLAGS = 只在 make时做静态连接用,不安装的库: noinst_LIBRARIES = libfoo.a …… ? 对头文件: include_HEADERS = foo.h ? 对数据文件: data_DATA = data1 data2 Makefile.am(3) ? 全局变量 (对所有目标都适用 ) INCLUDES = -I/dir1 -I/dir2 LDFLAGS = -L/dir1 -L/dir2 LDADD = foo.o foo.a -lfoo EXTRA_DIST = file1 file2 源程序和一些默认的文件自动打 入 .tar.gz包,其它文件若要进入 .tar.gz包可以用这种办法,比如配置文件 , 数据文件等等 。 SUBDIRS = dir1 dir2 在处理本目录之前要递归处理哪些子目录 Makefile.am(4) ? 标准安装路径 $(prefix) = /usr/local 是所有安装目录的默认前缀,可以通 过 ./configure --prefix=<new_prefix>的方法覆盖。 其它的预定义目录如: bindir = $(prefix)/bin, libdir = $(prefix)/lib, datadir = $(prefix)/share, sysconfdir = $(prefix)/etc, … ? 想定义一个新的安装路径?比如 config, 可定义 confdir = $(prefix)/config, 然后 conf_DATA = file1 file2, 则 file1, file2会作为数据文件安装到 $(prefix)/config目录 下。 Makefile.am(5) ? 尽量用相对路径引用源程序的位置,以 下两个变量是预定义好的: – $(top_srcdir)无论在哪个目录层次,该变量定 义了包含 src目录的目录位置,用于引用源程 序; – $(top_builddir)定义了生成目标文件上最上层 目录,用于引用 .o等编译出来的目标文件。 –…… configure’s Gifts ? configure脚本生成的 Makefile中已经带了 很多常用的目标如: check, all, install, uninstall, clean, dist, distcheck, distclean, tags, maintainerclean. – If configure or make did it, make distclean undoes it. – If make did it, make clean undoes it. – If make install did it, make uninstall undoes it. – If you did it, make maintainer-clean undoes it. libtool简介 ? 生成各种程序库的方便工具。 ? 提供一个统一的接口,程序员不用关心各种烦 人的底层细节:不同的平台的库可能要求不同 的后缀,不同平台对库的安装方法不同,有些 平台不支持动态库等等。 ? 生成高层次的库,称为 libtool library,后缀 是 .la。用它连接时,默认产生动态连接库,也 可以用 -static参数指定生成静态连接库。 ? 既可单独使用又可与 automake和 autoconf一起使 用更加强大、方便。 使用 libtool ? 在 configure.in文件中加上 AC_PROG_LIBTOOL宏,如果原来有 AC_PROG_RANLIB宏,删去它。 ? 在 Makefile.am文件中: lib_LTLIBRARIES = libshell.la libshell_la_SOURCES = object.c subr.c symbol.c 与原来的写法非常相似! ?.la库只能连入 .lo(使用 libtool生成的目标文件 ) libshell_la_LDADD = xmalloc.lo @LTLIBOBJS@ ? 传入库的版本号: libshell_la_LDFLAGS = -version-info 1:0:1 ? 与其它目标文件连接时用 LDFLAGS指定连接的方式 (默认是动态 方式): -static, --all-static指定静态连接。 第24章Linux Shell编程基础 ? 24.1 shell编程的意义 ? 24.2 建立和执行 shell程序 ? 24.3 shell参数 ? 24.4 变量表达式 ? 24.5 控制结构语句 ? 24.6 条件语句 ? 24.7 其他语句 :break exit Shell程序设计 ?Shell的两层含义 : – 指由 Shell命令组成的 Shell命令语言 – 指该命令语言的解释程序 ? 流行的 Shell: – Bourne shell( UNIX System V使用,提示符 $,程序 名是 sh) –C shell( BSD UNIX使用,提示符%,程序名是 csh) –Korn shell(结合了上面两者的优点) – Bash(GNU Linux缺省 Shell) Shell程序设计 ?Shell程序设计语言 – 可以定义变量、关键字 – 有各种控制结构: ? 顺序结构 ? 分支结构 if case ? 循环结构 while for until – 有语法结构 – 可灵活地利用位置参数传递参数值 ? UNIX/Linux程序员常常利用 Shell语言,把 UNIX/Linux命令组合在一起,编写出功能很强但 代码简单的程序。 Shell程序的编写与运行 ? 一个最简单的 Shell程序例子: $cat file1 # count files in current directory ls -l | wc –l $ 说明:用任何纯文本编辑器均可,建议文件名加 .sh表明这是一个 Shell程序文件。 null程序运行方法( 4种) 第一种: $bash file1 第二种: $bash < file1 第三种: $chmod a+x file1 $./file1 第四种: $. file1 Shell程序设计 ?Shell程序设计语言的变量 – 环境变量 – 位置参数变量 – 用户自定义变量 环境变量 ? 与系统的工作环境有关的专用变量: man 指令的搜寻路径 $MANPATH 每隔多少秒检查是否有新的信件 $MAILCHECK 时区 $TZ 执行上一个命令的返回值;成功为 0,失败为 1 $? 执行上一个背景指令的 PID $! 命令行参数个数 $# Shell的所有参数 $* Shell的 PID $$ 辅助提示符,在命令结束前遇到换行时,在续 行中使用的提示符,系统默认为 “>”.如 $echo “first <CR> > second” $PS2 主提示符,表示 shell等待输入命令。在特权用户下,主提示符默认为 “#” $PS1 终端类型 $TERM 存放用户邮件的邮箱文件名 $MAIL 执行命令时所搜寻的目录 $PATH 用户注册后的当前目录, cd命令的缺省参数,每个用户具有不同值 $HOME 查看环境变量 ? #printenv ?#env 临时设置环境变量 ? #env PATH=$PATH:/usr/wangk 位置参数变量 ?Shel程序的命令参数由分割符分开,被从左到右依次赋 给位置参数 $0, $1, $2……第一个命令参数为 $1,第二个 命令参数为 $2, ……依次类推。 $0表示命令名( shell程 序名)。 null示例程序 $cat postfile echo The first: $1 echo The second: $2 echo The third: $3 echo The fourth: $4 echo The program name: $0 $ null执行过程及结果 $sh postfile first second third fourth The first: first The second: second The third: third The fourth: fourth The program name: postfile $ Shell程序的 shift命令 ?Shel程序的位置参数只能使用 $1——$9,但 Shell程序的 命令行中允许使用 128个命令参数。这时就必须使用 shift命令来存取 $9以上的参数。 null示例程序 $cat file.shift echo Before shift, the parameters: $0,$1,$2,$3,$4,$5,$6,$7,$8,$9 echo No of parameters: $# shift echo After shift,the parameters: $0,$1,$2,$3,$4,$5,$6,$7,$8,$9 echo No of parameters: $# $ Shell程序的 shift语句 null执行过程及结果 $file.shift 1 2 3 4 5 6 7 8 9 Before shift, the parameters: file.shift,1,2,3,4,5,6,7,8,9 No of parameters: 9 After shift,the parameters: file.shift,2,3,4,5,6,7,8,9 echo No of parameters: 8 $ ?shift命令重新命名所有的位置参数变量: $2成为 $1, $3成为 $2等。每使用一次 shift,都使所有的 位置参数依次向左移动一个位置,并使位置参数 的数量减 1,直至减为 0。 $0不受 Shift命令的影响。 用户自定义变量 ? 用户自定义变量语法: 定义方法: 变量名= string – 变量名由字母或下划线打头,由字母、下划线、数字组成。 –=表示赋值运算符,两边不能有空格 引用方法: $变量名 null示例程序 $cat file TIME=“Data and time: \c” USERS=“No of users: \c” HOST=“Personal stat: \c” echo $TIME date echo $USERS who | wc –l echo $HOST whoami $ null执行过程及结果 $file Data and time: mon Dec 16:00:00 CST 2003 No of users: 3 Personal stat: Wang Ke tty 01 Dec 15 08:00 wangk $ Shell程序结构程序结构 如何指定使用哪一个 Shell 来解释所写的 Script呢?几种 基本的指定方式如下所述: 1. 如果 Script的第一个非空白字符不是 "#",则它会使用 Bourne Shell。 2. 如果 Script的第一个非空白字符是 "#"时,但不以 "#!"开 头时,则它会使用 C Shell。 3. 如果 Script以 “#!”开头,则 “#!”后面所写的就是所使用 的 Shell,而且要将整个路径名称指出来。例如 : #! /bin/bash Shell程序结构程序结构 Script是以行为单位, Script会分解成一行一行来执行。 而每一行可以是命令、注解、或是流程控制指令等。如 果某一行尚未完成,可以在行末加上 “\” ,这个时候下一 行的内容就会接到这一行的後面,成为同一行。 当 Script中出现 “#” 时,再它後面的同一行文字即为注解, Shell 不会对其翻译。 Shell程序结构 ? 分支结构 null循环结构 if 命令 1 … … 命令 m then 命令 1 … … 命令 n else 命令 1 … … 命令 n fi for 变量名 [in 数值列表 ] do 命令 1 命令 2 … 命令 n done while 命令 1 … 命令 m do 命令 1 命令 2 … 命令 n done nullif语句示例程序 $cat seekword echo type a word and file name read WORD FILE //读入参数值,相当于 scanf if grep $WORD $FILE //从文件 $FILE 中查找字符串 $WORD then echo the $WORD is a word of the $FILE fi $ nullif语句示例程序 $cat username # check the passwd file for login NAME = ${1:– root} //给出缺省的位置参数: $1的值缺省为 root NULLNAME = /dev/null //用户自定义变量: /dev/null是系统的空文件 if grep $NAME /etc/passwd > $NULLNAME then echo $NAME is a passwd file elif grep $NAME /etc/group > $NULLNAME then echo $NAME is a group file. else echo the $NAME is not a passwd file name either or a group file. fi $ null执行过程及结果 $username root is a passwd file $username wangk wangk is a passwd file $ nullWhile循环示例程序 $cat md # put a list of name into file echo “type in each person’s name the a <CR>” echo “type the list of name with <Ctrl-D>” while read name do echo $name >> namefile done echo namefile contains the follow names: cat namefile $ 说明:因为 < >是输入输出重定向符号,要把它们变成普通字符, echo 语句必须加 “” nullfor循环示例程序 $cat movefile.file # move file to another directory. echo type a path read DESTIPATH for VARFILE in file1 file2 file3 do mv $VARFILE $DESTIPATH/$VARFILE done $ For语句的工作过程: null 如果命令中含有 in 列表,则用 in之后的数值顺序替换循环体列表中的 “$ 变量名 ”; null 如果 for语句中省略了 in列表,则用位置参数来替换循环体列表中的 “$ 变量名 ”; null 对每一个数值都执行 do…done之间的命令列表。 nullfor循环示例程序 $cat movefile.file # move file to another directory. echo type a path read DESTIPATH for VARFILE in file1 file2 file3 do mv $VARFILE $DESTIPATH/$VARFILE done $ 范例: 检查指定的文件是否存在并且可读 test –f /etc/passwd 检查指定的文件是否为目录 test –d /etc 检查指定的文件是否非空,若非空则列出该文件的内容 test –s /etc/passwd && cat /etc/passwd 当指定的文件不可读时为真 test ! –r /etc/passwd 当文件 /etc/passwd可读,并且文件 /etc/fstab存在时为真 test –r /etc/passwd –a –f /etc/fstab 当变量 $count大于等于 0,并且小于 10时为真 test “$count”–ge 0 –a “$count”–lt 10 当变量 $a等于 0或者 $b大于 5,并且 $c小于等于 10时为真 test \ ( “$a”–eq 0 –o “$b”–gt 5 \ ) –a “$c”–le 10 第25章Linux C编程基础 ? 21.1 NFS(网络文件系统)服务器 ? 21.2 NIS (网络信息服务)服务器 ? 21.3 Samba服务器 ? 21.4 Apache服务器 GCC的 命令行选项 产生 groff所需要的信息 -pg 产生 proff所需要的信息 -p 产生排错需要的符号信息(用于 gdb) -ggdb 产生排错需要的符号信息(同 gdb一起使用时) -g 显示附加的警告消息 -Wall 严格要求符合 ANSI标准 -pedantic 禁止警告消息 -w 为 include文件的搜索指定目录 -I directory 编译(不汇编或链接) -S 只进行编译和汇编(不链接) -c 指定语言( C、 C++和汇编为有效值) -x language 用来指定输出文件名( a.out为默认值) -o file 优化 -Olevel 只进行预处理(不编译、汇编或链接) -E 用来指定所使用的库;( -lm 表示在链接时装载名字为 libname.a的库) -l library gdb的 基本命令 使用户不退出 gdb就能执行 shell命令 shell 使用户不退出 gdb就可以重新产生可执行文件 make 在代码里设置断点,这将使程序执行到这里时被挂起 break 使用户能监视一个变量的值而不管它何时被改变 watch 终止 gdb quit 列出产生执行文件的源代码的一部分 list 终止正在调试的程序 kill 装入想要调试的可执行文件 file 执行一行源代码而且进入函数内部 step 执行一行源代码但不进入函数内部 next 执行当前被调试的程序 run