Ⅰ linux多線程情況下,線程多長時間進行一次切換
linux下線程分為用戶級線程和內核級線程,在內核來看,線程和進程是一樣的,本質版上沒有權區別
內核提供的是創建進程的介面do_fork()。內核提供了兩個系統調用clone()和fork(),最終都用不同的參數調用do_fork()核內API。當然,要想實現線程,沒有核心對多進程(其實是輕量級進程)共享數據段的支持是不行的,因此,do_fork()提供了很多參數,包括CLONE_VM(共享內存空間)、CLONE_FS(共享文件系統信息)、 CLONE_FILES(共享文件描述符表)、CLONE_SIGHAND(共享信號句柄表)和CLONE_PID(共享進程ID,僅對核內進程,即0號進程有效)。當使用fork系統調用時,內核調用do_fork()不使用任何共享屬性,進程擁有獨立的運行環境,而使用 pthread_create()來創建線程時,則最終設置了所有這些屬性來調用__clone(),而這些參數又全部傳給核內的do_fork(),從而創建的「進程」擁有共享的運行環境,只有棧是獨立的,由__clone()傳入。
具體可以參考<<深入理解Linux內核>>第三版,講的非常詳細
Ⅱ 如何查看linux線程 運行在哪個cpu核上
使用top命令,具體用法是 top -H,加上這個選項,top的每一行就不是顯示一個進程,而是一個線程專。
使用ps命令,具體屬用法是 ps -xH,這樣可以查看所有存在的線程,也可以使用grep作進一步的過濾。
使用ps命令,具體用法是 ps -mq PID,這樣可以看到指定的進程產生的線程數目。
更進一步,其實一些系統監控工具,在本質上也是讀取的系統產生的文件罷了。
Ⅲ Linux 多線程編程(二)2019-08-10
三種專門用於線程同步的機制:POSIX信號量,互斥量和條件變數.
在Linux上信號量API有兩組,一組是System V IPC信號量,即PV操作,另外就是POSIX信號量,POSIX信號量的名字都是以sem_開頭.
phshared參數指定信號量的類型,若其值為0,就表示這個信號量是當前進程的局部信號量,否則該信號量可以在多個進程之間共享.value值指定信號量的初始值,一般與下面的sem_wait函數相對應.
其中比較重要的函數sem_wait函數會以原子操作的方式將信號量的值減一,如果信號量的值為零,則sem_wait將會阻塞,信號量的值可以在sem_init函數中的value初始化;sem_trywait函數是sem_wait的非阻塞版本;sem_post函數將以原子的操作對信號量加一,當信號量的值大於0時,其他正在調用sem_wait等待信號量的線程將被喚醒.
這些函數成功時返回0,失敗則返回-1並設置errno.
生產者消費者模型:
生產者對應一個信號量:sem_t procer;
消費者對應一個信號量:sem_t customer;
sem_init(&procer,2)----生產者擁有資源,可以工作;
sem_init(&customer,0)----消費者沒有資源,阻塞;
在訪問公共資源前對互斥量設置(加鎖),確保同一時間只有一個線程訪問數據,在訪問完成後再釋放(解鎖)互斥量.
互斥鎖的運行方式:串列訪問共享資源;
信號量的運行方式:並行訪問共享資源;
互斥量用pthread_mutex_t數據類型表示,在使用互斥量之前,必須使用pthread_mutex_init函數對它進行初始化,注意,使用完畢後需調用pthread_mutex_destroy.
pthread_mutex_init用於初始化互斥鎖,mutexattr用於指定互斥鎖的屬性,若為NULL,則表示默認屬性。除了用這個函數初始化互斥所外,還可以用如下方式初始化:pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER。
pthread_mutex_destroy用於銷毀互斥鎖,以釋放佔用的內核資源,銷毀一個已經加鎖的互斥鎖將導致不可預期的後果。
pthread_mutex_lock以原子操作給一個互斥鎖加鎖。如果目標互斥鎖已經被加鎖,則pthread_mutex_lock則被阻塞,直到該互斥鎖佔有者把它給解鎖.
pthread_mutex_trylock和pthread_mutex_lock類似,不過它始終立即返回,而不論被操作的互斥鎖是否加鎖,是pthread_mutex_lock的非阻塞版本.當目標互斥鎖未被加鎖時,pthread_mutex_trylock進行加鎖操作;否則將返回EBUSY錯誤碼。注意:這里討論的pthread_mutex_lock和pthread_mutex_trylock是針對普通鎖而言的,對於其他類型的鎖,這兩個加鎖函數會有不同的行為.
pthread_mutex_unlock以原子操作方式給一個互斥鎖進行解鎖操作。如果此時有其他線程正在等待這個互斥鎖,則這些線程中的一個將獲得它.
三個列印機輪流列印:
輸出結果:
如果說互斥鎖是用於同步線程對共享數據的訪問的話,那麼條件變數就是用於在線程之間同步共享數據的值.條件變數提供了一種線程之間通信的機制:當某個共享數據達到某個值時,喚醒等待這個共享數據的線程.
條件變數會在條件不滿足的情況下阻塞線程.且條件變數和互斥量一起使用,允許線程以無競爭的方式等待特定的條件發生.
其中pthread_cond_broadcast函數以廣播的形式喚醒所有等待目標條件變數的線程,pthread_cond_signal函數用於喚醒一個等待目標條件變數線程.但有時候我們可能需要喚醒一個固定的線程,可以通過間接的方法實現:定義一個能夠唯一標識目標線程的全局變數,在喚醒等待條件變數的線程前先設置該變數為目標線程,然後採用廣播的方式喚醒所有等待的線程,這些線程被喚醒之後都檢查該變數以判斷是否是自己.
採用條件變數+互斥鎖實現生產者消費者模型:
運行結果:
阻塞隊列+生產者消費者
運行結果:
Ⅳ Linux 進程、線程和CPU的關系,cpu親和性
1、物理CPU數:機器主板上實際插入的cpu數量,比如說你的主板上安裝了一塊8核CPU,那麼物理CPU個數就是1個,所以物理CPU個數就是主板上安裝的CPU個數。
2、物理CPU核數:單個物理CPU上面有多個核,物理CPU核數=物理CPU數✖️單個物理CPU的核
3、邏輯CPU核數:一般情況,我們認為一顆CPU可以有多個核,加上intel的超線程技術(HT), 可以在邏輯上再分一倍數量的CPU core出來。邏輯CPU核數=物理CPU數✖️單個物理CPU的核*2
4、超線程技術(Hyper-Threading):就是利用特殊的硬體指令,把兩個邏輯CPU模擬成兩個物理CPU,實現多核多線程。我們常聽到的雙核四線程/四核八線程指的就是支持超線程技術的CPU。
1、並行:兩件(多件)事情在同一時刻一起發生。
2、並發:兩件(多件)事情在同一時刻只能有一個發生,由於CPU快速切換,從而給人的感覺是同時進行。
3、進程和線程
進程是資源分配的最小單位,一個程序有至少一個進程。線程是程序執行的最小單位。一個進程有至少一個線程。
線程之間的通信更方便,同一進程下的線程共享全局變數、靜態變數等數據,而進程之間的通信需要以通信的方式(IPC)進行。多進程程序更健壯,多線程程序只要有一個線程死掉,整個進程也死掉了,而一個進程死掉並不會對另外一個進程造成影響,因為進程有自己獨立的地址空間。
4、單核多線程:單核CPU上運行多線程, 同一時刻只有一個線程在跑,系統進行線程切換,系統給每個線程分配時間片來執行,看起來就像是同時在跑, 但實際上是每個線程跑一點點就換到其它線程繼續跑。
5、多核多線程:每個核上各自運行線程,同一時刻可以有多個線程同時在跑。
1、對於單核:多線程和多進程的多任務是在單cpu交替執行(時間片輪轉調度,優先順序調度等),屬於並發
2、對於多核:同一個時間多個進程運行在不同的CPU核上,或者是同一個時間多個線程能分布在不同的CPU核上(線程數小於內核數),屬於並行。
3、上下文切換:上下文切換指的是內核(操作系統的核心)在CPU上對進程或者線程進行切換。上下文切換過程中的信息被保存在進程式控制制塊(PCB-Process Control Block)中。PCB又被稱作切換幀(SwitchFrame)。上下文切換的信息會一直被保存在CPU的內存中,直到被再次使用。
CPU 親和性(affinity)就是進程要在某個給定的 CPU 上盡量長時間地運行而不被遷移到其他處理器的傾向性。這樣可以減少上下文切換的次數,提高程序運行性能。可分為:自然親和性和硬親和性
1、自然親和性:就是進程要在指定的 CPU 上盡量長時間地運行而不被遷移到其他處理器,Linux 內核進程調度器天生就具有被稱為 軟 CPU 親和性(affinity) 的特性,這意味著進程通常不會在處理器之間頻繁遷移。這種狀態正是我們希望的,因為進程遷移的頻率小就意味著產生的負載小。Linux調度器預設就支持自然CPU親和性(natural CPU affinity): 調度器會試圖保持進程在相同的CPU上運行。
2、硬親和性:簡單來說就是利用linux內核提供給用戶的API,強行將進程或者線程綁定到某一個指定的cpu核運行。Linux硬親和性指定API:taskset .
taskset [options] mask command [arg]...
taskset [options] -p [mask] pid
taskset 命令用於設置或者獲取一直指定的 PID 對於 CPU 核的運行依賴關系。也可以用 taskset 啟動一個命令,直接設置它的 CPU 核的運行依賴關系。
CPU 核依賴關系是指,命令會被在指定的 CPU 核中運行,而不會再其他 CPU 核中運行的一種調度關系。需要說明的是,在正常情況下,為了系統性能的原因,調度器會盡可能的在一個 CPU 核中維持一個進程的執行。強制指定特殊的 CPU 核依賴關系對於特殊的應用是有意義的
CPU 核的定義採用位定義的方式進行,最低位代表 CPU0,然後依次排序。這種位定義可以超過系統實際的 CPU 總數,並不會存在問題。通過命令獲得的這種 CPU 位標記,只會包含系統實際 CPU 的數目。如果設定的位標記少於系統 CPU 的實際數目,那麼命令會產生一個錯誤。當然這種給定的和獲取的位標記採用 16 進制標識。
0x00000001
代表 #0 CPU
0x00000003
代表 #0 和 #1 CPU
0xFFFFFFFF
代表 #0 到 #31 CPU
-p, --pid
對一個現有的進程進行操作,而不是啟動一個新的進程
-c, --cpu-list
使用 CPU 編號替代位標記,這可以是一個列表,列表中可以使用逗號分隔,或者使用 "-" 進行范圍標記,例如:0,5,7,9
-h, --help
列印幫助信息
-V, --version
列印版本信息
如果需要設定,那麼需要擁有 CAP_SYS_NICE 的許可權;如果要獲取設定信息,沒有任何許可權要求。
taskset 命令屬於 util-linux-ng 包,可以使用 yum 直接安裝。
Ⅳ linux中線程pid有何作用
問題: 我的程序在其內部創建並執行了多個線程,我怎樣才能在該程序創建線程後監控其中單個線程?我想要看到帶有它們名稱的單個線程詳細情況(如,CPU/內存使用率)。
線程是現代操作系統上進行並行執行的一個流行的編程方面的抽象概念。當一個程序內有多個線程被叉分出用以執行多個流時,這些線程就會在它們之間共享 特定的資源(如,內存地址空間、打開的文件),以使叉分開銷最小化,並避免大量高成本的IPC(進程間通信)通道。這些功能讓線程在並發執行時成為一個高 效的機制。
在Linux中,程序中創建的線程(也稱為輕量級進程,LWP)會具有和程序的PID相同的「線程組ID」。然後,各個線程會獲得其自身的線程 ID(TID)。對於Linux內核調度器而言,線程不過是恰好共享特定資源的標準的進程而已。經典的命令行工具,如ps或top,都可以用來顯示線程級 別的信息,只是默認情況下它們顯示進程級別的信息。
這里提供了在Linux上顯示某個進程的線程的幾種方式。
方法一:PS
在ps命令中,「-T」選項可以開啟線程查看。下面的命令列出了由進程號為<pid>的進程創建的所有線程。
1.$ ps -T -p <pid>
「SID」欄表示線程ID,而「CMD」欄則顯示了線程名稱。
方法二: Top
top命令可以實時顯示各個線程情況。要在top輸出中開啟線程查看,請調用top命令的「-H」選項,該選項會列出所有Linux線程。在top運行時,你也可以通過按「H」鍵將線程查看模式切換為開或關。
1.$ top -H
要讓top輸出某個特定進程<pid>並檢查該進程內運行的線程狀況:
$ top -H -p <pid>
方法三: Htop
一個對用戶更加友好的方式是,通過htop查看單個進程的線程,它是一個基於ncurses的交互進程查看器。該程序允許你在樹狀視圖中監控單個獨立線程。
要在htop中啟用線程查看,請開啟htop,然後按<F2>來進入htop的設置菜單。選擇「設置」欄下面的「顯示選項」,然後開啟「樹狀視圖」和「顯示自定義線程名」選項。按<F10>退出設置。
現在,你就會看到下面這樣單個進程的線程視圖。
Ⅵ linux 怎樣查看一個進程的線程
方法一:PS
在ps命令中,「-T」選項可以開啟線程查看。下面的命令列出了由進程號為<pid>的進程創建的所有線程。
$ ps -T -p <pid>
「SID」欄表示線程ID,而「CMD」欄則顯示了線程名稱。
方法二: Top
top命令可以實時顯示各個線程情況。要在top輸出中開啟線程查看,請調用top命令的「-H」選項,該選項會列出所有Linux線程。在top運行時,你也可以通過按「H」鍵將線程查看模式切換為開或關。
$ top -H
要讓top輸出某個特定進程<pid>並檢查該進程內運行的線程狀況:
$ top -H -p <pid>
方法三: Htop
一個對用戶更加友好的方式是,通過htop查看單個進程的線程,它是一個基於ncurses的交互進程查看器。該程序允許你在樹狀視圖中監控單個獨立線程。
要在htop中啟用線程查看,請開啟htop,然後按<F2>來進入htop的設置菜單。選擇「設置」欄下面的「顯示選項」,然後開啟「樹狀視圖」和「顯示自定義線程名」選項。按<F10>退出設置。
Ⅶ 求教Linux多個線程 可不可以同時調用一個函數
使用pthread庫執行多線程,這個是Linux下的線程庫 Windows下應該有自己的API,不過這種東西一般還是以Linux為標准。pthread_create()創建一個線程,傳入fun()的函數指針就行了。 然後這個Beep()的需求要進行線程間通信,可以用共享內存的方法,...