程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> linux服務器開發一 基礎,linux服務器開發

linux服務器開發一 基礎,linux服務器開發

編輯:關於C語言

linux服務器開發一 基礎,linux服務器開發


注:本文僅限交流使用,請務用於商業用途,否則後果自負!

Linux

  • 1、Linux介紹
    • Linux是類Unix計算機操作系統的統稱。
    • Linux操作系統的內核的名字也是“Linux”。
    • Linux這個詞本身只表示Linux內核,但在實際上人們已經習慣了用Linux來形容整個基於Linux內核的系統。
    • Linux是由芬蘭大學Linus Torvalds於1991年編寫的。
  • 2、Linux發行版組成
    • Linux內核
    • 應用軟件
      • 一些GNU程序庫和工具
        • emacs
        • GCC
        • GNOME
      • 命令行shell
      • 圖形桌面環境
        • KDE(qt編寫)
        • GNOME(GTK編寫)
        • Unity
      • 一些辦公軟件
        • OpenOffice
      • 編譯器
        • gcc
        • g++
      • 文本編輯器到科學工具的應用軟件
        • vi
        • gedit
  • 3、Linux版本
    • 商業公司維護的發行版本
      • RedHat(REHL)包管理方式采用基於RPM包的YUM包管理方式
    • 社區組織維護的發行版本
      • Debian 包管理方式采用的是:apt-get/dpkg xxx.deb
    • RedHat系列
      • RHEL(RedHat Enterprice Linux, 也就是所謂的RedHat Advance Server收費版本),穩定。
      • CentOS(RHEL的社區克隆版本,免費),穩定。
      • FedoraCore(由原來的RedHat桌面版本發展而來,免費版本),穩定性差,最好只用於桌面應用。
    • Debian系列
      • Debian
      • Ubuntu
        • 命名規則
          • 前兩位數字:發行時的年份的最後兩位數字
          • 後兩位數字:發行的月份
        • 版本
          • 桌面版(Desktop):至少三年的技術支持
          • 服務器版(Server):至少五年的技術支持
          • LTS版本(Long Term Support)
        • 版本發布頻率,一年兩次
          • 主版本號(年份)
            • 單數年:短期支持版
            • 雙數年:長期支持版(LTS)
          • 副版本號(月份)
            • 四月份(xx.04):該年度的穩定版
            • 十月份(xx.10):該年度的測試版

學習方法

  • 要求
    • 記好課堂筆記
    • 只聽不練學不會Linux,多動手實踐
    • 課上跟上思路,簡單的命令跟著敲,多思考
    • 分清主次,重點記憶重要命令
  • 資料
    • Linux自帶幫助文檔 - man
    • 鳥哥和私房菜

一、文件和目錄操作

  • 1、基本的shell操作

    • shell命令行快捷鍵

      • 編輯命令

        Ctrl + a          移到命令行首, ahead,與home鍵功能相同
        Ctrl + e          移到命令行尾, end, 與end鍵功能相同
        Ctrl + f          按字符前移(右向), forward, 與方向鍵left功能相同
        Ctrl + b          按字符後移(左向), back, 與方向鍵right功能相同
        Alt  + f          按單詞前移(右向)
        Alt  + b          按單詞後移(左向)
        Ctrl + xx         在命令行首和光標之間移動
        Ctrl + u          從光標處刪除至命令行首
        Ctrl + k          從光標處刪除至命令行尾
        Ctrl + w          從光標處刪除至字首
        Alt  + d          從光標處刪除至字尾
        Ctrl + d          刪除光標處的字符, 與delete鍵功能相同
        Ctrl + h          刪除光標前的字符, 與backspace鍵功能相同
        Ctrl + y          粘貼至光標後, yank
        Alt  + c          從光標處更改為首字母大寫的單詞
        Alt  + u          從光標處更改為全部大寫的單詞, uppercase
        Alt  + l          從光標處更改為全部小寫的單詞, lowercase
        Ctrl + t          交換光標處和之前的字符
        Alt  + t          交換光標處和之前的單詞
        Alt  + Backspace  與 Ctrl + w 類似,分隔符有些差別
        
      • 重新執行命令

        Ctrl + r          逆向搜索命令歷史
        Ctrl + g          從歷史搜索模式退出
        Ctrl + p          歷史中的上一條命令, previous,與方向鍵up功能相同
        Ctrl + n          歷史中的下一條命令, next, 與方向鍵down功能相同
        Alt  + .          使用上一條命令的最後一個參數
        
      • 控制命令

        Ctrl + l          清屏, clear
        Ctrl + o          執行當前命令,並選擇上一條命令
        Ctrl + s          阻止屏幕輸出
        Ctrl + q          允許屏幕輸出
        Ctrl + c          終止命令
        Ctrl + z          掛起命令
        
      • Bang (!) 命令

        !!                執行上一條命令
        !blah             執行最近的以 blah 開頭的命令,如 !ls
        !blah:p           僅打印輸出,而不執行
        !$                上一條命令的最後一個參數,與 Alt + . 相同
        !$:p              打印輸出 !$ 的內容
        !*                上一條命令的所有參數
        !*:p              打印輸出 !* 的內容
        ^blah             刪除上一條命令中的 blah
        ^blah^foo         將上一條命令中的 blah 替換為 foo
        ^blah^foo^        將上一條命令中所有的 blah 都替換為 foo
        
    • 虛擬終端(VT)

      • 簡介

        英文:Virtual Terminal
        解釋:連接在遠地的分時共用計算機系統的遠程終端,它具有使用戶感到是在計算機旁使用終端的功能。
        
      • 常用工具

        XManager
        Putty
        SecureCRT
        
    • 命令和路徑補齊

      tab鍵按一次    當只有一個匹配時,自動補全命令或路徑
      tab鍵按兩次    當有多個匹配時,顯示命令或路徑列表
      
  • 2、Linux 標准目錄結構

    初學Linux,首先需要弄清Linux 標准目錄結構:

    /
        root --- 啟動Linux時使用的一些核心文件。如操作系統內核、引導程序Grub等。
        home --- 存儲普通用戶的個人文件
            ftp --- 用戶所有服務
            httpd
            samba
            user1
            user2
        bin --- 系統啟動時需要的執行文件(二進制)
        sbin --- 可執行程序的目錄,但大多存放涉及系統管理的命令。只有root權限才能執行
        proc --- 虛擬,存在linux內核鏡像;保存所有內核參數以及系統配置信息
            1 --- 進程編號
        usr --- 用戶目錄,存放用戶級的文件
            bin --- 幾乎所有用戶所用命令,另外存在與/bin,/usr/local/bin
            sbin --- 系統管理員命令,與用戶相關,例如,大部分服務器程序
            include --- 存放C/C++頭文件的目錄
            lib --- 固定的程序數據
            local --- 本地安裝軟件保存位置
            man --- 手工生成的目錄
            info --- 信息文檔
            doc --- 不同包文檔信息
            tmp
            X11R6 ---  該目錄用於保存運行X-Window所需的所有文件。該目錄中還包含用於運行GUI要的配置文件和二進制文件。
            X386 --- 功能同X11R6,X11 發行版5 的系統文件
        boot --- 引導加載器所需文件,系統所需圖片保存於此
        lib --- 根文件系統目錄下程序和核心模塊的公共庫
            modules --- 可加載模塊,系統崩潰後重啟所需模塊
        dev --- 設備文件目錄
        etc --- 配置文件
            skel --- home目錄建立,該目錄初始化
            sysconfig --- 網絡,時間,鍵盤等配置目錄
        var
            file
            lib --- 該目錄下的文件在系統運行時,會改變
            local --- 安裝在/usr/local的程序數據,變化的
            lock --- 文件使用特定外設或文件,為其上鎖,其他文件暫時不能訪問
            log --- 記錄日志
            run --- 系統運行合法信息
            spool --- 打印機、郵件、代理服務器等假脫機目錄
            tmp
            catman --- 緩存目錄
        mnt --- 臨時用於掛載文件系統的地方。一般情況下這個目錄是空的。
                在我們將要掛載分區時在這個目錄下建立目錄,再將我們將要訪問的設備掛載在這個目錄上,這樣我們就可訪問文件了。
        tmp --- 臨時文件目錄,系統啟動後的臨時文件存放在/var/tmp
        lost+found --- 在文件系統修復時恢復的文件
    

    /

        根目錄,一般根目錄下只存放目錄,不要存放文件。
        /etc、/bin、/dev、/lib、/sbin應該和根目錄放置在一個分區中。
    

    /bin, /usr/bin

        可執行二進制文件的目錄,如常用的命令ls、tar、mv、cat等。
    

    /boot

        放置linux系統啟動時用到的一些文件。/boot/vmlinuz為linux的內核文件,以及/boot/gurb。建議單獨分區,分區大小100M即可。
    

    /dev

        存放linux系統下的設備文件,訪問該目錄下某個文件,相當於訪問某個設備,常用的是掛載光驅mount:
        /dev/cdrom、/mnt
    

    /etc

        系統配置文件存放的目錄,不建議在此目錄下存放可執行文件。
        重要的配置文件有:/etc/inittab、/etc/fstab、/etc/init.d、/etc/X11、/etc/sysconfig、/etc/xinetd.d。
        修改配置文件之前記得備份。
    
        注:/etc/X11存放與x windows有關的設置。
    

    /home

        系統默認的用戶家目錄,新增用戶賬號時,用戶的家目錄都存放在此目錄下。
        ~表示當前用戶的家目錄,~test表示用戶test的家目錄。
        建議單獨分區,並設置較大的磁盤空間,方便用戶存放數據。
    

    /lib,/usr/lib,/usr/local/lib

        系統使用的函數庫的目錄,程序在執行過程中,需要調用一些額外的參數時需要函數庫的協助,比較重要的目錄為/lib/modules。
    

    /lost+fount

        系統異常產生錯誤時,會將一些遺失的片段放置於此目錄下,通常這個目錄會自動出現在裝置目錄下。
        如加載硬盤於/disk 中,此目錄下就會自動產生目錄/disk/lost+found
    

    /mnt,/media

        光盤默認掛載點,通常光盤掛載於/mnt/cdrom下,也不一定,可以選擇任意位置進行掛載。
    

    /opt

        給主機額外安裝軟件所擺放的目錄。
        如:FC4使用的Fedora 社群開發軟件,如果想要自行安裝新的KDE 桌面軟件,可以將該軟件安裝在該目錄下。
        以前的 Linux 系統中,習慣放置在 /usr/local 目錄下。
    

    /proc

        此目錄的數據都在內存中,如系統核心,外部設備,網絡狀態,由於數據都存放於內存中,所以不占用磁盤空間。
        比較重要的目錄有/proc/cpuinfo、/proc/interrupts、/proc/dma、/proc/ioports、/proc/net/*等。
    

    /root

        系統管理員root的家目錄,系統第一個啟動的分區為/,所以最好將/root和/放置在一個分區下。
    

    /sbin,/usr/sbin,/usr/local/sbin

        放置系統管理員使用的可執行命令,如fdisk、shutdown、mount等。
        與/bin不同的是,這幾個目錄是給系統管理員root使用的命令,一般用戶只能"查看"而不能設置和使用。
    

    /tmp

        一般用戶或正在執行的程序臨時存放文件的目錄,任何人都可以訪問,重要數據不可放置在此目錄下。
    

    /srv

        服務啟動之後需要訪問的數據目錄,如www服務需要訪問的網頁數據存放在/srv/www內。
    

    /usr

        應用程序存放目錄。
        /usr/bin 存放應用程序。
        /usr/share 存放共享數據。
        /usr/lib 存放不能直接運行的,卻是許多程序運行所必需的一些函數庫文件。
        /usr/local 存放軟件升級包。
        /usr/share/doc 系統說明文件存放目錄。
        /usr/share/man 程序說明文件存放目錄。
        使用 man ls時會查詢/usr/share/man/man1/ls.1.gz的內容。
        建議單獨分區,設置較大的磁盤空間。
    

    /var

        放置系統執行過程中經常變化的文件。
        /var/log 隨時更改的日志文件。
        /var/log/message 所有的登錄文件存放目錄。
        /var/spool/mail 郵件存放的目錄。
        /var/run 程序或服務啟動後,其PID存放在該目錄下。
        建議單獨分區,設置較大的磁盤空間。
    
  • 3、文件和目錄操作相關命令

    • 用戶目錄

      • 絕對路徑:從根目錄開始寫,如/usr/bin
      • 相對路徑:相對於當前的工作目錄而言
        • . 當前目錄
        • .. 當前目錄的上一級目錄
        • - 在臨近的兩個目錄直接切換
      • root@ubuntu:~#
        • root: 當前用戶名
        • @:at, 在
        • ubuntu:主機名
        • ~ : 當前用戶home目錄
        • #:超級用戶
        • $:普通用戶
    • ls

      ls -al
          -a, --all           不隱藏任何以. 開始的項目
          -l                  使用較長格式列出信息
      
      -rw-r--r--  1 super root     3771 6月   7  2016 .bashrc
      drwx------ 22 super root     4096 12月 15 08:02 .cache
      lrwxrwxrwx  1 super root       31 11月 23 07:42 .vimrc -> /home/super/.spf13-vim-3/.vimrc
      
      以最後一個為例:
      lrwxrwxrwx
      第1個字符:表示文件類型
          -   普通文件
          d   目錄
          l   鏈接符號
          b   塊設備
          c   字符設備
          s   socket文件
          p   管道
      第2-4個字符:文檔所有者權限
      第5-7個字符:同組用戶權限
      第8-10個字符:其他人權限
      r: read 4
      w: write 2
      x: execute 1
      
      1               文件的硬鏈接數
      super           該文件或目錄的所有者
      root            該文件或目錄所屬的組
      31              占用的存儲空間
      11月 23 07:42   文件最後創建或修改的時間
      .vimrc          文件名
      
    • cd

      cd ~        切換到用戶home目錄
      cd /        切換到根目錄
      cd          切換到用戶home目錄
      cd..        切換到上一級目錄
      
    • tree

      tree path   顯示指定路徑的目錄樹結構
      
    • 文件或目錄顏色一般情況

      白色          普通文件
      藍色          目錄
      綠色          可執行文件
      紅色          壓縮文件
      青色          鏈接文件
      黃色          設備文件
      灰色          其他文件
      
    • mkdir

      mkdir dirname               創建目錄。
      mkdir dir1/dir2/dir3 -p     按層次創建目錄。
      
    • rmdir

      rmdir dirname       目錄必須為空才能刪除,所以實際使用時不常用。
      
    • rm

      rm -rf dirname      遞歸強制刪除文件夾下的目錄和文件,實際使用中常用。
      rm -ri dirname      遞歸刪除並提示用戶刪除了哪些目錄或文件。
      
    • touch

      touch test.txt      創建文件。
      
    • cp

      cp hello.c temp     在當前目錄下生成一個temp文件,並把hello.c的內容寫入文件。
                          如果temp不存在,則創建文件;如果存在,則覆蓋已有文件。
      
      cp mydir newdir -r  在當前目錄下生成一個newdir目錄,並把mydir目錄裡面的目錄或文件拷貝過去。
                          如果目錄不存在,則創建;如果存在,則mydir目錄本身也拷貝到newdir目錄下。
      
    • cat

      cat test.txt        查看文件的內容,缺點內容太多時查看困難。
      
    • more

      more stdio.h        分屏查看文件,Enter下翻一行,Space下翻一頁,缺點不能往回看。
      
    • less

      less stdio.h        分屏查看文件。比more更實用,可以來回翻頁。
                          ctrl + p    上翻一行
                          ctrl + n    下翻一行
                          ctrl + b    上翻一頁
                          ctrl + f    下翻一頁
                          q           退出
      
    • head

      head -5 stdio.h     查看前五行內容,不加參數默認是10行。
      
    • tail

      tail -5 stdio.h     查看後5行內容, 不加參數默認是10行。
      
    • mv

      mv test.c hello.c   移動到。多用於重命名目錄或文件。
      
    • ln

      ln -s ~/.vim/.vimrc .vimrc      創建軟鏈接,相當於windows下的快捷方式,可用於目錄或文件。
                                      路徑要用絕對路徑,這樣軟鏈接拷貝到哪裡都是有效的。
                                      如果刪除原文件,則軟鏈接失效。
      
      ln .vimrc .vimrc.hard           創建硬鏈接,只能用於文件。不必使用絕對路徑。
                                      創建後生成的硬鏈接與原文件引用同一個inode,硬鏈接本身不占硬盤空間。
                                      如果刪除原文件,硬鏈接仍然有效。
      
    • wc

      wc test.c       統計文件的行數,字數,字節數。
      
    • od

      od -tx test.c       以十六進制形式查看文件。
      od -tc test.c       以ASCII字符形式查看文件。
      od -td test.c       以有符號十進制形式查看文件。
      od -tf test.c       以浮點數形式查看文件。
      od -to test.c       以八進制形式查看文件。
      od -tu test.c       以無符號十進制形式查看文件。
      
    • du

      du -h       查看當前文件夾下的目錄或文件所占用磁盤的大小。
      
    • df

      df -h       查看當前文件夾下的目錄或文件所使用磁盤空間的詳細情況。
      
    • which

      which ls    查看外部命令的位置,內部命令無法查看。
      
    • pwd

      pwd         查看當前所在目錄
      
  • 4、文件權限、用戶、用戶組相關命令

    • 查看當前用戶

      whoami      查看當前用戶名。
      id          查看當前用戶信息,如用戶名,所屬群組,UID,GID等。
      
    • 修改目錄或文件權限

      • 文字設定法

        chmod [who] [+|-|=] [mode]
        who : 不指定的話,默認是所有
            文件所有者:u
            文件所屬組:g
            其他人:o
            所有人:a
        mode
            r : 讀
            w : 寫
            x : 執行
        chmod o+w temp      給其他人加寫權限。
        chmod a-x temp      給所有人去除執行權限。
        chmod a=r temp      所有人只有讀權限。
        
      • 數字設定法

        -   0   沒有權限
        r   4   讀
        w   2   寫
        x   1   執行
        
        chmod 755 temp      -rwxr-xr-x
        chmod -001 temp     -rwxr-xr--
        
    • 修改目錄或文件所有者與所屬組

      chown root temp         把文件temp的所有者修改為root。
      chown super:root temp   把文件temp的所有者修改super,所屬組修改為root。
      
    • 修改目錄或文件所屬組

      chgrp root temp         修改文件所屬組為root。
      
    • 目錄必須有執行權限,否則不能打開目錄。

  • 5、查找和檢索相關命令

    • 按文件屬性查找

      • 文件名

        find ~ -name "hello.c"      按完整名稱匹配
        find ~ -name "*.h"          *代表任意長度字符
        find ~ -name "tem?"         ?代表一個任意字符
        
      • 文件大小

        find ~ -size +10k               查找大於10k的文件
        find ~ -size -10M               查找小於10M的文件
        find ~ -size +10M -size -100M   查找大於10M小於是100M的文件
        
      • 文件類型

        find ~ -type p      查找類型為管道的檔案
        find ~ -type f      查找類型為文件的檔案
        find ~ -type d      查找類型為目錄的檔案
        find ~ -type l      查找類型為鏈接的檔案
        
    • 按文件內容查找

          grep -r "stdio.h" ~     在用戶家目錄中查找文件內容裡包括stdio.h的所有文件
      
  • 6、軟件安裝和卸載

    • 在線安裝

      • apt-get

        安裝      apt-get install tree        在線下載安裝
        移除      apt-get remove tree
        更新      apt-get update              更新軟件列表
        清理      apt-get clean               清理所有軟件安裝包,實際上清理的是/var/cache/apt/archives目錄下的.deb文件
        
      • aptitude

        安裝       aptitude install tree
        重新安裝    aptitude reinstall tree
        更新       apt-get update
        移除       aptitude remove tree
        顯示狀態    aptitude show tree
        
    • deb包安裝

      • 安裝

        dpkg -i xxx.deb
        
      • 刪除

        dpkg -r xxx
        
    • 源碼安裝

      1)解壓縮源代碼包。
      2)進入安裝目錄。
      3)檢測文件是否缺失,創建Makefile,檢測編譯環境:./configure。
      4)編譯源碼,生成庫和可執行程序:make。
      5)把庫和可執行程序,安裝到系統目錄下:make install。
      6)刪除和卸載軟件:make distclean。
      7)上述安裝步驟並不是絕對的,應該先查看附帶的README文件。
      
  • 7、磁盤管理

    • 磁盤設備種類

      hd      Hard Disk         硬盤
      fd      Floppy Disk       軟盤
      sd      SCSI Device       小型計算機系統接口(英語:Small Computer System Interface; 簡寫:SCSI)。
                                一種用於計算機和智能設備之間(硬盤、軟驅、光驅、打印機、掃描儀等)系統級接口的獨立處理器標准。
                                SCSI是一種智能的通用接口標准。
      設備都保存在/dev中
      
    • sd後面加小寫字母,分別代表不同的硬盤,如:

      sda     第一個硬盤
      sdb     第二個硬盤
      sdc     第三個硬盤
      sdd     第四個硬盤
      
    • 每個硬盤又分為主分區和邏輯分區,一個硬盤最多允許四個主分區,第一個邏輯分區從sda5開始。

      主分區:
      sda1    主分區1
      sda2    主分區2
      sda3    主分區3
      sda4    主分區4
      
      擴展分區:
      sda5    邏輯分區1
      sda6    邏輯分區2
      sda7    邏輯分區3
      ......
      
    • 查看設備信息

      fdisk -l    當你不知道usb的名稱時,可以用這個命令在獲取
      
    • 掛載USB

      mount /dev/sdb1 /mnt
      注: 如果掛載的目錄不是一個空目錄,則目錄裡面的內容會被臨時覆蓋掉,導致目錄原有文件無法操作,卸載後會恢復原有文件。
      建議使用空目錄, 如/mnt。
      
    • 卸載USB

      umount /mnt
      

二、打包壓縮和常用服務器

  • 1、壓縮包管理

    • 屌絲版

      • gzip -- .gz格式壓縮包

        gzip *.txt      假設當前目錄中有a.txt和b.txt, 則會生成a.txt.gz和b.txt.gz,txt源文件會被刪除。
                        這個命令不能用於目錄。
        gunzip *.gz     解壓
        
      • bzip2 -- .bz2格式的壓縮包

        bzip2 -k *.txt  假設當前目錄中有a.txt和b.txt,則會生成a.txt.bz2和b.txt.bz2文件,加-k參數可以將源文件保留。
                        這個命令不能用於目錄。
        bunzip2 *.bz2   解壓
        
    • 高富帥版

      • tar -- 不使用z或j參數,該命令只能對文件和目錄打包

        • 參數

          c       創建--壓縮時使用。
          x       釋放--解壓縮時使用。
          v       顯示提示信息--壓縮和解壓縮都可以使用,可以省略。
          f       指定壓縮文件的名字
          
          z       使用gzip的方式壓縮文件
          j       使用bzip2的方式壓縮文件
          
        • 壓縮

          用法:tar zcvf 生成的壓縮包的名字(xxx.tar.gz) 要壓縮的文件或目錄
          示例:tar zcvf alltxt.tar.gz *.txt test/       同時對文件和目錄進行打包壓縮
          
          用法:tar jcvf 生成的壓縮包的名字(xxx.tar.bz2) 要壓縮的文件或目錄
          示例:tar jcvf alltxt.tar.bz2 *.txt test/      同時對文件和目錄進行打包壓縮
          
        • 解壓縮

          tar zxvf 壓縮包的名字                 解壓到當前目錄
          tar jxvf 壓縮包的名字 -C 目錄           解壓到指定目錄
          
      • rar

        • 參數

          a       Add壓縮
          x       Extract解壓縮
          r       壓縮時遞歸目錄,不加這個參數默認就是遞歸的
          
        • 壓縮

          用法:rar a 生成的壓縮文件的名字 壓縮的文件或目錄
          
          示例:
          rar a all *.txt         打包壓縮文件
          rar a dir dir/          打包壓縮目錄
          
        • 解壓縮

          用法:rar x 壓縮文件名 [解壓縮目錄]
          示例:rar x all.rar
          
      • zip

        • 參數

          r       壓縮目錄時加個參數用於遞歸目錄,不加不能壓縮
          
        • 壓縮

          用法:zip 壓縮包的名字 壓縮的文件或目錄
          示例:zip all *.txt
               zip -r myzip mytest/
          
        • 解壓縮

          用法:unzip 壓縮包的名字
             unzip 壓縮包的名字 -d 解壓的目錄
          示例:unzip all.zip
               unzip all.zip -d test/
          
  • 2、進程管理

    • 查看在線用戶狀態

      who                 查看當前在線用戶的狀態
      
      tty1~tty6           文字界面終端
      tty7                圖形界面終端
      pts                 虛擬終端
      Alt+Ctrl+F1~F7      切換終端,切換後各個終端互不影響
      
    • 查看進程

      ps aux                  查看在線用戶下所有進程
      ps aux | grep bash      進程過濾
      
    • 終止進程

      kill -l                 查看所有信號
      kill -SIGKILL 5179      終止進程
      kill -9 4678            終止進程
      
    • 查看當前進程的環境變量

      env                     查看所有環境變量
      env | grep PATH         只查看PATH環境變量
      
    • 查看系統狀態

      top
      
  • 3、網絡管理

    • 獲取網絡接口信息

      ifconfig 
      
    • 測試與目標主機連通性

      ping www.baidu.com -c 4     發送4個數據包後終止
      
    • 查看服務器域名對應的IP地址

      nslookup www.baidu.com
      
  • 4、用戶管理

    • 創建用戶

      adduser super       用戶名只能小寫,不能大寫
      useradd -s /bin/bash -g super -d /home/super -m super       用戶名可以大寫
      -s      指定新用戶登陸時shell類型
      -g      指定所屬組,該組必須已經存在
      -d      用戶家目錄
      -m      用戶家目錄不存在時,自動創建該目錄
      
    • 設置用戶組

      groupadd super
      
    • 刪除用戶

      deluser super
      userdel -r super        選項-r的作用是把用戶的主目錄一起刪除
      
    • 切換用戶

      su super
      
    • 修改用戶密碼

      passwd super
      
    • 退出當前用戶

      exit
      
    • 查看所有用戶信息

      vi /etc/passwd
      
  • 5、ftp服務器搭建

    • vsftpd作用:文件的上傳和下載
    • 服務器端

      • 安裝vsftpd

        apt-get install -y vsftpd       安裝完成後會隨系統啟動而自動啟動
        
      • 修改配置文件

        vi /etc/vsftpd.conf
        
        listen=YES
        anon_root=/home/super/anonFtp/      #指定匿名用戶根目錄,不指定默認是/srv/ftp/
        anonymous_enable=YES    #允許匿名用戶登錄
        write_enable=YES        #實名用戶擁有寫權限(上傳數據)
        local_umask=022         #設置本地掩碼為022
        anon_upload_enable=YES      #匿名用戶可以向ftp服務器上傳數據
        anon_mkdir_write_enable=YES     #匿名用戶可以在ftp服務器上創建目錄
        
      • 創建匿名用戶根目錄

        cd ~
        mkdir anonFtp
        chown ftp anonFtp
        chmod 777 anonFtp
        
      • 重啟服務

        service vsftpd retart
        
    • 客戶端

      • 實名用戶登錄

        ftp IP(server)
        輸入用戶名
        輸入密碼
        
        文件的上傳和下載
            文件的上傳: put file
            文件的下載: get file
            不允許操作目錄,如果想操作目錄 -- 打包tar/rar/zip
        
      • 匿名用戶登錄

        ftp IP(server)
        用戶名:anonymous
        密碼:直接回車
        
        不允許匿名用戶在任意目錄直接切換
        只能在一個指定目錄范圍內工作
        需要在ftp服務器上創建一個匿名用戶的目錄 -- 匿名用戶的根目錄
        
      • 退出

        quit        推薦
        bye         推薦
        exit        
        
    • lftp客戶端訪問ftp服務器

      • 一個ftp客戶端工具,可以上傳和下載目錄
      • 安裝

        apt-get install -y lftp
        
      • 登錄服務器

        • 匿名

          lftp IP(sever) 回車
          login
          
        • 實名

          lftp username@IP(sever) 回車
          輸入服務器密碼
          
      • 操作

        put file                上傳文件
        mput file1 file2        上傳多個文件
        get file                下載文件
        mget file1 file2        下載多個文件
        mirror dir              下載整個目錄及其子目錄
        mirror -R dir           上傳整個目錄及其子目錄
        
  • 6、nfs服務器搭建

    • net file system : 網絡文件系統,它允許網絡中的計算機之間通過TCP/IP網絡共享資源。
    • 服務器端

      • 安裝

        apt-get install nfs-kernel-server       安裝成功後會隨系統啟動而自動啟動
        
      • 創建共享目錄

        如: /home/super/NfsShare
        
      • 修改配置文件

        vi /etc/exports
        在文件最後加入下面設置:
        /home/super/NfsShare *(rw, sync)
        
      • 重啟服務

        service nfs-kernel-server restart
        
    • 客戶端

      • 掛載服務器共享目錄

        用法: mount serverIP:ShareDir /mnt
        示例: mount 192.168.10.100:/home/super/NfsShare /mnt
        
  • 7、ssh(Secure Shell)服務器

    • 服務器端

      • 安裝ssh

        apt-get install -y openssh-server
        aptitude show openssh-server
        
    • 客戶端

      • 遠程登錄

        ssh Username@ServerIP       
        
      • 退出登錄

        logout
        
  • 8、scp(Super Copy)命令

    • 使用該命令的前提條件

      目標主機已經安裝了openssh-server
      
    • 使用方法

      scp -r 目標用戶名@目標主機IP地址:/目標文件的絕對路徑 /保存到本機的絕對(相對)路徑
      scp -r [email protected]:/home/super/SCP/ ./mydir/
      
  • 9、其他命令

    • 翻頁

      Shift+PageUp        上翻頁
      Shift+PageDown      下翻頁
      
    • 清屏

      clear
      Ctrl+l
      
    • 創建終端

      Ctrl+Alt+T      Ubuntu
      Ctrl+Shift+T    添加新標簽頁
      
    • 看手冊

      man man
      
      一共有九個章節,1,2,3,5是重點:
      1   可執行程序或 shell 命令
      2   系統調用(內核提供的函數)
      3   庫調用(程序庫中的函數)
      4   特殊文件(通常位於 /dev)
      5   文件格式和規范,如 /etc/passwd
      6   游戲
      7   雜項(包括宏包和規范,如man(7),groff(7))
      8   系統管理命令(通常只針對root用戶)
      9   內核例程 [非標准
      
    • 設置查看別名

      alias                   查看
      alias l='ls -al'        設置
      
    • 在顯示器上顯示數據

      echo "hello"    打印字符串
      echo $PATH      打印環境變量
      echo $?         顯示上一次程序退出值
      
  • 10、關機重啟

    • poweroff
    • reboot
    • shutdown

      • 參數

        -t      秒數:設定在切換至不同的runlevel之前,警告和刪除兩訊號之間的延遲時間(秒)
        -k      僅送出警告訊息文字,但不是真的要shutdown
        -r      shutdown之後重新開機
        -h      shutdown之後關機
        -n      不經過init,由shutdown指令本身來做關機動作(不建議使用)
        -f      重新開機時,跳過fsck指令,不檢查檔案系統
        -F      重新開機時,強迫做fsck檢查
        -c      將已經正在shutdown的動作取消
        
      • 示例

        shutdown -r now     #立即重啟
        shutdown -h now     #立即關機
        shutdown -k now 'Hey! Go away! now...'      #發出警訊息,但沒有真的關機
        shutdown -t3 -r now     #立即重啟,但在警告和刪除processes之間,延遲3秒鐘
        shutdown -h 10:42 'Hey! Go away!'   #10:42關機
        shutdown -r 10 'Hey! Go away!'      #10分鐘後關機
        shutdown -c     #取消shutdown指令,必須切換至其他tty,登入之後,才能下些命令
        shutdown now    #切換至單人操作模式(不加任何選項時)
        

三、vim和函數庫

1、vim編輯器的使用

1.1、vim簡介

  • Vim是從 vi 發展出來的一個文本編輯器。代碼補全、編譯及錯誤跳轉等方便編程的功能特別豐富,在程序員中被廣泛使用,和Emacs並列成為類Unix系統用戶最喜歡的文本編輯器。

1.2、工作模式

  • 命令模式 -- 打開文件之後,默認進入命令模式。

    • 移動光標

      h           左
      j           下
      k           下
      l           右
      0           行首
      $           行尾
      gg          文件頭部
      G           文件尾部
      5G          行跳轉,移到第五行
      
    • 刪除操作(不是真正意義上的刪除,更象是剪切操作)

      x           刪除光標後一個字符
      X           刪除光標前一個字符
      dw          刪除光標後一個單詞
      d0          刪除光標到行首的所有字符
      D(d$)       刪除光標到行尾的所有字符
      dd          刪除一行
      5dd         刪除五行
      
    • 撤消操作

      u           撤消
      ctrl+r      還原前一個操作
      
    • 復制粘貼

      p           小寫的p,粘貼到光標的下一行
      P           大寫的p,粘貼到光標的所在行
      yy          復制一行
      5yy         復制五行
      
    • 可視模式

      v           切換到可視塊模式
      h/j/k/l     調整選中塊
      y           復制
      d           刪除
      p           粘貼
      
    • 查找模式

      /           切換到查找模式,向下查找
      ?           切換到查找模式,向上查找
      n           下一個匹配
      N           上一個匹配
      #           移到要查找的單詞上,按#號即可開啟查找模式
      
    • 字符替換

      r           單個字符替換
      
    • 行縮進

      >>          向右縮進
      <<          向左縮進
      
    • 查看函數man文檔

      K           先輸入3(庫函數章節),再輸入K,以查看指定函數的man文檔
      
  • 編輯模式 -- 需要輸入一些命令,切換到編輯模式。

    a       在光標所在位置的後邊插入
    A       在當前行的尾部插入
    
    i       在光標所在位置的前邊插入
    I       在光標所在行的行首插入
    
    o       在光標所在行的下邊開辟一個新的行
    O       在光標所在行的上邊開辟一個新的行
    
    s       刪除光標後邊的字符
    S       刪除光標所有的行
    
  • 末行模式 -- 在末行模式下可以輸入一些命令。

    :s/tom/jack/g           把光標所在行的tom替換成jack
    :%s/tom/jack/g          把整個文檔的tom替換成jack
    :25,30s/tom/jack/g      把25到30行的tom替換成jack
    
    :q          退出
    :q!         強制退出
    :w          保存
    :wq         保存並退出
    :x          相當於:wq
    ZZ          相當於:wq
    
  • 分屏操作

    :sp [file]      將屏幕水平分成兩部分
    :vsp [file]     交屏幕垂直分成兩部分
    :wqall          同時保存打開文件
    ctrl+ww         切換兩個屏幕
    
  • vim打造成IDE

    /etc/vim/vimrc      系統級配置文件
    ~/.vim/vimrc        用戶級配置文件
    

2、gcc編譯器

  • gcc編譯的四個階段:

    hello.c  -------->   hello.i  -------->    hello.s  -------->    hello.o  ------->    hello.out
            預處理編譯器(cpp)     編譯器(gcc)          匯編器(as)           鏈接器(ld)
            gcc -E                gcc -S                gcc -c                gcc
    
  • 編譯工具鏈:

            預處理編譯器:cpp     gcc -E hello.c -o hello.i   頭文件展開,宏替換,注釋去掉
                 編譯器:gcc     gcc -S hello.i -o hello.s   c文件變成匯編文件
                 匯編器:as      gcc -c hello.s -o hello.o   匯編文件變成二進制文件
                 鏈接器:ld      gcc hello.o -o hello        將函數庫中相應的代碼組合到目標文件中
    
  • 直接編譯生成可執行文件

    gcc hello.c -o hello
    
  • 編譯時指定頭文件目錄-I

    gcc hello.c -I ./include hello
    
  • 編譯時指定宏,通常用於調試代碼-D

    gcc hello.c -D DEBUG
    
    在需要打印日志的代碼中加上下面的語句:
    #ifdef DEBUG
        printf("debug info");
    #endif
    
  • 編譯時對代碼進行優化-O3

    gcc hello.c -o hello -O3 
    級別:
    0   沒有優化
    1   缺省值
    3   優化級別最高
    
  • 編譯時顯示告警信息-Wall

    gcc hello.c -o hello -Wall
    
  • 編譯時包含調試信息-g(gdb)

    gcc hello.c -o hello -g
    
  • 查看編譯版本

    gcc -v
    gcc --version
    

3、靜態庫的創建和使用

  • 准備

    目錄結構
    myCalc
    ├── include
    │   └── head.h
    ├── lib
    │   └── libMyCalc.a
    ├── main.c
    └── src
        ├── add.c
        ├── div.c
        ├── mul.c
        ├── sub.c
    
  • 命名格式

    • lib開頭。
    • 靜態庫名。
    • .a結尾。

      示例 : libMyCalc.a
      
  • 描述

    • 優點
      • 尋址方便、速度快。
      • 庫被打包到可執行程序中,直接發布可執行程序即可使用。
    • 缺點
      • 靜態庫的代碼在編譯過程中已經被載入可執行程序,因此體積較大。
      • 如果靜態函數庫改變了,那麼你的程序就必須重新編譯。
    • 使用場合
      • 在核心程序上使用,保證速度,忽略空間。
      • 主流應用於80、90年代,現在很少使用。
  • 制作

    • 得到與位置有關的*.o

      cd ~/myClac/src
      gcc *.c -c -I ../include
      
    • 將生成的*.o文件打包成靜態庫libMyCalc.a

      ar rcs libMyCalc.a *.o
      
      ar工具不包含在一gcc中。
      參數:
      r       將文件夾插入到靜態庫中。
      c       創建靜態庫,不管庫是否存在。
      s       寫入一個目標文件索引到庫中,或者更新一個存在的目標文件。
      
      制作好以後移動到lib目錄中
      mv libMyCalc.a ../lib
      
    • 查看庫中的符號(函數)

      nm libMyCalc.a
      
    • 發布和使用靜態庫

      • 發布靜態庫,把includelib目錄打包給用戶。
      • 使用

        • main.c中包含頭文件

          #inlcude "head.h"
          
        • 兩種編譯方式

          gcc main.c lib/libMyCalc.a -I include -o myapp
          gcc main.c -I include -L lib -l MyCalc -o myapp
          
        • 執行myapp

          ./myapp
          

4、動態庫的創建和使用

  • 准備

    目錄結構
    myCalc
    ├── include
    │   └── head.h
    ├── lib
    │   └── libMyCalc.so
    ├── main.c
    └── src
        ├── add.c
        ├── div.c
        ├── mul.c
        ├── sub.c
    
  • 命名格式

    • lib開頭。
    • 靜態庫名。
    • .so結尾。

      示例 : libMyCalc.so
      
  • 描述

    • 優點
      • 執行程序體積小。
      • 動態庫更新了,不需要重新編譯程序,前提是函數接口不變。
    • 缺點
      • 發布程序的時候,需要將動態庫提供給用戶。
      • 動態庫沒有被打包到應用程序中,加載速度相對較慢。
    • 使用場合
      • 現代應用程序中常用。
  • 制作

    • 生成與位置無關的*.o

      cd ~/myClac/src
      gcc -fPIC *.c -c -I ../include
      
    • 將生成的*.o文件打包成共享庫(動態庫)libMyCalc.so

      gcc -shared -o libMyCalc.so *.o -I ../include
      
      制作好以後移動到lib目錄中
      mv libMyCalc.so ../lib
      
    • 查看庫中的符號(函數)

      nm libMyCalc.so
      
    • 發布和使用靜態庫

      • 發布靜態庫,把includelib目錄打包給用戶。
      • 使用

        • main.c中包含頭文件

          #inlcude "head.h"
          
        • 兩種編譯方式

          gcc main.c lib/libMyCalc.so -I include -o myapp
          gcc main.c -I include -L lib -l MyCalc -o myapp
          
        • 執行myapp

          ./myapp
          
        • 查看可執行文件夾所依賴的動態庫

          ldd myapp
          
        • 解決依賴的動態庫無法加載的問題

          • libMyCalc.so拷貝到/lib目錄下(不推薦使用,容易與系統庫沖突)

            cp lib/libMyCalc.so /lib
            
          • 設置環境變量LD_LIBRARY_PATH(測試時使用)

            export LD_LIBRARY_PATH=./lib    只對當前會話有效
            
          • 設置環境變量LD_LIBRARY_PATH到~/.bashrc中(測試時使用)

            vi ~/.bashrc
            export LD_LIBRARY_PATH=/home/super/myCalc/lib       會話每次開啟就會生效
            
          • 設置配置文件/etc/ld.so.conf(推薦使用),重啟終端

            • 編輯動態連接器的配置文件

              vi /etc/ld.so.conf
              
            • 動態庫的路徑寫到配置文件中

              /home/super/myCalc/lib
              
            • 更新動態庫

              ldconfig -v
              

四、makefile和文件IO

1、gdb調試

  • 1.1、啟動gdb

    gdb app
    
  • 1.2、查看代碼

    >>>(gdb) l          #list
    >>>(gdb) l 行號或函數名
    >>>(gdb) l 文件名:行號或函數名
    
  • 1.3、設置斷點

    • 設置當前文件斷點

      >>>(gdb) b      #break
      >>>(gdb) b 行號或函數名
      >>>(gdb) b 文件名:行號或函數名
      
    • 設置條件斷點

      >>>(gdb) b 10 if value==19
      
    • 刪除斷點

      >>>(gdb) d 斷點的編號        #delete或del
      
  • 1.4、查看設置的斷點

    >>>(gdb) i b            #info, 可以獲取斷點的編號,刪除斷點時用
    
  • 1.5、開始執行gdb調試

    >>>(gdb) start      #只執行一步
    >>>(gdb) c          #continue,直接停在斷點的位置
    >>>(gdb) run        #有斷點會停在斷點處,沒有會直接跑完程序,較少用
    
  • 1.6、單步調試

    >>>(gdb) s          #進入函數體內部
    >>>(gdb) finish     #從函數體內部跳出
    >>>(gdb) n          #不進入函數體內部
    >>>(gdb) u          #退出當前循環
    
  • 1.7、查看變量的值

    >>>(gdb) p      print
    
  • 1.8、查看變量的類型

    >>>(gdb) ptype 變量名
    
  • 1.9、設置變量的值

    >>>(gdb) set var 變量=值
    
  • 1.10、設置追蹤變量

    >>>(gdb) display 變量        #設置追蹤變量
    >>>(gdb) info display        #獲取變量的編號
    >>>(gdb) undisplay 編號       #取消追蹤變量
    
  • 1.10、退出gdb調試

    >>>(gdb) quit
    

2、makefile的編寫

2.1、makefile的命名

    makefile
    Makefile

    注:兩種任選其中一種,其他名稱不行。

2.2、makefile的規則

  • 規則中的三要素:目標、依賴、命令

    • makefile文件內容格式

      目標:依賴文件
          命令
      
    • makefile文件內容簡單示例

      app:main.c add.c sub.c mul.c div.c
          gcc main.c add.c sub.c mul.c div.c -o app
      
    • 第二行必須有一個tab縮進。

  • 子目標和終極目標

    • 示例

      #終極目標
      app:main.o add.o sub.o div.o
          gcc main.o add.o sub.o div.o -o app
      #子目標
      main.o:main.c
          gcc -c main.c
      #子目標
      add.o:add.c
          gcc -c add.c
      #子目標
      sub.o:sub.c
          gcc -c sub.c
      #子目標
      mul.o:mul.c
          gcc -c mul.c
      #子目標
      div.o:div.c
          gcc -c div.c
      
    • 好處

      • 當其他一個文件被修改時,只會編譯修改的文件,再打包生成app,編譯效率高。
  • 更新目標的原則

2.3、makefile的兩個函數

  • wildcard:取得目錄下的所有文件
  • patsubst:將目標下的所有文件作替換
  • 示例

    #自定義變量
    src=$(wildcard ./*.c)
    obj=$(patsubst ./%.c, ./%.o, $(src))
    target=app
    #終極目標
    $(target):$(obj)
        gcc $(obj) -o $(target)
    #子目標
    %.o:%.c
        gcc -c $< -o $@
    

2.4、makefile的三個自動變量

  • 普通變量

    • 變量取值:foo = $(obj)
    • 由makefile維護的一些變量
      • 通常格式都是大寫
        • CC: 默認值是cc
      • 有些有默認值,有些沒有
        • CPPFLAGS: 預處理器需要的選項,如:-I
        • CFLAGS: 編譯的時候使用的參數 -Wall -g -c
        • LDFLAGS: 鏈接庫使用的選項 -L -l
      • 用戶可以修改這些變量的默認值
        • CC = gcc
  • 自動變量

    • 變量
      • $< 規則中的第一個依賴條件
      • $@ 規則中的目標
      • $^ 規則中的所有依賴條件
      • 以上三種變量只能在規則的命令中使用
    • 模式規則

      • 在規則的目標定義中使用%
      • 在規則的依賴條件中使用%
      • 示例

        #自定義變量
        src=$(wildcard ./*.c)
        obj=$(patsubst ./%.c, ./%.o, $(src))
        target=app
        #makefile維護的變量
        CC = gcc
        CPPFLAGS = -I
        #終極目標
        $(target):$(obj)
            $(CC) $^ -o $@
        #子目標
        %.o:%.c
            $(CC) -c $< -o $@
        #偽目標
        .PHONY:clean
        clean:
            #命令前面加-表示,如果命令執行失敗則忽略這個命令
            -makir /release
            rm -f $(obj) $(target)
        

3、系統IO函數

3.1、一些概念

  • C庫IO函數工作流程 C庫IO函數工作流程

  • 虛擬內存地址空間 虛擬內存地址空間

  • pcb與文件描述符 pcb與文件描述符

  • 庫函數與系統函數之間的關系 庫函數與系統函數之間的關系

  • CPU為什麼要使用虛擬地址空間與物理地址空間映射?解決了什麼問題?

    • 方便編譯器和操作系統安排程序的地址分布。
      • 程序可以使用一系列相鄰的虛擬地址來訪問物理內存中不相鄰的大內存緩沖區
    • 方便進程之間隔離
      • 不同進程使用的虛擬地址彼此隔離,一個進程中的代碼無法更改正在由另一個進程使用的物理內存。
    • 方便OS使用你那可憐的內存
      • 程序可以使用一系列虛擬地址來訪問大於可用物理內存的內存緩沖區。當物理內存的供應量變小時,內存管理器會將物理內存頁(通常大小為4KB)保存到磁盤文件。數據或代碼頁會根據需要在物理內存和磁盤之間移動。
  • 查看幫助文檔

    man 2 open
    man 3 printf
    
  • errno

    • 定義在頭文件/usr/include/error.h
      • 全局變量
      • 任何標准C庫函數都能對其進行修改(Linux系統函數更可以)
  • 錯誤宏定義位置
    • 第1-34個錯誤定義:/usr/include/asm-generic/errno-base.h
    • 第35-133個錯誤定義:/usr/include/asm-generic/errno.h
  • 是記錄系統的最後一次錯誤代碼。代碼是一個int型的值。
    • 第個errno值對應著以字符串表示的錯誤類型。
    • 當調用“某些”函數出錯時,該函數會重新設置errno的值。
  • perror函數
    • 頭文件stdio.h
    • 函數定義void perror(const char * s)
    • 函數說明
      • 用來將上一個函數發生的錯誤的原因輸出到標准設備(stderr)。
      • 參數s所指的字符串會先打印出,後面再加上錯誤原因字符串。
      • 些錯誤原因依照全局變量error的值來決定要輸出的字符串。

3.2、open

  • 函數定義

    int open(const char *pathname, int flags);
    int open(const char *pathname, int flags, mode_t mode);
    
  • 功能

    打開文件。
    
  • 參數

    pathname    文件路徑,如./hello.c
    flags       文件訪問模式,O_RDONLY, O_WRONLY, O_RDWR, 更多見man 2 open
    mode        文件權限設置,實際結果是mode & umask
    
  • 返回值

    返回一個文件描述fd,-1表示打開文件時發生錯誤。
    
  • 示例

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    int main()
    {
        int fd; 
        //打開文件
        fd = open("hello.c", O_RDWR);
        //打開文件,不存在則創建並設置權限為:755 & umask
        fd = open("hello.c", O_RDWR | O_CREAT, 0755);
        //打開文件,不存在則創建並設置權限為:755 & umask,另判斷文件是否存在
        fd = open("hello.c", O_RDWR | O_CREAT | O_EXCL, 0755);
        //打開文件並清空文件裡的內容
        fd = open("hello.c", O_RDWR | O_TRUNC);
    
        printf("fd = %d\n", fd);
        //打開失敗則打印錯誤並退出程序
        if(fd == -1) 
        {   
            perror("open file failure");
            exit(1);
        }   
    
        int ret = close(fd);
        printf("ret = %d\n", ret);
        //關閉失敗則打印錯誤並退出程序
        if(ret == -1) 
        {   
            perror("close file failure");
            exit(1);
        }   
        return 0;
    }
    

3.3、read

  • 函數定義

    ssize_t read(int fd, void *buf, size_t count);
    
  • 功能

    讀取文件。
    
  • 參數

    fd          文件描述符
    buf         緩沖區
    count       讀取多少字節數
    
  • 返回值

    有符號int型值
    -1      表示讀文件失敗
    0       表示文件讀完了
    >0      表示讀取的字節數
    

3.4、write

  • 函數定義

    ssize_t write(int fd, const void *buf, size_t count);
    
  • 功能

    寫入文件。
    
  • 參數

    fd          文件描述符
    buf         緩沖區
    count       讀取多少字節數
    
  • 返回值

    有符號int型值
    -1      表示寫文件失敗
    0       表示什麼都沒寫
    >0      表示寫了多少字節數
    
  • 示例

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    
    int main()
    {
        //以只讀方式找開文件
        int fd = open("english.txt", O_RDONLY);
        if(fd == -1)
        {
            perror("open");
            exit(1);
        }
        //以寫的方式找開文件,文件不存在則創建
        int fd1 = open("newfile", O_CREAT | O_WRONLY, 0664);
        //打開失敗,打印錯誤並退出程序
        if(fd1 == -1)
        {
            perror("open1");
            exit(1);
        }
    
        char buf[2048] = {0};
        //每次讀取2048字節
        int count = read(fd, buf, sizeof(buf));
        //讀取失敗,打印錯誤並退出程序
        if(count == -1)
        {
            perror("read");
            exit(1);
        }
        while(count)
        {
            //寫入文件
            int ret = write(fd1, buf, count);
            printf("write bytes %d\n", ret);
            //繼續讀取內容
            count = read(fd, buf, sizeof(buf));
        }
        //關閉文件
        close(fd);
        close(fd1);
        return 0;
    }
    

3.5、close

  • 函數定義

    int close(int fd);
    
  • 功能

    關閉文件。
    
  • 參數

    fd      文件描述符
    
  • 返回值

    0       表示關閉成功
    -1      表示關閉失敗
    

3.6、lseek

  • 函數定義

    off_t lseek(int fd, off_t offset, int whence);
    
  • 功能

    1、獲取文件大小。
    2、移動文件指針。
    3、文件拓展。
    
  • 參數

    fd          文件描述符
    offset      文件指針偏移量
    whence      來源,主要值有:SEEK_SET、SEEK_CUR、SEEK_END等
    
  • 返回值

    有符號int型值
    -1      表示讀文件失敗
    0       表示文件讀完了
    >0      表示讀取的字節數
    
  • 示例

    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        int fd = open("aa", O_RDWR);
        if(fd == -1)
        {
            perror("open file");
            exit(1);
        }
    
        int ret = lseek(fd, 0, SEEK_END);
        printf("file length = %d\n", ret);
    
        //文件拓展
        ret = lseek(fd, 2000, SEEK_END);
        printf("return value = %d\n", ret);
    
        //實現文件拓展,需要再最後做一次寫操作
        write(fd, "a", 1);
    
        close(fd);
        return 0;
    }
    

五、一些系統函數的使用

1、Linux文件操作相關函數

stat函數

  • 函數定義

    int stat(const char *pathname, struct stat *buf);
    
  • 功能

    獲取文件屬性(從inode上獲取)。
    
  • 參數

    pathname        文件名
    buf             結構體指針stat
    
  • 返回值

    0       成功
    -1      失敗
    
  • 文件屬性

    struct stat 
    {
           dev_t     st_dev;         /* 文件的設備編號 */
           ino_t     st_ino;         /* 節點 */
           mode_t    st_mode;        /* 文件的類型和存取的權限 */
           nlink_t   st_nlink;       /* 鏈接到該文件的硬鏈接數目,剛建立的文件值為1 */
           uid_t     st_uid;         /* 用戶ID */
           gid_t     st_gid;         /* 組ID */
           dev_t     st_rdev;        /* (設備類型)若此文件為設備文件,則為其設備編號 */
           off_t     st_size;        /* 文件字節數(文件大小) */
           blksize_t st_blksize;     /* 塊大小(文件系統的I/O, 緩沖區的大小) */
           blkcnt_t  st_blocks;      /* 塊數 */
           struct timespec st_atim;  /* 最後一次訪問時間 */
           struct timespec st_mtim;  /* 最後一次修改時間 */
           struct timespec st_ctim;  /* 最後一次改變時間(屬性) */
    }
    
  • 特性

    • 能夠穿透(跟蹤)符號鏈接。如果是軟鏈接,會統計原始文件信息,而不是軟鏈接的信息。
  • 示例

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <stdlib.h>
    #include <time.h>
    #include <pwd.h>
    #include <grp.h>
    
    int main(int argc, char * argv[])
    {
        if(argc < 2)
        {
            printf("./a.out filename\n");
            exit(1);
        }
    
        struct stat st;
        int ret = stat(argv[1], &st);
        if(ret == -1)
        {
            perror("stat");
            exit(1);
        }
        //存儲文件類型和訪問權限
        char perms[11] = {0};
        //判斷文件類型
        switch(st.st_mode & S_IFMT)
        {
            case S_IFLNK:
                perms[0] = 'l';
                break;
            case S_IFDIR:
                perms[0] = 'd';
                break;
            case S_IFREG:
                perms[0] = '-';
                break;
            case S_IFBLK:
                perms[0] = 'b';
                break;
            case S_IFCHR:
                perms[0] = 'c';
                break;
            case S_IFSOCK:
                perms[0] = 's';
                break;
            case S_IFIFO:
                perms[0] = 'p';
                break;
            default:
                perms[0] = '?';
                break;                
        }
    
        //判斷文件的訪問權限
        //文件所有者
        perms[1] = (st.st_mode & S_IRUSR) ? 'r' : '-';
        perms[2] = (st.st_mode & S_IWUSR) ? 'w' : '-';
        perms[3] = (st.st_mode & S_IXUSR) ? 'x' : '-';
        //文件所屬組
        perms[4] = (st.st_mode & S_IRGRP) ? 'r' : '-';
        perms[5] = (st.st_mode & S_IWGRP) ? 'w' : '-';
        perms[6] = (st.st_mode & S_IXGRP) ? 'x' : '-';
        //其他人
        perms[7] = (st.st_mode & S_IROTH) ? 'r' : '-';
        perms[8] = (st.st_mode & S_IWOTH) ? 'w' : '-';
        perms[9] = (st.st_mode & S_IXOTH) ? 'x' : '-';
    
        //硬鏈接計數
        int linkNum = st.st_nlink;
        //文件所有者
        char * fileUser = getpwuid(st.st_uid)->pw_name;
        //文件所屬組
        char * fileGrp = getgrgid(st.st_gid)->gr_name;
        //文件大小
        int filesize = (int)st.st_size;
        //修改時間
        char * time = ctime(&st.st_mtime);
        char mtime[512] = {0};
        strncpy(mtime, time, strlen(time) - 1);
    
        char buf[1024];
        sprintf(buf, "%s %d %s %s %d %s %s", perms, linkNum, fileUser, fileGrp, fileSize, mtime, argv[1]);
    
        printf("%s\n", buf);
    
        return 0;
    }
    
  • st_mode

    • 該變量占兩字節,共16位。
    • 掩碼的使用:st_mode & 掩碼
    • 其他人權限(0-2 bit)

      S_IROTH 00004 讀權限
      S_IWOTH 00002 寫權限
      S_IXOTH 00001 執行權限
      S_IRWXO 00007 掩碼
      
    • 所屬組權限(3-5 bit)

      S_IRGRP 00040 讀權限
      S_IWGRP 00020 寫權限
      S_IXGRP 00010 執行權限
      S_IRWXG 00070 掩碼
      
    • 文件所有者權限(6-8 bit)

      S_IRUSR 00400 讀權限
      S_IWUSR 00200 寫權限
      S_IXUSR 00100 執行權限
      S_IRWXU 00700 掩碼
      
    • 特殊權限位(9-11 bit),很少用

      S_ISUID 0004000 設置用戶ID
      S_ISGID 0002000 設置組ID
      S_ISVTX 0001000 黏住位
      
    • 文件類型(12-15 bit)

      S_IFSOCK 0140000 套接字
      S_IFLNK 0120000 符號鏈接(軟鏈接)
      S_IFREG 0100000 普通文件
      S_IFBLK 0060000 塊設備
      S_IFDIR 0040000 目錄
      S_IFCHR 0020000 字符設備
      S_IFIFO 0010000 管道
      S_IFMT 0170000 掩碼
      

st_mode

lstat函數

  • 功能和用法與stat相同
  • 特性:不穿透(跟蹤)符號鏈接。如果是軟鏈接,會統計軟鏈接的信息,而不是原始文件的信息。
  • 鏈接的追蹤 鏈接的追蹤

access函數

  • 函數定義

    int access(const char *pathname, int mode);
    
  • 功能

    測試指定文件是否擁有某種權限。
    
  • 參數

    pathname        文件名
    mode            權限類別
                    R_OK        是否有讀權限
                    W_OK        是否有寫權限
                    X_OK        是否有執行權限
                    F_OK        測試一個文件是否存在
    
  • 返回值

    0       所有欲查核的權限都通過了檢查
    -1      有權限被禁止
    
  • 示例

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    int main(int argc, char * argv[])
    {
        if(argc < 2)
        {
            printf("access filename\n");
            exit(1);
        }
    
        int ret = access(argv[1], W_OK);
        if(ret == -1)
        {
            perror("access");
            exit(1);
        }
        printf("you can write this file.\n");
        return 0;
    }
    

chmod函數

  • 函數定義

    int chmod(const char *pathname, mode_t mode);
    
  • 功能

    改變文件的權限
    
  • 參數

    pathname        文件名
    mode            權限,必須是一個8進制數字,轉換用strtol函數
    
  • 返回值

    0       改變成功
    -1      失敗
    
  • 示例

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/stat.h>
    
    int main(int argc, char * argv[])
    {
        if(argc < 2)
        {
            printf("chmod filename\n");
            exit(1);
        }
    
        int ret = chmod(argv[1], 0755);
        if(ret == -1)
        {
            perror("chmod");
            exit(1);
        }
        return 0;
    }
    

chown函數

  • 函數定義

    int chown(const char *pathname, uid_t owner, gid_t group);
    
  • 功能

    改變文件的所有者
    
  • 參數

    pathname        文件名
    owner           文件所有者ID
    group           文件所屬組ID
    
    查看UID和GID:/etc/passwd
    
  • 返回值

    0       成功
    -1      失敗
    
  • 示例

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    int main(int argc, char * argv[])
    {
        if(argc < 2)
        {
            printf("chown filename\n");
            exit(1);
        }
    
        int ret = chown(argv[1], 116, 125);
        if(ret == -1)
        {
            perror("chown");
            exit(1);
        }
        return 0;
    }
    

truncate函數

  • 函數定義

    int truncate(const char *path, off_t length);
    
  • 功能

    將參數path指定的文件大小改為參數length指定的大小。如果原來的文件大小比參數length大,則超過部分會被刪去。
    
  • 參數

    path        文件路徑
    length      指定文件的大小
    
  • 返回值

    0       成功
    -1      失敗
    

連接函數

  • link函數

    • 函數定義

      int link(const char *oldpath, const char *newpath);
      
    • 功能

      創建一個硬鏈接。
      
  • symlink函數

    • 函數定義

      int symlink(const char *target, const char *linkpath);
      
    • 功能

      創建一個軟鏈接。
      
  • readlink函數

    • 函數定義

      ssize_t readlink(const char *pathname, char *buf, size_t bufsiz);
      
    • 功能

      讀軟鏈接對應的文件名,而不是讀內容。
      
    • 示例

      #include <stdio.h>
      #include <stdlib.h>
      #include <unistd.h>
      
      int main(int argc, char * argv[])
      {
          if(argc < 2)
          {
              printf("readlink filename\n");
              exit(1);
          }
      
          char buf[512];
          int ret = readlink(argv[1], buf, sizeof(buf));
          if(ret == -1)
          {
              perror("readlink");
              exit(1);
          }
          buf[ret] = 0;
          printf("buf = %s\n", buf);
      
          return 0;
      }
      
  • unlink函數

    • 函數定義

      int unlink(const char *pathname);
      
    • 功能

      刪除一個文件的目錄並減少它的鏈接數,若成功則返回0,否則返回-1,錯誤原因存於errno。
      如果想調用這個函數來成功刪除文件,你就必須擁有這個文件的所屬目錄的寫和執行權限。
      
    • 使用

      如果是符號鏈接,刪除符號鏈接。
      如果是硬鏈接,硬鏈接數減1,,當減為0時,釋放數據塊和inode。
      如果文件硬鏈接數為0,但有進程已打開該文件,並持有文件描述符,則等該進程關閉該文件時,kernel才真正去刪除該文件。
      
    • 示例

      #include <stdio.h>
      #include <stdlib.h>
      #include <sys/types.h>
      #include <sys/stat.h>
      #include <unistd.h>
      #include <fcntl.h>
      
      int main()
      {
          int fd = open("tempfile", O_CREAT | O_RDWR, 0664);
          if(fd == -1)
          {
              perror("open");
              exit(1);
          }
          //刪除臨時文件
          int ret = unlink("tempfile");
      
          //write file
          write(fd, "hello\n", 5);
      
          //重置文件指針
          lssek(fd, 0, SEEK_SET);
      
          //read file
          char buf[24] = {0};
          int len = read(fd, buf, sizeof(buf));
      
          //將讀出的內容寫在屏幕上
          write(1, buf, len);
      
          //close file
          close(fd);
          return 0;
      }
      

rename函數

  • 函數定義

    int rename(const char *oldpath, const char *newpath);
    
  • 功能

    文件重命名。
    

2、Linux目錄操作相關函數

chdir函數

  • 函數定義

    int chdir(const char *path);
    
  • 功能

    修改當前進程的路徑。
    

getcwd函數

  • 函數定義

    char *getcwd(char *buf, size_t size);
    
  • 功能

    獲取當前進程工作目錄。
    

mkdir函數

  • 函數定義

    int mkdir(const char *pathname, mode_t mode);
    
  • 功能

    創建目錄。
    注意:創建的目錄需要有執行權限,否則無法進入目錄。
    

rmdir函數

  • 函數定義

    int rmdir(const char *pathname);
    
  • 功能

    刪除一個空目錄。
    

opendir函數

  • 函數定義

    DIR *opendir(const char *name);
    
  • 功能

    打開一個目錄。
    

readdir函數

  • 函數定義

    struct dirent *readdir(DIR *dirp);
    
  • 功能

    讀目錄。
    
  • 返回值

    struct dirent {
        ino_t          d_ino;       /* 此目錄進入點的inode */
        off_t          d_off;       /* 目錄文件開頭至此目錄進入點的位移 */
        unsigned short d_reclen;    /* d_name的長度,不包含NULL字符 */
        unsigned char  d_type;      /* d_name所指的文件類型 */
        char           d_name[256]; /* 文件名 */
    };
    
    d_type:
    DT_BLK      This is a block device.
    DT_CHR      This is a character device.
    DT_DIR      This is a directory.
    DT_FIFO     This is a named pipe (FIFO).
    DT_LNK      This is a symbolic link.
    DT_REG      This is a regular file.
    DT_SOCK     This is a UNIX domain socket.
    DT_UNKNOWN  The file type is unknown.
    
    -D_BSD_SOURCE 編譯時添加宏定義
    

colsedir函數

  • 函數定義

    int closedir(DIR *dirp);
    
  • 功能

    關閉目錄。
    
  • 示例

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <dirent.h>
    
    int get_file_count(char * root)
    {
        DIR * dir = NULL;
        dir = opendir(root);
        if(dir == NULL)
        {
            perror("opendir");
            exit(1);
        }
    
        struct dirent * ptr = NULL;
        char path[1024] = {0};
        int total = 0;
        while(ptr = readdir(dir) != NULL)
        {
            //過濾.和..
            if(strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0)
            {
                continue;
            }
            //如果是目錄
            if(ptr->d_type == DT_DIR)
            {
                sprintf(path, "%s/%s", root, ptr->d_name);
                total += getFileNum(path);
            }
            //如果是文件
            if(ptr->d_type == DT_REG)
            {
                total++;            
            }
        }
    
        closedir(dir);
        return total;
    }
    
    int main(int argc, char * argv[])
    {
        if(argc < 2)
        {
            printf("./a.out dir\n");
            exit(1);
        }
    
        int total = get_file_count(argv[1]);
        printf("%s has file numbers %d\n", argv[1], total);
    
        return 0;
    }
    

6、fcntl函數

  • 函數定義

    int fcntl(int fd, int cmd, ... /* arg */ );
    
  • 功能

    改變已經打開的文件的屬性。
    1、復制一個現有的描述符 -- cmd
            F_DUPFD
    2、獲取/設置文件描述符標記 -- cmd
            F_GETFD
            F_SETFD
    3、獲取/設置文件狀態標記 -- cmd
            F_GETFL
                        O_RDONLY        只讀打開
                        O_WRONLY        只寫打開
                        O_RDWR          讀寫打開
                        O_EXEC          執行打開
                        O_SEARCH        搜索打開目錄
                        O_APPEND        追加寫
                        O_NONBLOCK      非阻塞模式
    
            F_SETFL, 可更改的幾個標識
                        O_APPEND
                        O_NONBLOCK
    4、獲取/設置異步I/O所有權 -- cmd
            F_GETOWN
            F_SETOWN
    5、獲取/設置記錄鎖 -- cmd
            F_GETLK
            F_SETLK
            F_SETLKW
    
  • 示例

    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <string.h>
    
    int main(int argc, char * argv[])
    {
        int fd;
        int flag;
    
        //測試字符串
        char * p = "we are family!";
        cahr * q = "yes, man.";
    
        //只寫的方式找開文件
        fd = open("test.txt", O_WRONLY);
        if(fd == -1)
        {
            perror("open");
            exit(1);
        }
    
        //輸入新的內容,該部分會覆蓋原來舊的內容
        if(write(fd, p, strlen(p)) == -1)
        {
            perror("write");
            exit(1);
        }
    
        //使用F_GETFL命令得到文件狀態標志
        flag = fcntl(fd, F_GETFL, 0);
        if(flag == -1)
        {
            perror("fcntl");
            exit(1);
        }
    
        //將文件狀態標志添加“追加寫”選項
        flag |= O_APPEND;
        //將文件狀態修改為追加寫
        if(fcntl(fd, F_SETFL, flag) == -1)
        {
            perror("fcntl -- append write");
            exit(1);
        }
    
        //再次輸入新內容,該內容會追加到舊內容的後面
        if(write(fd, q, strlen(q)) == -1)
        {
            perror("write again");
            exit(1);
        }
    
        //關閉文件
        close(fd);
        return 0;
    }
    

7、dup, dup2函數

  • 函數定義

    int dup(int oldfd);
    int dup2(int oldfd, int newfd);
    
  • 功能

    復制現有的文件描述符。
    
  • 返回值

    dup返回的是文件描述符中沒有被占用的最小的文件描述符
    
  • 注意事項

    dup2兩種情況:
    1、old --> new, 如果new是一個被打開的文件描述符,在拷貝前先關掉new。
    2、old和new是同一個文件描述符,不會關掉new,直接返回old。
    
  • dup示例

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    int main()
    {
        int fd = open("a.txt", O_RDWR);
        if(fd == -1)
        {
            perror("open");
            exit(1);
        }
    
        printf("file open fd = %d\n", fd);
    
        //找到進程文件描述表中==第一個==可用的文件描述符
        //將參數指定的文件復制到該描述符後,返回這個描述符
        int ret = dup(fd);
        if(ret == -1)
        {
            perror("dup");
            exit(1);
        }
        printf("dup fd = %d\n", ret);
        char * buf = "你是猴子派來的救兵嗎???\n";
        char * buf1 = "你大爺的,我是程序猿!!!\n";
    
        write(fd, buf, strlen(buf));
        write(ret, buf1, strlen(buf1));
    
        close(fd);
        return 0;
    }
    
  • dup2示例

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    int main()
    {
        int fd = open("english.txt", O_RDWR);
        if(fd == -1)
        {
            perror("open");
            exit(1);
        }
    
        int fd1 = open("a.txt", O_RDWR);
        if(fd1 == -1)
        {
            perror("open");
            exit(1);
        }
    
        printf("file open fd = %d\n", fd);
        printf("file open fd1 = %d\n", fd1);
    
        //調用dup2後,fd1和fd同時指向了a.txt
        int ret = dup2(fd1, fd);
        if(ret == -1)
        {
            perror("dup2");
            exit(1);
        }
        printf("current fd = %d\n", ret);
        char * buf = "主要看氣質^_^!!!!!!!!!!!\n";
    
        write(fd, buf, strlen(buf));
        write(fd1, "hello, world!", 13);
    
        close(fd);
        close(fd1);
        return 0;
    }
    
  • 解決gcc編譯過程中c99語法報錯的問題

    alias gcc='gcc -std=gnu99'
    
  • 索引節點inode:保存的其實是實際的數據的一些信息,這些信息稱為“元數據”(也就是對文件屬性的描述)。例如:文件大小,設備標識符,用戶標識符,用戶組標識符,文件模式,擴展屬性,文件讀取或修改的時間戳,鏈接數量,指向存儲內容的磁盤區塊的指針,文件分類等等。(注意數據分成:元數據+數據本身)

  • 注意inode怎樣生成的:每個inode節點的大小,一般是128字節或256字節。inode節點的總數,在格式化時就給定(現代OS可以動態變化),一般每2KB就設置一個inode。一般文件系統中很少有文件小於2KB的,所以預定按照2KB分,一般inode是用不完的。所以inode在文件系統安裝的時候會有一個默認數量,後期會根據實際的需要發生變化。

  • 注意inode號:inode號是唯一的,表示不同的文件。其實在Linux內部的時候,訪問文件都是通過inode號來進行的,所謂文件名僅僅是給用戶容易使用的。當我們打開一個文件的時候,首先,系統找到這個文件名對應的inode號;然後通過inode號,得到inode信息,最後,由inode找到文件數據所在的block,現在可以處理文件數據了。

  • inode與文件的關系:當創建一個文件的時候,就給文件分配了一個inode。一個inode只對應一個實際文件,一個文件也會只有一個inode。inode最大數量就是文件的最大數量。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved