学习笔记:GNU Linux编程指南(第二版):一

目录:

第一章 Linux及Linux编程综述

第二章 设置开发系统

第三章 使用GNU CC

第四章 使用GNU make 管理项目

第五章 创建可移植的自配置软件 GNU autoconf

第六章 比较和合并源代码文件

第七章 使用RCS和CVS控制版本

第八章 调试

第九章 出错处理

注:原书639页,内容繁多,不易快速定位要点。在第一次阅读过程中,我摘抄要点、记录心得,形成该笔记,供日后查阅和再学习用。

说明:$ 表示 终端输入命令


第一章 Linux及Linux编程综述


1. Linux不是Unix,Unix是一个注册商标,需要满足一大串条款并且支付可观的费用才能被许可使用
    Linux在运行特性上与Unix相似,所有内核代码都是由Linus和几位核心黑客手工编写的。
   许多Linux上运行的程序,也是手动编写的,当然也有移植的

   Linux之所以和Unix相像,是因为它遵循POSIX标准 

    -------------------------------------------------------------------                         

第二章 设置开发系统


第三章 使用GNU CC

1. GCC能编译ANSI C和传统C等C语言变体
   GCC能编译C、C++、Objective C
   GNU Compiler Collection
2. 增加搜索路径 -I <针对头文件>
gcc hello.c -I /home/fred/include -o hello
3. 增加搜索路径 -L <针对库文件>
gcc hello.c -L/home/fred/lib -lnew -o hello
    gcc首先在/home/fred/lib 下查找库文件,然后到默认路径下搜索
    -l 选项使得链接程序使用指定的函数库中的目标代码
4. 通常用法
gcc hello.c -L/home/fred/lib -I /home/fred/include -lnew -o hello
   告诉GCC链接libnew.so, 在/home/fred/lib 中查找libnew.so, 以及在/home/fred/include中查找任何非标准的头文件
5. 启用任何一种调试的选项都会让二进制文件的大小急剧增长
6. gcc -c filename  得到目标文件

第四章 使用GNU make 管理项目

1. make是一种控制编译或者重复编译软件的工具
      make可以自动管理软件编译的内容、方式和时机,从而使程序员能够把精力集中在编写代码上
2. 为何使用make
   (1). 包含多个源文件的项目在编译时都有长而且复杂的命令行
   (2). 减少重复编译所需要的时间。(编译修改过的部分)
   (3). 构建依赖信息数据库,检测是否能找到所需的文件
   (4). 能够建立一个稳定的编译环境
   (5). 让编译过程自动执行
3. makefile
   (1). 文本形式的数据库文件,包含一些规则告诉make编译哪些文件、如何编译以及在什么条件下编译
   (2). 规则--三个部分组成
          <1>. target     : 目标体,即make最终需要创建的东西。
          <2>. denpendency: 包含一或多个dependency列表,通常是编译目标体需要的其它文件。
          <3>. command    : 为了从指定依赖创建出目标体所需要执行的命令列表。
         target通常是程序,但可以是文本文件、手册等任何东西。
         command可以是编译器的命令或者shell命令,也可以是任何命令行能完成的命令
   (3). 通用形式
  target : dependency [denpendency [...]]
               command
               command 
               [...]

          注意:,每个command的第一个字符必须是 制表符
4. 一个makefile文件
  sayHelloApp: main.o simple_fun.o simple_fun.h
	gcc main.o simple_fun.o -o sayHelloApp

  simple_fun.o: simple_fun.c simple_fun.h
	gcc -c simple_fun.c

  main.o: main.c
	gcc -c main.c

  .PHONY : clean

  clean: 
	rm main.o simple_fun.o
5. 伪目标
   上面的makefile文件中的clean并不是对应实际的文件,是伪目标
   伪目标规定了make应该执行的命令
   clean没有依赖体,所以它的命令不会被自动执行,使用make clean
   如果不使用.PHONY,如果存在clean的文件,make就会发现它,
   但是使用了.PHONY后,make不检查是否存在有文件名和依赖体中的一个名字相匹配的文件,直接执行命令
6. 变量
   定义: VARNAME=some_text
   使用: $(VARNAME)
   除用户自定义变量外,make运行使用环境变量、自动变量和预定义变量
      (1)环境变量:  如果makefile中有同名的,以makefile中的为准
      (2)自动变量:  make自动用特定的、熟知的值替换。$(@F) : 目标文件的文件名部分;。。。
      (3)预定义变量:用于定义程序名或者给这些程序传递标志和参数。CC : C编译程序;RM :文件删除程序;。。。
7. 模式规则
   扩展make的隐式规则的一种方法。
   类似普通规则,但是它的目标必定有符号“%”,可以任何非空字符串匹配。
   依赖文件也必须使用%
8. 注释
   #
9. 命令行
   -f file   : 指定makefile的文件名
   -n        : 打印将需要执行的命令,但实际上并不执行这些命令
   -s        : 在执行时不打印命令名
   -w        : 如果make在执行时改变目录,打印当前目录名
   -d        : 打印调试信息

第五章 创建可移植的自配置软件 GNU autoconf

1. autoconf
   它生成一个能自动配置源代码包的shell脚本,以使程序能够在许多不通品牌的UNIX和类UNIX系统上编译和运行。
   这些脚本通常名为configure,它们检查在当前系统中是否提供程序所需要的某些功能,在此基础上生成makefile。
   ./configure
2. configure.in
   为了生成configure脚本,需要在源文件树的根目录下创建名为configure.in 的文件。
   它调用一系列autoconf宏来测试程序需要的或用到的特性是否存在,以及这些特性的功能。
3. configure.in 文件的常用格式
AC_INIT                #AC_INIT(unique_file_in_source_dir),用来测试当前目录是否正确
  测试程序              #每个宏一行
  测试函数库            #如果超过一行,需要使用[]和\,[]扩住所有的参数
  测试头文件            #  AC_CHECK_HEADERS([head1.h header2.h \
  测试类型定义          #             header3.h])
  测试结构
  测试编译器行为
  测试库函数
  测试系统调用
AC_OUTPUT               #AC_OUTPUT(file) file是空格分割的输出文件列表
                        #用于创建名为makefile或者其它名字的输出文件
4. 运行autoscan
   autoscan 包含在autoconf软件包中 (sudo apt-get install autoconf),
   是Perl脚本
   从源文件中抽取与函数调用和头文件有关的信息,并将其输出到configure.scan 文件中。
5. config.h.in文件
   包含程序需要的所有#define指令
   运行autoconf 自带的名为autoheader的shell脚本
   autoheader通过读入configure.in、作为autoconf软件一部分的acconfig.h、
     位于源代码根路径下用于保存预处理符号的acconfig.h(即./acconfig.h) 生成 config.h.in文件
6. ./acconfig.h 
   只需要包含可以被autoconf和autoheader读取和使用的合法定义的C风格预处理符号
   让宏其作用,则设置其值为1
7. 流程
   (1). 编写源文件 和 Makefile.in文件 和 acconfig.h文件 
   (2). 运行autoscan   得到configure.scan
   (3). 重命名 由configure.scan得到configure.in
   (4). 运行autoheader 由acconfig.h 和
                          configure.in  得到 config.h.in
   (5). 运行autoconf  由configure.in    得到 configure               
   (6). ./configure   由config.h.in    得到 Config.h
                       由Makefile.in     得到 Makefile
   (7). 运行make      由makefile        得到 应用程序app

第六章 比较和合并源代码文件

1. diff 和 patch 区别
   如果认为 diff 是通过从一个文件中减去另一个文件来生成者两个文件的差别文件
   那么可以认为 patch 是使用这个差别文件和其中的源文件来生成另一个源文件
2. diff 并排输出两个文件 
 diff -y -W 80 a.vim b.vim
3. diff3 
   当两个人同时修改一个共用文件时,diff3 就会发挥作用。
   它比较两个人做出的两套修改内容,创建第3个文件保存合并后的输出结果,并且指出双方修改的冲突之处。

第七章 使用RCS和CVS控制版本


第八章 调试

1. GDB GNU DeBugger
   自由软件联盟(Free Software Foundation,FSF)的主要软件工具之一
2. make progname
   编写源文件main.c
   使用make main.c,则输出cc main.c -o main,并得到main可执行文件
3. gdb 的使用步骤
   (1). 使用gcc -g test.c -o test
        使用-g 选项,编译出的可执行代码才包含调试信息,否则gdb无法载入改执行文件 
   (2). gdb test [core]
        core 为可选的文件,内存转存文件,增强gdb调试能力
        至此进入gdb命令交互界面
4. gdb 常用调试命令
   (1). l  查看所载入的文件
        注:gdb 中都可以使用缩略形式:
           如   l 代表 list;
                b 代表 brekpoint;
                p 代表 print
                r 代表 run
                n 代表 next
                c 代表 continue
   (2). b  设置断点
        b 6 在第6行设置断点      
        tbreak 6    设置临时断点,运行到后就自动移除
        ignore 6    忽略断点6
        enable 6    激活断点6
        disable 6   使断点6失效
   (3). info b 查看断点
   (4). delete 移除断点
          delete 1 移除断点号为1的断点
   (5). run 运行代码
        默认从代码首行运行
        run 6 从第六行运行
   (6). p 查看变量值
        p i : 查看变量i 的值
        结果显示:$1 = 2
                '$1' 是变量i的标志
   (7). n\s 单步运行
        当有函数调用时,s 会进入函数,n 不会进入函数
   (8). c 继续
          c        : 运行,直到函数结束或者下一个断点
          finish: 运行,直到函数结束
5. gdb 其它常用命令
   (1). help
         $ help
         $ help running

第九章 出错处理

1. assert
 #include <assert.h>
 void assert(int expression);
   如果expression值为假(0),则向stderr打印一条出错信息,然后通过函数abort来终止程序运行
2. 如果在
   include <assert.h> 之前加上下面的语句
   #define NDEBUG
   则不会调用assert宏 
3. 使用系统日志
   Linux 用两个守护进程 klogd 和 syslogd 提供了集中的系统日志功能
   syslogd 控制着来自用户空间程序的消息的产生。
   klogd 供内核和运行在内核空间的程序,特别是设备驱动程序所使用。
   大多数Linux系统,系统日志位于/var/log 目录下,包括如:messages,debug,mail,news等等
   还可能有其它的日志,取决于/etc/syslog.conf中定义的日志功能配置(注:Ubuntu没有文件)

   标准的控制台日志守护进程是syslogd,由它来维护这些日志文件。
   写入系统日志的消息由它的级别(level)和功能(facility)来控制,
   级别指出了消息的严重性或重要性,而功能告诉维护系统日志的syslogd守护进程是哪个程序发送的这条消息
   一条日志消息的级别和功能合起来被称为它的优先级(priority)。
4. syslog的日志级别
      级别                  严重性
    LOG_EMERG             系统不可用
    LOG_ALERT             要求立即处理
    LOG_CRIT              重大错误,比如硬盘故障
    LOG_ERR               错误条件
    LOG_WARNING           警告条件 
    LOG_NOTICE            正常但重要的消息
    LOG_INFO              纯粹的通报消息 
    LOG_DEBUG             调试或跟踪输出
5. syslog的功能值
      功能                   消息源
    LOG_AUTHPRIV          私有的安全和授权消息
    LOG_CRON              时钟守护进程(crond 和 atd)
    LOG_DAEMON            其它系统守护进程
    LOG_KERN              内核消息
    LOG_LOCAL[0-7]        为本地/站点使用而保留
    LOG_LPR               打印子系统
    LOG_MAIL              邮件子系统
    LOG_NEWS              新闻子系统
    LOG_SYSLOGsyslog      产生的内部消息
    LOG_USER             (默认值)一般用户级消息
    LOG_UUCP              uucp子系统
    注:当出现错误时,对于用户级程序来说LOG_WARN已经足够了
       LOG_INFO 对于日常烦人的日志消息最合适
       LOG_ERR 出现了可能致命的系统错误
6. 系统日志函数
   头文件 <syslog.h> 定义了syslogd的接口。
   创建一个日志消息,使用syslog函数,原型为: 
#include <syslog.h>
void syslog(int priority, char* format,...);     
priority 是级别和功能的位逻辑“或”值
format指定写入日志的消息和任何类似printf的格式说明字符串    
         %m 由strerror为errno分配的错误消息 替换    
7. 简单的例子
    /***********************************************************
                         程序代码
    /***********************************************************/
	#include <stdio.h>
	#include <syslog.h>


	int main(int argc,int** argv)
	{
		//LOG_WARNING 结果写入 /var/log/syslog 文件中
		syslog(LOG_WARNING | LOG_USER,\
		       "This is a warning from %s,%s %s,%m\n",\
		       __FILE__,__DATE__,__TIME__);   
		
		//ubuntu下,LOG_INFO 结果也是写入 /var/log/syslog 文件中
		//LOG_USER是默认的功能级
		syslog(LOG_INFO,"This is a normal message from %s\n",__FILE__);
		return 1;
	} 
 
    /***********************************************************
                         运行结果
    /***********************************************************/
/*
   在/var/log/下的syslog文件中,有如下两条记录条记录:
Sep  3 16:39:52 jarvischu-Studio-1435 using_syslog: This is a warning from using_syslog.c,Sep  3 2011 16:39:47,Success
Sep  3 16:39:52 jarvischu-Studio-1435 using_syslog: This is a normal message from using_syslog.c                        */
8. openlog 定制日志操作,主要是加上前缀
#include <syslog.h>
void openlog(const char *ident, int option, int facility);
   ident: 指定加到日志消息前的字符串
   option: 多个选项的位逻辑“或”值        
       LOG_PID      在每条消息中包含PID
       LOG_CONS     如果消息不能写入日志文件,则发送到控制台
       LOG_NDELAY   立即打开链接(默认是在syslog第一次被调用时才打开链接)
       LOG_PERROR   把消息写入日志文件的同时也输出到stderr
   facility:即 5. 中的某个值
   例:
openlog("JarvisChu",LOG_PID,LOG_USER);
syslog(LOG_INFO|LOG_USER,"This is a message\n");
     则在/var/log/syslog 文件中,有如下记录:
                     JarvisChu[1231]:This is a message
9. 其它函数
      (1). closelog()   
              如同openlog,可选的,关闭openlog打开的文件描述符。
      (2). int setlogmask(int priority);
           设置所有日志消息的默认级别,(即哪些级别的消息能写入syslog,哪些不能写入)
            函数返回原来的优先级
            syslog拒绝任何没有在掩码中设置的优先级消息

             同 宏:

LOG_MASK(int priority) :创建仅由一个优先级组成的掩码
LOG_UPTO(int priority) :创建一个由一系列降序优先级组成的掩码

              如LOG_UPTO(LOG_NOTICE)创建的掩码包括了从LOG_EMERG到LOG_NOTICE之间的任何级别的消息。

              而LOG_INFO和LOG_DEBUG级别的消息则不能通过

待续...


作者:Jarvis Chu

首发:CSDN Blog

转载请注明出处:http://blog.csdn.net/jarvischu/article/details/6747420


posted @ 2011-09-04 17:30  JarvisChu  阅读(922)  评论(0编辑  收藏  举报