• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 200, comments - 8, trackbacks - 0, articles - 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的原始代碼如下:

            #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"的程序。這樣,我們就可以單獨的編譯每一個例程,而不用顧及作者所給的雜湊的頭文件。同時這種比較笨的方法,反而有利于幫助我們了解不同系統調用所對應的頭文件,對于學習來說,這應該是一件好事。

            歡迎交流,歡迎自由轉載,但請注明CU鏈接或本人CU Blog鏈接:
            http://blog.chinaunix.net/u/33048/showart_343553.html
            精品蜜臀久久久久99网站| 91精品国产色综久久| 久久久亚洲AV波多野结衣| 少妇人妻综合久久中文字幕| 婷婷五月深深久久精品| 成人久久精品一区二区三区| 久久国产高清字幕中文| 中文字幕无码久久人妻| 国内精品伊人久久久久av一坑| 99久久精品免费看国产| 成人综合久久精品色婷婷| 久久精品免费观看| 久久精品国产乱子伦| 2020最新久久久视精品爱| 久久午夜夜伦鲁鲁片免费无码影视| 精品人妻久久久久久888| 国内精品久久久久影院老司| 婷婷综合久久中文字幕| 久久人人爽人人爽人人AV| 久久久久亚洲AV综合波多野结衣| 99久久超碰中文字幕伊人| 久久婷婷五月综合成人D啪| 久久久久噜噜噜亚洲熟女综合| 色综合久久无码中文字幕| 无码任你躁久久久久久| 精品久久久久一区二区三区| 久久99精品久久久久久久不卡 | 久久香蕉超碰97国产精品| 亚洲国产成人精品91久久久| 国产99久久九九精品无码| 精品久久久噜噜噜久久久| 久久久av波多野一区二区| 亚洲国产欧洲综合997久久| 久久亚洲精品无码VA大香大香| 亚洲另类欧美综合久久图片区| 久久精品夜色噜噜亚洲A∨ | 无码伊人66久久大杳蕉网站谷歌| 久久人人爽人人爽人人片AV高清 | 久久久久久久99精品免费观看| 久久久无码人妻精品无码| 久久精品亚洲一区二区三区浴池 |