C++服務端面試準備(4)Linux及多線程相關

聲明:本文內容純屬博主本身查找和概括的我的所需的知識點,僅做參考,若有錯誤,博主強烈但願您指出。若是您是某個知識點的原創博主,若有須要,可聯繫本人加上連接。本文內容會根據博主所需進行更新,但願你們多多關照。

文件IO相關知識點

  • 七種文件類型:普通文件(-)、目錄(d)、符號連接(l)、管道(p)、套接字(s)、字符設備(c)、塊設備(b)
  • shell中文件的顏色:白色——普通文件、綠色——可執行文件、紅色——壓縮文件、藍色——目錄、青色——連接文件、黃色——塊設備字符設備管道、灰色——其餘文件
  • PCB:進程控制塊,存放文件描述符表,本質是一個結構體
  • PCB內部成員:進程ID、進程狀態、當前工做目錄、文件描述符表、用戶ID組ID、信號相關的信息等
  • 一個進程有一個文件描述符表,大小爲1024字節,前三個被佔用,分別是STDIN_FILENO、STDOUT_FILENO和STDERR_FILENO
  • 文件描述符做用:尋找磁盤文件
  • 查看磁盤命令:df -h

併發與並行

  • 併發:

       是指同一個時間段內多個任務同時都在執行,而且都沒有執行結束。併發任務強調在一個時間段內同時執行,而一個時間段由多個單位時間累積而成,因此說併發的多個任務在單位時間內不必定同時在執行 。linux

  • 並行:

       是說在單位時間內多個任務同時在執行。c++

       在多線程編程實踐中,線程的個數每每多於CPU的個數,因此通常都稱多線程併發編程而不是多線程並行編程。shell

進程相關知識點

  • 查看進程:ps auxps ajx能顯示父進程,查看內存佔用:free -h,查看當前cpu:top
  • MMU:虛擬內存映射單元,單位爲4k,虛擬內存經過MMU映射到物理內存
  • 寄存器4字節,1字節8位
  • 進程基本狀態:初始態、就緒態、運行態、掛起態、終止態

       運行態->掛起態:等待使用資源,如等待外設傳輸、人工干預等
       運行態->就緒態:出現有更高優先權進程數據庫

  • 父子進程共享:文件描述符、mmap映射區、全局變量讀時共享、寫時複製
  • 孤兒進程:父進程先於子進程結束,子進程稱爲孤兒進程,init進程變爲它的父進程並接管孤兒進程
  • 殭屍進程:當子進程比父進程先結束,而父進程又沒有回收子進程,子進程的進程描述符仍然保存在系統中,此時子進程將成爲一個殭屍進程

進程間通訊相關知識點

  • 進程間經常使用的4種通訊方式:管道(使用簡單)、信號(開銷小)、共享映射區(無血緣關係可用)、本地套接字(穩定)
  • 管道:

       本質爲一個僞文件,內核使用環形隊列機制,藉助內核緩衝區(4k)實現,數據一旦讀走,管道中不在存在編程

  • 共享映射區:

       mmap,一種內存映射文件的方法,將一個文件或者其它對象映射進內存,無血緣關係的進程間可以使用共享映射區進行通訊,在要求高性能的應用中比較經常使用。mmap映射內存必須是頁面大小的整數倍,面向流的設備不能進行mmap,mmap的實現和硬件有關windows

  • 信號:

       簡單但不能攜帶大量信息,知足條件才發送,至關於中斷,有很強的延時性,全部信號都由內核(PCB)發送和處理
       信號4要素:編號、名稱、事件、默認處理動做
       信號處理方式:執行默認動做(終止進程、忽略信號、終止進程並生成CORE文件、暫停進程、繼續運行進程)、忽略、捕捉安全

  • 查看信號列表:kill -l

建立會話要注意什麼

  • 建立會話的進程不能是進程組組長,不然出錯返回
  • 該進程變成新會話的首進程和一個新進程組組長
  • 須要有root權限(Ubuntu不須要)
  • 新會話丟棄原有的控制終端,該會話沒有控制終端
  • 建立會話時,先調用fork,父進程終止,子進程再調用setsid()

建立守護進程

  1. 在父進程中執行fork並exit退出;
  2. 在子進程中調用setsid函數建立新的會話;
  3. 在子進程中調用chdir函數,讓根目錄 "/" 成爲子進程的工做目錄;
  4. 在子進程中調用umask函數,設置進程的umask爲0;
  5. 在子進程中關閉任何不須要的文件描述符(close(fd))或者重定向"/dev/null"

線程相關知識點

  • 查看全部線程:top -Hps -Lf 進程號,查看該進程的線程
  • 線程定義:LWP,輕量級進程,有獨立的PCB和共享地址空間
  • 爲何會出現線程安全:當一個線程在操做共享資源時,未執行完畢的狀況下,其餘線程參與進來,致使共享資源出現安全問題。
  • 保護共享數據區方法:互斥量、讀寫鎖、條件變量、信號量(C語言)、原子操做(一般用來保護單個變量)、windows臨界區
  • 死鎖:對一個鎖反覆Lock,或者2個線程各自鎖上一把鎖後請求對方的鎖
  • 死鎖解決方法:按一樣的順序上鎖,c++11用std::lock(mutex1, mutex2, ...)

條件變量的使用

  1. 建立一個互斥量,用lock_guard或者unique_lock封裝互斥量
  2. 建立條件變量,用wait成員函數等待條件知足
  3. 另外一線程使用notify_one或notify_all後激活wait
  4. wait拿鎖後判斷第二個參數是否爲true,若是true則執行下面的代碼,若是false則表示條件不知足,繼續等待下次的激活

sleep()和wait()的區別

  • sleep()包含<windows.h>頭文件,wait()包含<wait.h>文件
  • sleep()佔着CPU休眠,不會解鎖,wait()釋放鎖並騰出CPU資源等待喚醒並拿鎖

進程與線程的區別

  1. 進程是分配資源的基本單位;線程是系統調度和分派的基本單位。
  2. 一個進程能夠擁有多個線程,屬於同一進程的線程,具備相同的地址空間,堆是共享的,棧是私有的。
  3. 進程開銷大,線程開銷小
  4. 線程間通訊相對方便,進程間通訊相對複雜
  5. 多進程更健壯,多線程容易出錯
  6. 進程是一個資源的容器,爲進程裏的全部線程提供共享資源,是對程序的一種靜態描述,線程是計算機最小的調度和運行單位,是對程序的一種動態描述

爲何使用多線程

  1. 避免阻塞

       單個線程中的程序,是順序執行的。若是前面的操做發生了阻塞,那麼就會影響到後面的操做。這時候能夠採用多線程多線程

  1. 避免CPU空轉

       有時候處理一條請求,會涉及到數據庫訪問、磁盤IO等操做,這些操做的速度比CPU慢不少,而在等待這些響應的時候,CPU卻不能去處理新的請求,沒有充分利用資源,這時多線程就發揮做用了併發

  1. 提高性能

       在知足條件的前提下,多線程確實能提高性能:
       第1,任務具備併發性,子任務之間不能有前後順序的依賴,必須是容許並行的,另外,還不能有資源競爭
       第2,只有在CPU是性能瓶頸的狀況下,多線程才能實現提高性能的目的。
       第3,就是須要有多核CPU才行,若是上述條件都知足,有一個經驗公式能夠計算性能提高的比例,叫阿姆達爾定律:
       速度提高比例 = 1/[(1-P)+(P/N)]
       其中P是可並行任務的比例,N是CPU核心數量app

gdb基礎調試

編譯:gcc加要加-g,-g保留函數名和變量名
啓動:gdb 可執行文件
傳參:set args 參數1 參數2 ...

操做 命令
查看第n行的上下程序 l n
設置查看n行上下程序 set listsize n
查看其餘文件程序 l 文件名 : n 或 函數名
在n行打斷點 b n
查看斷點 i b
刪除斷點 d n,n爲斷點編號
設置無效或有效斷點 dis / enb n,n爲斷點編號
條件斷點 b n if 變量==值
運行 r 或 start,r直接到斷點,start進入程序第一行
單步執行 n
執行到下一個斷點 c
查看變量信息 p 變量名
查看變量類型 ptype 變量名
一直顯示變量信息 display 變量名
取消顯示變量 先i display 查看變量編號n,而後undisplay n
進入函數 s
離開函數 finish
跳出循環 until,須要刪除斷點
離開gdb q

gdb也能夠直接調試core文件查看錯誤:

1.當一個程序出現段錯誤時,會出現如下提示:
       Segmentation fault (core dumped)
       core 指該程序運行時,進程空間的內存分佈
       dumped 表示內核已經把core拋出
       一般,出現段錯誤提示時程序運行目錄下應該自動生成一個core文件用來存儲內核拋出的core,可是,因爲linux環境通常默認設置core文件限制爲0,因此通常狀況下沒法生成core文件。

2.查看core文件大小限制:ulimit -c

3.將其修改成無限制:ulimit -c unlimited

4.運行命令:gdb 執行文件名 core

5.gdb輸入  where

gdb多線程調試

命令行查看線程信息:

  • 查看當前運行的進程:ps aux|grep 執行文件名
  • 查看當前運行的輕量級進程:ps -aL|grep 執行文件名
  • 查看主線程和新線程的關係:pstree -p 主線程id

線程棧結構的查看:

  • 獲取線程ID
  • 經過命令查看棧結構:ps stack 線程ID

利用gdb查看線程信息:

  • 將運行着的進程附加到gdb調試器當中,查看是否建立了新線程:gdb attach 主線程ID

進入gdb調試:

  • info inferiors:查看當前進程
  • info threads:查看當前線程
  • bt:查看當前線程棧結構
  • thread n/ID:切換線程(n表明第幾個線程)
  • break 行號/函數名:設置當前線程斷點
  • break file.c:100 thread all:在file.c文件第100行處爲全部通過這裏的線程設置斷點。
  • set scheduler-locking off/on/step
    在使用step或者continue命令調試當前被調試線程的時候:
    off:不鎖定任何線程,也就是全部線程都執行,這是默認值。
    on:只有當前被調試程序會執行。
    step:在單步的時候,除了next過一個函數的狀況之外(熟悉狀況的人可能知道,這實際上是一個設置斷點而後continue的行爲),只有當前線程會執行。
  • thread apply ID1 ID2 command:讓一個或者多個線程執行GDB命令command
  • thread apply all command:讓全部被調試線程執行GDB命令command

makefile基礎

  • 向下檢索內容,根據時間判斷哪一個文件須要更新
  • 目標:依賴
           命令
  • 查找目錄下指定文件類型:變量 = $(wildcard 文件路徑)
  • 匹配替換:變量 = $(patsubst 原名稱, 替換後的名稱, 源文件)
  • notdir:去除文件名的目錄函數
  • basename:取文件名函數
  • $@:規則中的目標 $<:規則中的第一個依賴 $^:規則中全部依賴
  • /:換行
  • 自定義命令:
    名稱:
           命令
  • 聲明僞目標:
    .PHONY:名稱

隨便說一下Linux和Windows的區別

  1. 兼容性:windows向後兼容,linux內核升級可能就不兼容,軟件方面windows佔優
  2. 進程:單個進程windows不能執行,linux能夠
  3. 性能:windows圖形界面,不少渲染,性能下降,linux少,用命令行工做,性能好
  4. 文件系統:linux有多種文件系統,對文件和設備的管理佔優,windows較差
  5. 中斷優先級:windows有32級,linux彷佛只有5級,異常分爲故障(fault)、陷阱(trap)和停止(abort)
  6. 軟件啓動:windows用註冊表,linux用配置文件,靈活性高
相關文章
相關標籤/搜索