开启左侧

(初学APUE的进来看看)《UNIX环境高级编程》单个 ...

二维码 [复制链接]
87 0
对于很多初学《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的原始代码如下:
  1. #include <sys/types.h>
  2. #include <dirent.h>
  3. #include "ourhdr.h"

  4. int
  5. main(int argc, char *argv[])
  6. {
  7.     DIR                *dp;
  8.     struct dirent    *dirp;

  9.     if (argc != 2)
  10.         err_quit("usage: ls directory_name");

  11.     if ((dp = opendir(argv[1])) == NULL)
  12.         err_sys("can't open %s", argv[1]);
  13.     while ((dirp = readdir(dp)) != NULL)
  14.         printf("%s\n", dirp->d_name);

  15.     closedir(dp);
  16.     exit(0);
  17. }
复制代码
从书后面的附录中可以看到"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修改为如下内容:
  1. #include <sys/types.h>
  2. #include <dirent.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. int main(int argc, char* argv[])
  6. {
  7.     DIR *dp;
  8.     struct dirent *dirp;
  9.    
  10.     if(argc != 2)
  11.     {
  12.         printf("You need input the directory name.\n");
  13.         exit(1);  
  14.     }
  15.    
  16.     if((dp = opendir(argv[1])) == NULL)
  17.     {
  18.         printf("cannot open %s\n", argv[1]);
  19.         exit(1);   
  20.     }

  21.     while ((dirp = readdir(dp)) != NULL)
  22.         printf("%s\n", dirp->d_name);


  23.     closedir(dp);

  24.     exit(0);
  25. }
复制代码
  这样修改后的程序已经与作者的头文件"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"的程序。这样,我们就可以单独的编译每一个例程,而不用顾及作者所给的杂凑的头文件。同时这种比较笨的方法,反而有利于帮助我们了解不同系统调用所对应的头文件,对于学习来说,这应该是一件好事。


赞助本站





上一篇:程序员技术练级攻略
下一篇:Linux 内核编程风格
学会善用【论坛搜索】功能,很多你要寻找的答案就在这里面;
资源共享区【解压密码】集合,【爱好街币】的作用与获取方式;
您需要登录后才可以回帖 登录 | 注册

本版积分规则

发新帖 回复

104

主题

104

帖子

233

街币
更多

精彩推荐

独立团VIP教程第1-7版全套打包下载(含课件源码工具等)
独立团VIP教程第1-7版全套打包
独立团第1版易语言教程 独立团第一版1易语言入门 1-1-1外
爱好街资源共享区文件解压密码
爱好街资源共享区文件解压密码
因本站分享的文件实在太多,目前收集整理已经接近4T,所以有些文
传奇3智辅教程(含课件源码与工具)
传奇3智辅教程(含课件源码与工
目录 01.课传奇3过驱动保护教程.zip 02.课传奇3过十分钟非
天都吧全站VIP教程合辑(完整无KEY版下载)
天都吧全站VIP教程合辑(完整无
天都吧VIP_CE基础系列视频 易语言辅助入门第1课之CE的使用
挂茶馆全套教程(含课件,源码,工具等)完整版下载
挂茶馆全套教程(含课件,源码,
一切从零开始教程目录 第一部(游戏为征途,随便
新人报到专用贴
新人报到专用贴
==新人报道格式(选填)== 【我的昵称】: 【我的性别
更多

热门帖子

    免责声明:
    在爱好街发布的文章与主题属会员个人意见,与本站立场无关,文章内容由作者与爱好街享有相关版权,如需转载请注明出处或取得会员与本站的许可,否则本站将追究相应的法律责任,如部分内容有侵犯任何版权问题,请立即告知本站,本站将及时予以删除并致以最深的歉意。另外不得将本站内容用于商业或者非法用途,否则,一切后果请用户自负。

    Mail To:MasTer@AiHaiJie.Com

    快速回复
    快速回复 返回顶部 返回列表