關於cp命令的編寫


關於cp命令的編寫

婁老師在課上詳細的講了命令who的編寫過程~對此,我很有啟發!於是想親自動手試試~ 有什么不足的地方請大家提出來!

Learning by doing ~ 做中學,真的只有自己動手去實踐一遍,才能體會到其中的精髓!我跟着婁老師講who命令時的思路來做了一遍cp,收獲頗多~很爽!

參考資料——別出心材的Linux系統調用

在編寫cp命令之前,同樣有三個問題:

  • cp命令能做什么
  • cp命令是如何實現的?
  • 能不能自己編寫一個cp命令?

問題1. cp命令能做什么?

cp能夠復制文件,典型的用法是:

cp source-file target-file

如果target-file所指定的文件不存在,cp就創建這個文件,如果已經存在就覆蓋,target-file的內容與source-file相同。

問題2. cp命令是如何實現的?

一個Linux命令的功能我們可以通過whatisman -f來查看,當然最好的方法是自己通過使用來體驗一下:

要進一步了解cp的用法,需要借助聯機幫助manpages。我們輸入man -k cp,再輸入man 1 cp。

 

要學會在幫助文檔中尋找有用的信息!

 

到這,即使以前沒有用過cp命令,也大概知道它的功能了。

了解cp的功能后,寫出其偽代碼:

  • 打開source-file
  • 創建target-file
  • 從source-file讀出一段數據
  • 把這段數據寫入target-file
  • 關閉source-file
  • 關閉target-file

現在的問題是如何創建文件?如何打開文件?如何讀文件,如何寫文件?

如何創建文件:

 

如何讀文件:

我們用man -k read | grep file | grep 2搜一下,再man 2 read

如何打開文件:

 

圖片中紅線內部是需要用到的庫。

然后使用grep -nr XXX /usr/include查找相關宏。

如何寫文件:

問題3.能不能自己編寫一個cp命令

看代碼的時候我最先不理解的就是main函數的定義:

int main(int argc, char *argv[]){}

經查閱得知,argc是用來表示在命令行下輸入命令時的參數個數,包括指令本身;argv[]是用來取得你輸入的參數。針對具體指令分析如下(每一步解釋由注釋形式給出)。

首先先先看一下涉及到的頭文件的用處:

  • stdio.h 標准輸入輸出
  • stdlib.h C標准函數庫
  • unistd.h Unix類系統定義符號常量
  • fcntl.h 定義了很多宏和open,fcntl函數原型
  • sys/types.h 基本系統數據類型
  • dirent.h unix類目錄操作的頭文件,包含了許多UNIX系統服務的函數原型,例如opendir函數、readdir函數。
  • termios.h 在Posix規范中定義的標准接口

代碼如下:

 #include        <stdio.h>//標准輸入輸出
 #include        <stdlib.h>//C標准函數庫
 #include        <unistd.h>//Unix類系統定義符號常量
 #include        <fcntl.h>//定義了很多宏和open,fcntl函數原型

   #define BUFFERSIZE      4096//定義存儲器容量
   #define COPYMODE        0644//定義復制的長度

 void oops(char *, char *);

 int main(int argc, char *argv[])
 {
int in_fd, out_fd, n_chars;//三個描述符值
char buf[BUFFERSIZE];//存儲器位置

/*cp的參數有兩個,分別是要復制的文件,和目的目錄,這樣一共應該是有三個操作數
所以要先檢查argc的值是否為三,如果不是,返回標准錯誤*/
if (argc != 3) {
    fprintf(stderr, "usage: %s source destination\n", *argv);
    exit(1);
}
/*檢查cp的第一個參數,要復制的文件,用open打開,in_fd為open返回的描述符
如果返回-1,代表打開失敗,提示錯誤*/
if ((in_fd = open(argv[1], O_RDONLY)) == -1)
    oops("Cannot open ", argv[1]);

/*檢查cp的第二個參數,復制的目的地址,用create在目的地址創建新文件,out_fd為open返回的描述符
如果返回-1,代表創建失敗,提示錯誤*/
if ((out_fd = creat(argv[2], COPYMODE)) == -1)
    oops("Cannot creat", argv[2]);

/*cp指令的動作就是讀取一個文件的內容到存儲器,在新的地址創建空白文件,再從存儲器將內容寫入新文件。
這里判斷復制是否成功:
如果能讀取順利,而讀取的位數和寫的位數不同,是寫錯誤;
如果讀取失敗,是讀錯誤。*/
while ((n_chars = read(in_fd, buf, BUFFERSIZE)) > 0)
    if (write(out_fd, buf, n_chars) != n_chars)
        oops("Write error to ", argv[2]);
if (n_chars == -1)
    oops("Read error from ", argv[1]);

/*這里執行的是關閉文件的動作,in_fd和out_fd兩個文件描述符
所指向的文件只要有一個關閉錯誤,就提示關閉錯誤。*/
if (close(in_fd) == -1 || close(out_fd) == -1)
    oops("Error closing files", "");
}

/*這個是用來輸出錯誤信息的函數*/
void oops(char *s1, char *s2)
{
fprintf(stderr, "Error: %s ", s1);
perror(s2);//用來將上一個函數發生錯誤的原因輸出到標准設備(stderr)
exit(1);
 }

這里要注意main函數的兩個參數:

  • argc記錄了用戶在運行程序的命令行中輸入的參數的個數。
  • arg[]指向的數組中至少有一個字符指針,即arg[0].它通常指向程序中的可執行文件的文件名。

代碼驗證:

首先新建兩個txt文件,我這里為1.txt和2.txt。

1.txt里面的內容是111111;2.txt的內容為222222.

 

經過cp命令后,1.txt的內容拷貝到了2.txt里面。

 

將2.txt里面的內容復原后,用編寫的cp命令來試一下,

 

 

果然經過編寫的cp命令后,1.txt的內容拷貝到了2.txt里面。

說明編寫的cp代碼正確!

總結

通過上面的例子,我們學習了Linux中學習Linxu系統編程的方法:

  • 仔細研究manpages
  • 問題驅動,使用man -k key1|grep key2|...在manpages中搜索你要的內容
  • 閱讀.h文件: 可以通過grep -nr XXXX /usr/incldue查找相關的宏定義,結構體定義,類型定義等
  • 解決一個問題要多個系統調用,可以參考manpages的SEE ALSO部分來得到相關系統調用的信息


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM