Linux 程序 任務和執行緒

2021-06-10 13:11:53 字數 4240 閱讀 5736

程序、任務和執行緒

程序在os中是乙個非常關鍵的抽象概念。

在os中虛擬cpu稱為執行執行緒,簡稱為執行緒。

用於建立和管理多執行執行緒的實用工具通常包含在乙個pthread庫。因為該庫中介面是按照posix標準定義的,所以以p開頭。

在unix os中,單執行緒程序和多執行緒程序模型如下:

linux中,單執行緒任務和多執行緒任務組模型如下:

在linux os中,用「任務」替代「程序」,而沒有「程序」這個物件。

用資料結構task_struct來描述任務,任務就相當於unix os中的程序。 每乙個任務都有任務位址空間(相當於unix os中的程序位址空間),但乙個任務中只有乙個執行緒。通過「任務組」這個概念來實現多執行緒任務(相當於unix中的多執行緒程序)。

可以這樣簡單地說:「linux的任務是unix單執行緒程序的對等體」。

用於描述任務的資料結構task_struct,是乙個資訊量非常大的資料結構。但是並不是每乙個執行緒都會有完整的task_struct成員,而只是保留了需要的成員變數值。在多執行緒的任務組中,每個執行緒都有乙個task_struct資料結構來描述執行緒所在的任務。但是所有的執行緒都共享所在任務組的資源和相關資訊,所以這些副本是一種浪費。實際上,並不是這麼糟糕,大多數任務的成員變數是一些單獨的物件,共享這些物件的執行緒,僅僅儲存了對它的引用。

在linux作業系統中,定義了乙個指向當前任務的指標current

在單處理器中,任何時刻只有乙個任務在執行,current指標指向的任務在執行,current是乙個全域性變數。

在多處理器中,在同一時刻可以有多個任務在執行,那麼在os中可以看到的每個cpu上(也就是「執行執行緒」)有乙個current指標,並且都是區域性變數。

由於current使用地過於頻繁,os都把current申明為暫存器變數。在ia64平台下,通用暫存器r13用來儲存current指標。

/* * in kernel mode, thread pointer (r13) is used to point to the current task

* structure.

*/ #define _ia64_reg_tp 1037 /* r13 */

#define current ((struct task_struct *) ia64_getreg(_ia64_reg_tp))

建立任務

在linux os中建立任務(也就是建立程序和執行緒,只不過在linux中沒有程序的概念了,用任務替換了程序的概念,並且任務都是單執行緒的,多執行緒的任務稱為任務組)根據不同的體系結構不同。我們在此之討論在ia64結構下的實現辦法。

在linux os中沒有提供用於建立原始執行緒的函式,因為除了系統啟動的初始執行緒外(即pid為0的執行緒),任何乙個執行緒都是從原有的執行緒上覆制過來的而產生的。

通過copy_thread函式建立新的執行緒。

int copy_thread (int nr, unsigned long clone_flags,

unsigned long user_stack_base, unsigned long user_stack_size,

struct task_struct *p, struct pt_regs *regs)

這個函式在linux中封裝成copy_process函式(用於建立任務),再一次被封裝成函式do_fork(建立乙個任務)和函式fork_idle(建立空閒任務或者說是空閒程序、空閒執行緒)

,函式do_fork再一次被封裝成系統呼叫sys_fork。

核心建立新的任務步驟:

2、初始化任務結構(task_struct),但還沒有初始化thread_struct。

3、初始化thread_struct

4、完成初始化task_struct中剩餘的與平台無關的部分

5、將新建立的任務新增到執行佇列中,這就可以執行了

task_struct分成兩個部分:平台無關的部分和平台特定部分(執行緒結構)。

在建立任務過程中涉及到幾個非常重要的資料結構:pt_regs、switch_stack、thread_struct等

pt_regs結構:

這個結構封裝了需要在核心入口中儲存的最少的狀態資訊。比如說每一次的系統呼叫、中斷、陷阱、故障時,pt_regs結構中儲存了最少的狀態資訊。該結構中主要儲存了必要的scratch型別的暫存器。(在現代ia64架構中還有3類暫存器:scratch暫存器、保持暫存器、專用暫存器)。在每一次的系統呼叫、中斷、陷阱、故障發生時,依次會發生下列事件:

1、在核心堆疊上為pt_regs結構分配記憶體

2、在pt_regs結構中儲存scratch暫存器

3、呼叫了適當的核心處理器(執行系統呼叫內部處理、中斷處理程式等)

4、從pt_regs中恢復scratch暫存器

5、從核心堆疊中釋放pt_regs占用的記憶體

應該保持pt_regs盡可能的小,可以提高效能。

在ia64平台的linux中pt_regs定義如下:

struct pt_regs ;

switch_stack結構:

該結構用在核心將執行乙個執行緒切換到另乙個執行緒之時,該結構主要儲存了保持暫存器。pt_regs和switch_stack結合起來,一起封裝了每個執行緒正確執行所需的最低限度的機器狀態。這種機器狀態稱為高度管理狀態(eagerly managed state),與鬆散管理狀態(lazily managed state)相對。

簡單地說switch_stack儲存了任務切換的上下文,主要儲存了保持暫存器。

在ia64架構的linux中,switch_stack定義如下:

struct switch_stack ;

thread_struct結構:

該結構封裝了鬆散管理狀態,主要封裝了核心堆疊指標ksp,ksp指向swicth_stack。鬆散管理狀態,並不是每次上下文切換時都要切換鬆散管理狀態,往往只在確實需要新的狀態時才切換鬆散管理狀態。切換鬆散管理狀態比切換高度管理狀態慢很多,所以盡量不切換鬆散管理狀態,以提高效能。

struct thread_struct ;

在任務建立後,會分配一大塊記憶體給task_struct結構來維護。這塊記憶體具體使用如下圖:

通過以上語句定義ia64_stk_offset,決定分配記憶體的大小。就是說,如果系統配置每個頁面的大小為4kb的情況下,那麼ia64_stk_offset就是8*4kb=32kb;

如果page_size=8kb,那麼ia64_stk_offset就是4*8kb=32kb;

如果page_size=16kb,那麼ia64_stk_offset就是2*16kb=32kb;

如果page_size=64kb,那麼ia64_stk_offset就是1*64kb=64kb;

在上圖中還有乙個變數ia64_rbs_base,該變數用來描述什麼?看linux是如何實現的就知道了,用中文描述,我還真不知道。

#define ia64_rbs_offset ((ia64_task_size + ia64_thread_info_size + 31) & ~31)

define(ia64_task_size, sizeof (struct task_struct));

define(ia64_thread_info_size, sizeof (struct thread_info));

Linux 程序 任務和執行緒

程序 任務和執行緒 程序在os中是乙個非常關鍵的抽象概念。在os中虛擬cpu稱為執行執行緒,簡稱為執行緒。用於建立和管理多執行執行緒的實用工具通常包含在乙個pthread庫。因為該庫中介面是按照posix標準定義的,所以以p開頭。在unix os中,單執行緒程序和多執行緒程序模型如下 在linux中...

任務 程序 執行緒

認識多工 多程序 單執行緒 多執行緒 現在的作業系統都是多工作業系統,每個執行的任務就是作業系統所做的一件事情,比如你在聽歌的同時還在用msn和好友聊天。聽歌和聊天就是兩個任務,這個兩個任務是 同時 進行的。乙個任務一般對應乙個程序,也可能包含好幾個程序。比如執行的msn就對應乙個msn的程序,如果...

linux程序和執行緒

這兩天一直在看linxu程序和執行緒的東西,總是效率比較低,這麼一點基礎的東西還看了這麼久。該自我反省一下。首先來看看程序。程序分為三個部分,程序控制塊,程式段和資料段。程序是乙個有生命的實體,程式是乙個沒有生命的實體。只有cpu賦予程式生命的時候,程式才成為乙個活動的實體,我們稱之為 程序 每乙個...