你需要知道的linux基礎編程(四)

  1. gdb調試
    GDB(GNU Debugger)是GCC的調試工具。功能如下:

     1. 啓動你的程序,可以按照你的自定義的要求隨心所欲的運行程序
     2. 可讓被調試的程序在你所指定的調試的斷點出停住。(斷點可以是條件表達式)
     3. 當程序被停住的時候,可以檢查此時你的程序中所發生的事
     4. 動態的改變你程序的運行環境
    
    1. 生成可調式的gdb文件的時候在gcc編譯的時候要加參數 -g
    2. 啓動gdb
      1. start 只執行一步
      2. n(next)----執行下一步
      3. s(step)----可以進入到函數體的內部
      4. c (continue)----直接停在斷點的位置
    3. 查看代碼
      1. l(list)
      2. l + 行號
      3. l + 文件名 + : + 函數名
      4. l+ 文件名 + : + 行號
    4. 設置斷點
      1. 設置當前文件斷點
        1. break + 行號(break可以簡寫爲b)
        2. break + 函數名
      2. 設置指定文件斷點
        1. break + 文件名 + 行號
        2. break + 文件名 + 函數名
      3. 設置條件斷點
        b + 行號 + 條件(if I == 15)
      4. 刪除斷點
        del + 斷點對應的編號
    5. 查看設置的斷點
      info + break(簡寫:I b)
    6. 開始執行gdb調試(start)
      1. 執行一步操作
      2. n(next)----執行下一步
      3. s(step)----可以進入到函數體的內部
      4. c(continue)----直接停在斷點的位置
    7. 單步調試
      1. 進入函數體內部:s
      2. 從函數的內部跳出:finish(前提是要去掉函數體內的斷點)
      3. 退出當前循環:u
    8. 查看當前變量的值
      p(print) + 變量名
    9. 查看變量的類型
      ptype + 變量名
    10. 設置變量的值
      set var + 變量名 + ‘=’ + 值(避免等待)
    11. 設置追蹤變量
      1. display + 變量名
      2. info + display(顯示追蹤變量)
      3. undislay + 追蹤變量的編號
    12. 退出gdb調試
      quit
  2. makefile的編寫

    1. make命令執行的時候,需要一個makefile文件,以告訴make命令需要怎樣的去編譯和鏈接程序。
      makefile來告訴make命令如何編譯和鏈接這幾個文件,規則是:

      1. 如果這個工程沒有編譯過,那麼所有的c文件都要進行編譯和鏈接
      2. 如果這個工程的某幾個C文件被修改,那麼我們只編譯被修改的C文件,並鏈接目標程序
      3. 如果這個工程的頭文件被改變了,那麼我們只需要編譯被引用了這幾個頭文件的C文件,並鏈接目標程序
      4. 只要makefile文件寫的好,所有的這一切,只用一個make命令就可以完成,make命令會自動只能的根據當前文件修改的情況來確定那些文件需要重新編譯,從而自己編譯所需要的文件和鏈接目標程序
    2. makefile的命名
      MakeFile 或者 makefile

    3. makefile的規則(makefile中最核心的內容)

       1. Target…:prerequisites…
       		Command
       		…
       		…
       2. target也就是一個目標文件,可以是object File,也可以是執行文件,還可以是一個標籤(Label)
       prerequisites就是,要生成那個target所需要的文件或是目標
       command就是make需要執行的命令。(任意的Shell命令)
       3. 這是一個文件的依賴關係,target這一個或多個的目標文件依賴於prerequisittes中的文件,其生成規則定義在command中。說白一點,prerequisites中如果有一個以上的文件比target文件要新的話,command所定義的命令就會被執行。
       4. 在定義好依賴關係以後,後續的那一行定義瞭如何生成目標文件的操作系統命令,一定要以一個Tab鍵作爲開頭。make並不管命令是如何工作的,他只管執行所定義的命令。make會比較targets文件和prerequisites文件的修改日期,如果prerequisites文件的日期要比targets文件的日期要新,或者target不存在的話,那麼make就會執行後面的命令
      
    4. 一個例子
      1) test目錄:
      在這裏插入圖片描述
      2) makefile文件的內容:
      在這裏插入圖片描述
      3) 在test目錄下輸入make命令就會執行command命令,並且產生可執行文件main
      4) 輸入命令:./main
      在這裏插入圖片描述

    5. make的工作方式
      在默認的方式下,也就是我們只輸入make命令,執行步驟爲:

      1. make會在當前目錄下找名字叫"Makefile"或"makefile"的文件
      2. 如果找到,他會找文件中的第一個目標文件(target),並把這個文件作爲最終的目標文件
      3. 如果目標文件不存在,或是目標文件所依賴的.o文件的修改時間要比目標文件新,那麼他就會執行後面所定義的命令來生成目標文件
      4. 如果目標文件所以來的.o文件也存在,那麼make會在當前文件中找目標文件爲.o文件的依賴性,如果找到則在根據那一個規則生成.o文件(這像是一個堆棧過程)
        在這裏插入圖片描述
      5. C文件和H文件是存在的,於是make會生成.o文件,然後再用.o文件生成make的終極任務,也就是目標文件了
    6. makefile中使用變量

      1. 普通變量
        1. 當makefile文件變的複雜的時候,爲了makefile的易維護,在makefile中我們可以使用變量,makefile的變量也就是一個字符串
          在這裏插入圖片描述
        2. 由makefile維護的一些變量,通常格式都是大寫。
          1. 有些變量有默認值(CC:默認值爲cc cc==gcc)
          2. 有些變量沒有默認值
            1. CPPFLAGS:預處理需要的選項 如:-I
            2. CFLAGS:編譯的時候使用的參數 -wall -g -c
            3. LDFLAGS:鏈接庫使用的選項 -L -l
        3. 用戶也可以修改這些變量的值(CC = gcc)
      2. 自動變量
        1. 變量:
          a) $@ -->> 規則中的目標
          b) $< -->> 規則中的第一個依賴條件
          c) $^ -->> 規則中的所有的依賴文件
        2. 模式規則:
          a) 在規則的目標定義中使用 %
          b) 在規則的依賴條件中使用 %
          在這裏插入圖片描述
    7. make自動的推導
      GNU的make很強大,他可以自動推導文件及文件依賴關係後面的命令,只要看到一個.o文件,他就會把.c文件添加到依賴關係中,並且後面的也會推導出來
      在這裏插入圖片描述

    8. makefile裏面的內容:
      makefile裏面主要包含了五個東西:顯示規則、隱晦規則、變量定義、文件指示和註釋

      1. 顯示規則:顯示規則說明了,如何生成一個或多個目標文件。這是由makefile的書寫者明顯指出,要生成的文件,文件的依賴,生成的命令
      2. 隱晦規則:由於我們的make有自動推導功能,所以隱晦規則可以讓我們比較粗糙的書寫makefile,這是由make所支持的
      3. 變量的定義:在makefile中我們要定義一系列的變量,變量一般都是字符串,當makefile被執行的時候,其中的變量就會被擴展到相應的引用位置上
      4. 文件指示:三部分:
        1. 一個makefile中引用另一個makefile(像C語言中的include)
        2. 根據某些情況指定makefile文件中有效部分(像C語言中預編譯#if一樣)
        3. 定義一個多行命令
      5. 註釋:makefile中只有行註釋,其註釋是“#”字符,如果要使用“#”字符,要進行反斜槓轉義,如:“/#”
        在makefile中的命令,必須要以tab鍵開始
    9. makefile的兩個函數
      在makefile中每個函數都有返回值

      1. 獲取指定目錄中.c文件
        src = $(wildcard ./.c)
        函數名爲wildcard
        目錄爲./
        .c(當前目錄下的所有.c文件)
        $爲取值對返回的值進行獲取
      2. 將.c文件替換成.o文件
        obj=$(patsubst ./%.c, ./%.o, $(src))
        函數名爲patsubst
        ./%.c爲c文件
        ./%.o爲o文件
        $(src)裏面存儲的.c文件
        在這裏插入圖片描述
    10. 刪除*.o文件和目標文件(清除中間的臨時文件)(在終端輸入命令:make clean就會執行makefile文件中的rm $(obj) $(target) -f)
      在這裏插入圖片描述
      參數-f的作用:是強制執行前面的命令

    11. 僞目標

      1. 原因
        命令make clean在當前的目錄下沒有生成一個文件,因此clean爲僞目標,如果在當前的文件下創建一個clean文件,在執行make clean命令的時候就會提示“‘clean’ is up to date”,就不會執行"rm $(obj) $(target) -f"這條命令
      2. 解決辦法:
        在clean前面聲明,clean爲僞目標
        在這裏插入圖片描述
  3. 系統的Io函數
    查看文件的格式:file + 文件名稱

    1. C庫IO函數工作流程
      在這裏插入圖片描述

    2. pcb和文件描述符
      在這裏插入圖片描述

    3. 虛擬地址空間
      在這裏插入圖片描述

    4. cpu爲什麼要使用虛擬地址空間與物理地址空間映射?解決了什麼樣的問題?

      1. 方便編譯器和操作系統安排程序的地址分佈。
        程序可以使用一系列相鄰的虛擬地址來訪問物理內存中不相鄰的大內存緩衝區
      2. 方便進程之間的隔離
        不同的進程使用的虛擬地址彼此隔離,一個進程中的代碼無法更改正在由另一個進程使用的物理內存
      3. 方便操作系統使用內存
        程序可以使用一些列的虛擬地址來訪問大於可用物理內存的內存緩衝區。當物理內存的供應量變小的時候,內存管理器會將物理內存頁(通常大小爲4KB)保存到磁盤文件中
    5. 庫函數與系統函數的關係
      在這裏插入圖片描述
      f. 函數(open、read、write、lseek、close)

       查man文檔(man 2 + 函數名稱)
       	errno:
       		1) 是一個全局變量(任何標準C庫函數都能對其進行修改(Linux系統函數更可以))
       		2) 錯誤信息定義的位置:
       			a) 第1-34個錯誤定義:
       			/usr/include/asm-gengric/errno-base.h
       			b) 地35-133個錯誤定義:
       			/usr/include/asm-generic/errno.h
       		3) 是記錄系統的最後一次錯誤代碼,代碼是一個int型的值
       			a) 每個errno值對應着以字符串表示的錯誤類型
       			b) 當調用“某些”函數出錯時,該函數會重新設置errno的值
       		4) perror
       			a) 頭文件:stdio.h
       			b) 函數定義:void perror(const char * s)
       			c) 函數說明:
       				i) 用來將上一個函數發生錯誤的原因輸出到標準設備(stderr)
       				ii) 參數s所指的字符串會先打印出,後面在加上錯誤原因字符串
       				iii) 此錯誤原因依照全局變量errno的值來決定要輸出的字符串
       	1. open
       		1) 頭文件:
       			a) #include<sys/types.h>
       			b) #include<sys/stat.h>
       			c) #include<fcntl.h>
       		2) 函數定義
       			a) int open(const char * pathname,int flags);
       			b) int open(const char * pathname,int flags,mode_t mode)
       		3) 函數說明(用來打開一個存在或者打開一個不存在的文件)
       		4) 參數說明:
       			a) pathname:打開文件的路徑(絕對路徑或者是相對路徑)
       			b) flags:文件的打開方式
       				i) the argument flags must include one of the following access modes:O_RDONLY,O_WRONLY,or O_RDRW.This request opening the file read-only,write-only,or read/write, respectively
       				ii) in addition,zero or more file creation flags and file status flags can be bitwise-or'd in flags. The file creation flags are O_CLOEXEC,O_CREAT,O_DIRECTORY,O_EXCL,O_NOCTTY,O_NOFOLLOW,O_TEPFILE, and O_TRUNC. The file status flags are all of the remaining flags listed below. The distinction between these two groups id flags is that the file status flags can be retricved and (in some cases) modified.
       			c) mode:指文件創建後的權限
       				注意:文件的實際權限 = 創建文件是給定的權限 & 本地掩碼取反
       				查看掩碼umask
       				修改掩碼umask + 三位的八進制數
       		5) 函數返回值:
       			open() return the new file descriptor, or -1 if an error occurred (in which case,errno is set appropriately).
       	2. read
       		1) 頭文件:
       			a) #include<unistd.h>
       		2) 函數定義
       			a) ssize_t read(int fd,void *buf,size_t count)
       				i) size_t是無符號的整數
       				ii) ssize_t是有符號的整數
       		3) 函數說明
       			a) read() attempts to read up to count bytes from file descriptor fd into the buffer starting at buf
       		4) 參數說明
       			a) fd:文件描述符
       			b) buf:緩衝區
       			c) count:緩衝區的大小
       		5) 函數返回值
       			a) on success, the number of bytes read is returned (zero indicates end of file), and the file position is advanced by this number. It is not an error if this number is smaller than number of bytes requested; this may happen for example because fewer bytes are actually available right now (maybe because we were close to end-of-file, or because we are reading from a pipe, or from a terminal), or because read() was interrupted by a signal
       			b) on error, -1 is returned, and errno is set appropriately. In this case, it is left unspecified whether the file position (if any) changes
       	3. write
       		1) 頭文件:
       			a) #include<unistd.h>
       		2) 函數定義:
       			a) Ssize_t write(int fd, const void * buf, size_t count)
       				i) Size_t是無符號的整數
       				ii) Ssize_t是有符號的整數
       		3) 函數說明:
       			a) write() writes up to count bytes from the buffer pointed buf to the file referred to by the file descriptor fd
       		4) 參數說明:
       			a) fd:文件描述符
       			b) buf:緩衝區
       			c) count:寫的位置
       		5) 函數返回值:
       			a) on success, the number of bytes written is returned (zero indicates nothing was written). It is not an error if this number is smaller than the number of bytes requested; this may happen for example because the disk device was filled.
       			b) on error, -1 is returned,and errno is set appropriately
       	4. lseek(獲取文件大小、移動文件指針、文件拓展)
       		1) 頭文件:
       			a) #include<sys/types.h>
       			b) #include<unistd.h>
       		2) 函數定義:
       			a) off_t lseek(int fd,off_t offset,int whence)
       		3) 函數說明:以指定的位置打開文件
       		4) 參數說明:
       			a) fd:文件描述符
       			b) offset:文件偏移量
       			c) whence:
       				i) SEEK_SET(the offset is set to offset bytes)
       				ii) SEEK_CUR(the offset is set to its current location plus bytes)
       				iii) SEEK_END(the offset is set to the size of the file plus offset byte)
       		5) 函數返回值:
       			a) upon successful completion,lseek() returns the resulting offset location as measured in bytes from the beginning of the file.
       			b)  on error, the value (off_t) -1 is returned and errno is set to indicate the error
       	5. close
       		1) 頭文件:
       			a) #include<unistd.h>
       		2) 函數定義
       			a) int close(int fd);
       		3) 函數說明:關閉一個已經打開的文件
       		4) 參數說明:
       			a) fd:文件描述符
       		5) 函數返回值:
       			close() returns zero on success. On error, -1 is returned, and errno is set appropriately
       		6) 錯誤類型:
       			a) EBADF: fd isn't a valid open file descriptor
       			b) EINTR: The close() call was interrupted by a signal
       			c) EIO:An I/O error occurred
      

下面的是筆者的微信公衆號,歡迎關注,會持續更新c++、python、tensorflow、機器學習、深度學習、計算機視覺等系列文章,公衆號中內含300+本pdf電子書籍,肯定有你需要的一本,關注公衆號即可領取哦。
在這裏插入圖片描述
如果你對JAVA方面感興趣,可以關注下面JAVAERS公衆號,陪你一起學習,一起成長,一起分享JAVA路上的詩和遠方。在公衆號裏面都是JAVA這個世界的朋友,公衆號每天會有技術類文章,面經乾貨,也有進階架構的電子書籍,如Spring實戰、SpringBoot實戰、高性能MySQL、深入理解JVM、RabbitMQ實戰、Redis設計與實現等等一些高質量書籍,關注公衆號即可領取哦。
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章