博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《UNIX环境高级编程》单个源码编译方法
阅读量:6855 次
发布时间:2019-06-26

本文共 2975 字,大约阅读时间需要 9 分钟。

对于很多初学 《UNIX环境高级编程》(AdvancedProgramming in the UNIX Environment,简称APUE,以下使用简称)的朋友 ,第一个遇到的问题可能就是该书中的源代码编译 的问题。此书中差不多每个例程中,都会有这样一行源码

#include "ourhdr.h"
在第二版中改为:
#include "apue.h"

 这个头文件 是 作者把把每个例程中常用的标准头文件,一些常用的出错处理函数(err_**()之类的函数)和一些常用的宏定义给整理在一个头文件中。这个可以省去在每 个例程中录入较多的重复代码,这样可以减少每个例程的长度。但是,这样就给读者带来了不少麻烦。因为我们还要去搞明白如和把这个头文件编译,然后做成库文 件,添加到我们的系统 中。特别读于初学者,本来满怀信心的,结果在编译第一个程序 的时候就出现了问题。我也没有搞明白如何把"ourhdr.h"静态的编译到系统中。

   不过,不明白如何使用"ourhdr.h"这个头文件,并不会影响我们学习APUE,也不会影响我们编译和运行每一个例程。其实,简单的想一下,如果一 个C程序要能顺利的编译和运行,除了我们要语法正确等方面外,最根本的是要保证我们程序中所调用的函数以及宏等等都要有完整的来源,也就是必须包含所有调 用函数和宏所在的头文件。对于一个具体的源程序,如果我们正确的包含了头文件,那么剩下的就是程序本生语法方面应该注意的事项。
   如何确定系统调用函数包含在那个头文件中呢?这在Unix/Linux系统下并非一件难事。Unix/Linux下命令 man可以帮助我们找到。man命令不仅可以帮助我们查找一般命令的用法,同时提供不同层次的帮助诸如系统调用或者管理员级别的命令等等(譬如FreeBSD6.1中,man1是用户专用手册,man 2是系统调用,man 3是库函数查询等等)。
   下面我们就以APUE书中程序1-1(实现ls命令部分功能 ) 为例,来说明如何将书中的程序改编成全部使用标准头文件的程序。其中,操作系统用的是FreeBSD6.1,经过相应的修改可以在书中所说的几个Unix 系统及Linux系统中运行,我也曾在Debian Linux下成功编译和运行该程序。书中1-1.c的原始代码如下:

 

# include < sys/ types. h> # include < dirent. h> # include "ourhdr.h" int main( int argc, char * argv[ ] ) {
DIR * dp; struct dirent * dirp; if ( argc ! = 2) err_quit( "usage: ls directory_name" ) ; if ( ( dp = opendir( argv[ 1] ) ) = = NULL ) err_sys( "can't open %s" , argv[ 1] ) ; while ( ( dirp = readdir( dp) ) ! = NULL ) printf ( "%s/n" , dirp- > d_name) ; closedir( dp) ; exit ( 0) ; }

 从书后面的附录中可以看到"ourhdr.h"的内容比较多,包含了比较多的常用头文件,一些宏定义和一些常用函数和出错函数的定义。其实,对于每一个具体的程序,我们只需要找到该程序中用到的头文件即可。

    该1-1.c中所用到的系统函数调用有:opnedir(),readdir(),printf(),closedir()和exit()。
其中,对于常用的函数prinft()和exit(),它们所在的头文件一般都知道,分别是<stdio.h>和<stdlib.h>。而对于 opnedir(),readdir()和closedir(),我们可以通过man opendir,man readdir,manclosedir得到这三个关于目录 操作的函数所在的头文件都是:<sys/types.h>和<dirent.h>。这两个头文件在源程序中也已经列出。
   其次,1-1.c中还用到了作者自定义的两个函数:err_quit()和err_sys()。这两个函数主要使用来进行出错处理的。当然,使用这两个 函数对错误信息的处理是比较完善的。但是,作为我们学习来讲,了解程序的核心功能是首要的,我们可以将出错处理简化一点,即当遇到错误的时候,我们只简单 的使用printf()函数来提示一下有错误发生。当然,用printf()来进行出错处理并不是一种很合理的方法,而且往往我们看不到更关键的错误信 息,但对于我们仅仅作为学习来用还是可以接受的。毕竟我们要理解的核心部分是程序的功能实现,出错处理在于其次。
   通过以上的说明,我们可以将1-1.c修改为如下内容:

 

# include < sys/ types. h> # include < dirent. h> # include < stdio. h> # include < stdlib. h> int main( int argc, char * argv[ ] ) {
DIR * dp; struct dirent * dirp; if ( argc ! = 2) {
printf ( "You need input the directory name./n" ) ; exit ( 1) ; } if ( ( dp = opendir( argv[ 1] ) ) = = NULL ) {
printf ( "cannot open %s/n" , argv[ 1] ) ; exit ( 1) ; } while ( ( dirp = readdir( dp) ) ! = NULL ) printf ( "%s/n" , dirp- > d_name) ; closedir( dp) ; exit ( 0) ; }

这样修改后的程序已经与作者的头文件"ourhdr.h"没有关系,可以单独的进行编译。我使用的是root用户,执行命令:

# gcc 1-1.c  //生成目标文件a.out
或者
# gcc -o 1-1 1-1.c  //生成目标文件1-1
    没有任何错误和警告,说明编译成功。这时我们执行生成的目标文件:
# ./a.out /home
或者
# ./1-1 /home
    则会列出/home路径下的所有文件,包括目录(.)和(..)。
   通过这样的方法,基本上我们可以将该书中所有的例程修改成不包含"ourhdr.h"的程序。这样,我们就可以单独的编译每一个例程,而不用顾及作者所 给的杂凑的头文件。同时这种比较笨的方法,反而有利于帮助我们了解不同系统调用所对应的头文件,对于学习来说,这应该是一件好事。

转载地址:http://diyyl.baihongyu.com/

你可能感兴趣的文章
NIPS 2016精华大盘点丨吴恩达、LeCun等大师的论文、PPT都在这儿,别劳心去找了...
查看>>
详悉物联网搜索解决方案上的飞跃
查看>>
智慧城市与城市创新
查看>>
“大数据”是重塑招聘未来的首要趋势
查看>>
信息通信十三五规划:支持窄带物联网全国性网络
查看>>
Teradata与Nuix合作 助客户处理“暗数据”
查看>>
关于今年最大的IPO公司Line 你需要了解这几点
查看>>
杨元庆增持联想 并向股东致歉
查看>>
PC软件安装量排名出炉:最高的竟是它
查看>>
从HTTP迁移至HTTPS需要注意什么?
查看>>
韩国上百机构曾被朝鲜黑客攻击 逾4万份文件泄露
查看>>
Aspire Fertility诊所采用RFID技术
查看>>
微软最新博文:Windows 7寿命仅剩3年 企业应尽早升级
查看>>
前沿|CCAI 2017专题论坛:拥抱智能金融新时代
查看>>
2017年我国将开始部署和建设IPv6地址项目
查看>>
Digital workspace 终端用户计算演变的“终结者”
查看>>
快来围观!5款必看的Aruba网络新品
查看>>
成都电信:三大举措护航网络安全
查看>>
物联网技术将深度改变你我生活
查看>>
IDC:2017年全球安全技术支出预计突破817亿美元
查看>>