1. 程式人生 > >Linux 下程序與執行緒的關係

Linux 下程序與執行緒的關係

一.基礎知識執行緒程序

按照教科書上的定義,程序是資源管理的最小單位,執行緒是程式執行的最小單位。在作業系統設計上,從程序演化出執行緒,最主要的目的就是更好的支援SMP以及減小(程序/執行緒)上下文切換開銷。

無論按照怎樣的分法,一個程序至少需要一個執行緒作為它的指令執行體,程序管理著資源(比如cpu、記憶體、檔案等等),而將執行緒分配到某個cpu上執行。一個程序當然可以擁有多個執行緒,此時,如果程序執行在SMP機器上,它就可以同時使用多個cpu來執行各個執行緒,達到最大程度的並行,以提高效率;同時,即使是在單cpu的機器上,採用多執行緒模型來設計程式,正如當年採用多程序模型代替單程序模型一樣,使設計更簡潔、功能更完備,程式的執行效率也更高,例如採用多個執行緒響應多個輸入,而此時多執行緒模型所實現的功能實際上也可以用多程序模型來實現,而與後者相比,執行緒的上下文切換開銷就比程序要小多了,從語義上來說,同時響應多個輸入這樣的功能,實際上就是共享了除cpu以外的所有資源的。

針對執行緒模型的兩大意義,分別開發出了核心級執行緒和使用者
級執行緒兩種執行緒模型,分類的標準主要是執行緒的排程者在核內還是在核外。前者更利於併發使用多處理器的資源,而後者則更多考慮的是上下文切換開銷。在目前的商用系統中,通常都將兩者結合起來使用,既提供核心執行緒以滿足smp系統的需要,也支援用執行緒庫的方式在使用者態實現另一套執行緒機制,此時一個核心執行緒同時成為多個使用者態執行緒的排程者。正如很多技術一樣,"混合"通常都能帶來更高的效率,但同時也帶來更大的實現難度,出於"簡單"的設計思路,Linux從一開始就沒有實現混合模型的計劃,但它在實現上採用了另一種思路的"混合"。

線上程機制的具體實現上,可以在作業系統核心上實現執行緒,也可以在核外實現,後者顯然要求核內至少實現了程序,而前者則一般要求在核內同時也支援程序。核心級執行緒模型顯然要求前者的支援,而使用者級執行緒模型則不一定基於後者實現。這種差異,正如前所述,是兩種分類方式的標準不同帶來的。

當核內既支援程序也支援執行緒時,就可以實現執行緒-程序的"多對多"模型,即一個程序的某個執行緒由核內排程,而同時它也可以作為使用者級執行緒池的排程者,選擇合適的使用者級執行緒在其空間
中執行。這就是前面提到的"混合"執行緒模型,既可滿足多處理機系統的需要,也可以最大限度的減小排程開銷。絕大多數商業作業系統(如Digital Unix、Solaris、Irix)都採用的這種能夠完全實現POSIX1003.1c標準的執行緒模型。在核外實現的執行緒又可以分為"一對一"、"多對一"兩種模型,前者用一個核心程序(也許是輕量程序)對應一個執行緒,將執行緒排程等同於程序排程,交給核心完成,而後者則完全在核外實現多執行緒,排程也在使用者態完成。後者就是前面提到的單純的使用者級執行緒模型的實現方式,顯然,這種核外的執行緒排程器實際上只需要完成執行緒執行棧的切換,排程開銷非常小,但同時因為核心訊號(無論是同步的還是非同步的)都是以程序為單位的,因而無法定位到執行緒,所以這種實現方式不能用於多處理器系統,而這個需求正變得越來越大,因此,在現實中,純使用者級執行緒的實現,除演算法研究目的以外,幾乎已經消失了。

Linux核心只提供了輕量程序的支援,限制了更高效的執行緒模型的實現,但Linux著重優化了程序的排程開銷,一定程度上也彌補了這一缺陷。目前最流行的執行緒機制LinuxThreads所採用的就是執行緒-程序"一對一"模型,排程交給核心,而在使用者級實現一個包括訊號處理在內的執行緒管理機制。Linux-LinuxThreads的執行機制正是本文的描述重點。

二.Linux 2.4核心中的輕量程序實現

最初的程序定義都包含程式、資源及其執行三部分,其中程式通常指程式碼,資源在作業系統層面上通常包括記憶體資源、IO資源、訊號處理等部分,而程式的執行通常理解為執行上下文,包括對cpu的佔用,後來發展
為執行緒。線上程概念出現以前,為了減小程序切換的開銷,作業系統設計者逐漸修正程序的概念,逐漸允許將程序所佔有的資源從其主體剝離出來,允許某些程序共享一部分資源,例如檔案、訊號,資料記憶體,甚至程式碼,這就發展出輕量程序的概念。Linux核心在2.0.x版本就已經實現了輕量程序,應用程式可以通過一個統一的clone()系統呼叫介面,用不同的引數指定建立輕量程序還是普通程序。在核心中,clone()呼叫經過引數傳遞和解釋後會呼叫do_fork(),這個核內函式同時也是fork()、vfork()系統呼叫的最終實現:


<linux-2.4.20/kernel/fork.c>;
int do_fork(unsigned long clone_flags, unsigned long stack_start, 
struct pt_regs *regs, unsigned long stack_size)

其中的clone_flags取自以下巨集的"或"值:


<linux-2.4.20/include/linux/sched.h>;
#define CSIGNAL                        0x000000ff        /* signal mask to be sent at exit */
#define CLONE_VM                0x00000100        /* set if VM shared between processes */
#define CLONE_FS        0x00000200        /* set if fs info shared between processes */
#define CLONE_FILES     0x00000400        /* set if open files shared between processes */
#define CLONE_SIGHAND        0x00000800        /* set if signal handlers and blocked signals shared */
#define CLONE_PID                0x00001000        /* set if pid shared */
#define CLONE_PTRACE        0x00002000        /* set if we want to let tracing continue on the child too */
#define CLONE_VFORK        0x00004000        /* set if the parent wants the child to wake it up on mm_release */
#define CLONE_PARENT        0x00008000        /* set if we want to have the same parent as the cloner */
#define CLONE_THREAD        0x00010000        /* Same thread group? */
#define CLONE_NEWNS        0x00020000        /* New namespace group? */
#define CLONE_SIGNAL         (CLONE_SIGHAND | CLONE_THREAD)

在do_fork()中,不同的clone_flags將導致不同的行為,對於LinuxThreads,它使用(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND)引數來呼叫clone()建立"執行緒",表示共享記憶體、共享檔案系統訪問計數、共享檔案描述符表,以及共享訊號處理方式。本節就針對這幾個引數,看看Linux核心是如何實現這些資源的共享的。

1.CLONE_VM

do_fork()需要呼叫copy_mm()來設定task_struct中的mm和active_mm項,這兩個mm_struct資料與程序所關聯的記憶體空間相對應。如果do_fork()時指定了CLONE_VM開關,copy_mm()將把新的task_struct中的mm和active_mm設定成與current的相同,同時提高該mm_struct的使用者數目(mm_struct::mm_users)。也就是說,輕量級程序與父程序共享記憶體地址空間,由下圖示意可以看出mm_struct在程序中的地位:


2.CLONE_FS

task_struct中利用fs(struct fs_struct *)記錄了程序所在檔案系統的根目錄和當前目錄資訊,do_fork()時呼叫copy_fs()複製了這個結構;而對於輕量級程序則僅增加fs->;count計數,與父程序共享相同的fs_struct。也就是說,輕量級程序沒有獨立的檔案系統相關的資訊,程序中任何一個執行緒改變當前目錄、根目錄等資訊都將直接影響到其他執行緒。

3.CLONE_FILES

一個程序可能打開了一些檔案,在程序結構task_struct中利用files(struct files_struct *)來儲存程序開啟的檔案結構(struct file)資訊,do_fork()中呼叫了copy_files()來處理這個程序屬性;輕量級程序與父程序是共享該結構的,copy_files()時僅增加files->;count計數。這一共享使得任何執行緒都能訪問程序所維護的開啟檔案,對它們的操作會直接反映到程序中的其他執行緒。

4.CLONE_SIGHAND

每一個Linux程序都可以自行定義對訊號的處理方式,在task_struct中的sig(struct signal_struct)中使用一個struct k_sigaction結構的陣列來儲存這個配置資訊,do_fork()中的copy_sighand()負責複製該資訊;輕量級程序不進行復制,而僅僅增加signal_struct::count計數,與父程序共享該結構。也就是說,子程序與父程序的訊號處理方式完全相同,而且可以相互更改。

do_fork()中所做的工作很多,在此不詳細描述。對於SMP系統,所有的程序fork出來後,都被分配到與父程序相同的cpu上,一直到該程序被排程時才會進行cpu選擇。

儘管Linux支援輕量級程序,但並不能說它就支援核心級執行緒,因為Linux的"執行緒"和"程序"實際上處於一個排程層次,共享一個程序識別符號空間,這種限制使得不可能在Linux上實現完全意義上的POSIX執行緒機制,因此眾多的Linux執行緒庫實現嘗試都只能儘可能實現POSIX的絕大部分語義,並在功能上儘可能逼近。

三.LinuxThread的執行緒機制

LinuxThreads是目前Linux平臺上使用最為廣泛的執行緒庫,由Xavier Leroy ([email protected])負責開發完成,並已繫結在GLIBC中發行。它所實現的就是基於核心輕量級程序的"一對一"執行緒模型,一個執行緒實體對應一個核心輕量級程序,而執行緒之間的管理在核外函式庫中實現。

1.執行緒描述資料結構及實現限制

LinuxThreads定義了一個struct _pthread_descr_struct資料結構來描述執行緒,並使用全域性陣列變數__pthread_handles來描述和引用程序所轄執行緒。在__pthread_handles中的前兩項,LinuxThreads定義了兩個全域性的系統執行緒:__pthread_initial_thread和__pthread_manager_thread,並用__pthread_main_thread表徵__pthread_manager_thread的父執行緒(初始為__pthread_initial_thread)。

struct _pthread_descr_struct是一個雙環連結串列結構,__pthread_manager_thread所在的連結串列僅包括它一個元素,實際上,__pthread_manager_thread是一個特殊執行緒,LinuxThreads僅使用了其中的errno、p_pid、p_priority等三個域。而__pthread_main_thread所在的鏈則將程序中所有使用者執行緒串在了一起。經過一系列pthread_create()之後形成的__pthread_handles陣列將如下圖所示:

圖2 __pthread_handles陣列結構

新建立的執行緒將首先在__pthread_handles陣列中佔據一項,然後通過資料結構中的鏈指標連入以__pthread_main_thread為首指標的連結串列中。這個連結串列的使用在介紹執行緒的建立和釋放的時候將提到。

LinuxThreads遵循POSIX1003.1c標準,其中對執行緒庫的實現進行了一些範圍限制,比如程序最大執行緒數,執行緒私有資料區大小等等。在LinuxThreads的實現中,基本遵循這些限制,但也進行了一定的改動,改動的趨勢是放鬆或者說擴大這些限制,使程式設計更加方便。這些限定巨集主要集中在sysdeps/unix/sysv/linux/bits/local_lim.h(不同平臺使用的檔案位置不同)中,包括如下幾個:

每程序的私有資料key數,POSIX定義_POSIX_THREAD_KEYS_MAX為128,LinuxThreads使用PTHREAD_KEYS_MAX,1024;私有資料釋放時允許執行的運算元,LinuxThreads與POSIX一致,定義PTHREAD_DESTRUCTOR_ITERATIONS為4;每程序的執行緒數,POSIX定義為64,LinuxThreads增大到1024(PTHREAD_THREADS_MAX);執行緒執行棧最小空間大小,POSIX未指定,LinuxThreads使用PTHREAD_STACK_MIN,16384(位元組)。

2.管理執行緒

"一對一"模型的好處之一是執行緒的排程由核心完成了,而其他諸如執行緒取消、執行緒間的同步等工作,都是在核外執行緒庫中完成的。在LinuxThreads中,專門為每一個程序構造了一個管理執行緒,負責處理執行緒相關的管理工作。當程序第一次呼叫pthread_create()建立一個執行緒的時候就會建立(__clone())並啟動管理執行緒。

在一個程序空間內,管理執行緒與其他執行緒之間通過一對"管理管道(manager_pipe[2])"來通訊,該管道在建立管理執行緒之前建立,在成功啟動了管理執行緒之後,管理管道的讀端和寫端分別賦給兩個全域性變數__pthread_manager_reader和__pthread_manager_request,之後,每個使用者執行緒都通過__pthread_manager_request向管理執行緒發請求,但管理執行緒本身並沒有直接使用__pthread_manager_reader,管道的讀端(manager_pipe[0])是作為__clone()的引數之一傳給管理執行緒的,管理執行緒的工作主要就是監聽管道讀端,並對從中取出的請求作出反應。

建立管理執行緒的流程如下所示:
(全域性變數pthread_manager_request初值為-1)

圖3 建立管理執行緒的流程

初始化結束後,在__pthread_manager_thread中記錄了輕量級程序號以及核外分配和管理的執行緒id,2*PTHREAD_THREADS_MAX+1這個數值不會與任何常規使用者執行緒id衝突。管理執行緒作為pthread_create()的呼叫者執行緒的子執行緒執行,而pthread_create()所建立的那個使用者執行緒則是由管理執行緒來呼叫clone()建立,因此實際上是管理執行緒的子執行緒。(此處子執行緒的概念應該當作子程序來理解。)

__pthread_manager()就是管理執行緒的主迴圈所在,在進行一系列初始化工作後,進入while(1)迴圈。在迴圈中,執行緒以2秒為timeout查詢(__poll())管理管道的讀端。在處理請求前,檢查其父執行緒(也就是建立manager的主執行緒)是否已退出,如果已退出就退出整個程序。如果有退出的子執行緒需要清理,則呼叫pthread_reap_children()清理。

然後才是讀取管道中的請求,根據請求型別執行相應操作(switch-case)。具體的請求處理,原始碼中比較清楚,這裡就不贅述了。

3.執行緒棧

在LinuxThreads中,管理執行緒的棧和使用者執行緒的棧是分離的,管理執行緒在程序堆中通過malloc()分配一個THREAD_MANAGER_STACK_SIZE位元組的區域作為自己的執行棧。

使用者執行緒的棧分配辦法隨著體系結構的不同而不同,主要根據兩個巨集定義來區分,一個是NEED_SEPARATE_REGISTER_STACK,這個屬性僅在IA64平臺上使用;另一個是FLOATING_STACK巨集,在i386等少數平臺上使用,此時使用者執行緒棧由系統決定具體位置並提供保護。與此同時,使用者還可以通過執行緒屬性結構來指定使用使用者自定義的棧。因篇幅所限,這裡只能分析i386平臺所使用的兩種棧組織方式:FLOATING_STACK方式和使用者自定義方式。

在FLOATING_STACK方式下,LinuxThreads利用mmap()從核心空間中分配8MB空間(i386系統預設的最大棧空間大小,如果有執行限制(rlimit),則按照執行限制設定),使用mprotect()設定其中第一頁為非訪問區。該8M空間的功能分配如下圖:

圖4 棧結構示意

低地址被保護的頁面用來監測棧溢位。

對於使用者指定的棧,在按照指標對界後,設定執行緒棧頂,並計算出棧底,不做保護,正確性由使用者自己保證。

不論哪種組織方式,執行緒描述結構總是位於棧頂緊鄰堆疊的位置。

4.執行緒id和程序id

每個LinuxThreads執行緒都同時具有執行緒id和程序id,其中程序id就是核心所維護的程序號,而執行緒id則由LinuxThreads分配和維護。

__pthread_initial_thread的執行緒id為PTHREAD_THREADS_MAX,__pthread_manager_thread的是2*PTHREAD_THREADS_MAX+1,第一個使用者執行緒的執行緒id為PTHREAD_THREADS_MAX+2,此後第n個使用者執行緒的執行緒id遵循以下公式:


        tid=n*PTHREAD_THREADS_MAX+n+1
        

這種分配方式保證了程序中所有的執行緒(包括已經退出)都不會有相同的執行緒id,而執行緒id的型別pthread_t定義為無符號長整型(unsigned long int),也保證了有理由的執行時間內執行緒id不會重複。

從執行緒id查詢執行緒資料結構是在pthread_handle()函式中完成的,實際上只是將執行緒號按PTHREAD_THREADS_MAX取模,得到的就是該執行緒在__pthread_handles中的索引。

5.執行緒的建立

在pthread_create()向管理執行緒傳送REQ_CREATE請求之後,管理執行緒即呼叫pthread_handle_create()建立新執行緒。分配棧、設定thread屬性後,以pthread_start_thread()為函式入口呼叫__clone()建立並啟動新執行緒。pthread_start_thread()讀取自身的程序id號存入執行緒描述結構中,並根據其中記錄的排程方法配置排程。一切準備就緒後,再呼叫真正的執行緒執行函式,並在此函式返回後呼叫pthread_exit()清理現場。

6.LinuxThreads的不足

由於Linux核心的限制以及實現難度等等原因,LinuxThreads並不是完全POSIX相容的,在它的發行README中有說明。

1)程序id問題

這個不足是最關鍵的不足,引起的原因牽涉到LinuxThreads的"一對一"模型。

Linux核心並不支援真正意義上的執行緒,LinuxThreads是用與普通程序具有同樣核心排程檢視的輕量級程序來實現執行緒支援的。這些輕量級程序擁有獨立的程序id,在程序排程、訊號處理、IO等方面享有與普通程序一樣的能力。在原始碼閱讀者看來,就是Linux核心的clone()沒有實現對CLONE_PID引數的支援。

在核心do_fork()中對CLONE_PID的處理是這樣的:


          if (clone_flags & CLONE_PID) {
                if (current->;pid)
                        goto fork_out;
        }
        

這段程式碼表明,目前的Linux核心僅在pid為0的時候認可CLONE_PID引數,實際上,僅在SMP初始化,手工建立程序的時候才會使用CLONE_PID引數。

按照POSIX定義,同一程序的所有執行緒應該共享一個程序id和父程序id,這在目前的"一對一"模型下是無法實現的。

2)訊號處理問題

由於非同步訊號是核心以程序為單位分發的,而LinuxThreads的每個執行緒對核心來說都是一個程序,且沒有實現"執行緒組",因此,某些語義不符合POSIX標準,比如沒有實現向程序中所有執行緒傳送訊號,README對此作了說明。

如果核心不提供實時訊號,LinuxThreads將使用SIGUSR1和SIGUSR2作為內部使用的restart和cancel訊號,這樣應用程式就不能使用這兩個原本為使用者保留的訊號了。在Linux kernel 2.1.60以後的版本都支援擴充套件的實時訊號(從_SIGRTMIN到_SIGRTMAX),因此不存在這個問題。

某些訊號的預設動作難以在現行體系上實現,比如SIGSTOP和SIGCONT,LinuxThreads只能將一個執行緒掛起,而無法掛起整個程序。

3)執行緒總數問題

LinuxThreads將每個程序的執行緒最大數目定義為1024,但實際上這個數值還受到整個系統的總程序數限制,這又是由於執行緒其實是核心程序。

在kernel 2.4.x中,採用一套全新的總程序數計算方法,使得總程序數基本上僅受限於實體記憶體的大小,計算公式在kernel/fork.c的fork_init()函式中:


        max_threads = mempages / (THREAD_SIZE/PAGE_SIZE) / 8
        

在i386上,THREAD_SIZE=2*PAGE_SIZE,PAGE_SIZE=2^12(4KB),mempages=實體記憶體大小/PAGE_SIZE,對於256M的記憶體的機器,mempages=256*2^20/2^12=256*2^8,此時最大執行緒數為4096。

但為了保證每個使用者(除了root)的程序總數不至於佔用一半以上實體記憶體,fork_init()中繼續指定:


    init_task.rlim[RLIMIT_NPROC].rlim_cur = max_threads/2;
    init_task.rlim[RLIMIT_NPROC].rlim_max = max_threads/2;
    

這些程序數目的檢查都在do_fork()中進行,因此,對於LinuxThreads來說,執行緒總數同時受這三個因素的限制。

4)管理執行緒問題

管理執行緒容易成為瓶頸,這是這種結構的通病;同時,管理執行緒又負責使用者執行緒的清理工作,因此,儘管管理執行緒已經遮蔽了大部分的訊號,但一旦管理執行緒死亡,使用者執行緒就不得不手工清理了,而且使用者執行緒並不知道管理執行緒的狀態,之後的執行緒建立等請求將無人處理。

5)同步問題

LinuxThreads中的執行緒同步很大程度上是建立在訊號基礎上的,這種通過核心複雜的訊號處理機制的同步方式,效率一直是個問題。

6)其他POSIX相容性問題

Linux中很多系統呼叫,按照語義都是與程序相關的,比如nice、setuid、setrlimit等,在目前的LinuxThreads中,這些呼叫都僅僅影響呼叫者執行緒。

7)實時性問題

執行緒的引入有一定的實時性考慮,但LinuxThreads暫時不支援,比如排程選項,目前還沒有實現。不僅LinuxThreads如此,標準的Linux在實時性上考慮都很少。

相關推薦

Linux 程序執行關係

一.基礎知識:執行緒和程序 按照教科書上的定義,程序是資源管理的最小單位,執行緒是程式執行的最小單位。在作業系統設計上,從程序演化出執行緒,最主要的目的就是更好的支援SMP以及減小(程序/執行緒)上下文切換開銷。 無論按照怎樣的分法,一個程序至少需要一個執行緒作為它的指令執行體,程序管理著資源(比如cpu、記

linux程序執行狀態檢視

檢查 使用 ps -fe |grep programname 檢視獲得程序的pid,再使用 ps -Lf pid 檢視對應程序下的執行緒數. 查詢資料發現可以通過設定 ulimit -s 來增加每程序執行緒數。 每程序可用執行緒數 = VIRT上限/stack size

Linux程序執行的概念以及區別

linux程序與執行緒的區別,早已成為IT界經常討論但熱度不減的話題。無論你是初級程式設計師,還是資深專家,都應該考慮過這個問題,只是層次角度不同罷了。對於一般的程式設計師,搞清楚二者的概念並在工作中學會運用是其思考的主要問題;對於資深工程師,如何在系統層面實現兩種技術及其各自的效能和實現代價是其思考的主要問

linux檢視程序執行資訊(pstree pstack jstack)

導言 在日常開發運維中,經常需要對程序及其執行緒資訊進行獲取,來排查記憶體溢位,死鎖,阻塞等問題。本文主要是檢視程序及其程序堆疊資訊 一.PSTREE pstree [-acGhlnpuUV][-H <程式識別碼>][<程式識別碼

Linux系統學習】程序執行

程序執行新程式 程序等待 wait()函式 程序執行新程式 fork()/exec()組合是典型的Linux

程序執行理解和關係

程序 執行緒的含義 程序就是一個程式在一個數據集上的一次動態執行過程。 程序一般由程式、資料集、程序控制塊三部分組成。我們編寫的程式用來描述程序要完成哪些功能以及如何完成;資料集則是程式在執行過程中所需要使用的資源;程序控制塊用來記錄程序的外部特徵,描述程序的執行變化過程,系統可以利用它

程序執行之間的關係

程序和執行緒之間的關係 轉載來自:https://www.cnblogs.com/losing-1216/p/5083097.html 程序概念   程序是表示資源分配的基本單位,又是排程執行的基本單位。例如,使用者執行自己的程式,系統就建立一個程序,併為它分配資源,包括各種表格、

LINUX作業系統知識:程序執行詳解

當一個程式開始執行後,在開始執行到執行完畢退出這段時間內,它在記憶體中的部分就叫稱作一個程序。 Linux 是一個多工的作業系統,也就是說,在同一時間內,可以有多個程序同時執行。我們大家常用的單CPU計算機實際上在一個時間片段內只能執行一條指令。   那麼Linux是如何實現多程序的同時執行的呢?原來Linu

Linux程序執行的區別 詳細總結

首先,簡要了解一下程序和執行緒。對於作業系統而言,程序是核心之核心,整個現代作業系統的根本,就是以程序為單位在執行任務。系統的管理架構也是基於程序層面的。在按下電源鍵之後,計算機就開始了複雜的啟動過程,此處有一個經典問題:當按下電源鍵之後,計算機如何把自己由靜止啟動起來的?本

linux裡的程序執行(上)

在學習linux的過程中,程序與執行緒可謂一對好兄弟,是必然要掌握的內容。 一:何所謂程序 何所謂執行緒         程序:程序(Process)是計算機中的程式關於某資料集合上的一次執行活動,是系統進行資源分配與排程的基本單位。         執行緒:執行緒是作

linux的多執行/多程序同步/通訊機制

while (1) { //這個mutex主要是用來保證pthread_cond_wait的併發性 pthread_mutex_lock(&mtx); while (head == NULL) {

Linux程序執行關係淺析 (轉載)

  程序概念   程序是表示資源分配的基本單位,又是排程執行的基本單位。例如,使用者執行自己的程式,系統就建立一個程序,併為它分配資源,包括各種表格、記憶體空間、磁碟空間、I/O裝置等。然後,把該程序放人程序的就緒佇列。程序排程程式選中它,為它分配CPU以及其它有關資源,該程序才真正執行。所以,

Linux的多執行程式設計二(執行的同步互斥)

一、什麼叫做執行緒的同步與互斥?為什麼需要同步與互斥? 1、同步與互斥 互斥:是指某一資源同時只允許一個訪問者對其進行訪問,具有唯一性和排它性。但互斥無法限制訪問者對資源的訪問順序,即訪問是無序的。 同步:是指在互斥的基礎上(大多數情況),通過其它機制

程序執行關係區別

程序,是併發執行的程式在執行過程中分配和管理資源的基本單位,是一個動態概念,竟爭計算機系統資源的基本單位。每一個程序都有一個自己的地址空間,即程序空間或(虛空間)。程序空間的大小 只與處理機的位數有關,一個 16 位長處理機的程序空間大小為 216 ,而 32 位處理機

程序執行關係

程序和執行緒沒有嚴格的定義。這裡僅僅給出彼此的相同和不同點。不同點:程序是作業系統資源分配的最小單位,在沒有執行緒的情況下也是最小的排程單位。執行緒是任務排程的最小單位,可以作為一個獨立的單元執行。程序至少包含一個執行緒,執行緒共享所屬程序的資源。所以在一個程序中有多個程序時

Linux程序排程】程序執行的本質區別?

簡而言之,執行緒是程序的一部分,程序是程式的一部分。 異同: 1、程序是資源分配的基本單位,而執行緒是排程的基本單位; 2、程序與程序之間是獨立的,一個程序的異常終止不會影響其它程序,而執行緒與執行

程序執行關係及區別

1、定義   程序是具有一定獨立功能的程式關於某個資料集合上的一次執行活動,程序是系統進行資源分配和排程的一個獨立單位。   執行緒是程序的一個實體,是CPU排程和分派的基本單位,它是比程序更小的能獨立執行的基本單位,執行緒自己基本上不擁有系統資源,只擁有一點在執行中必不可

Linux程序執行的區別

程序與執行緒的區別,早已經成為了經典問題。自執行緒概念誕生起,關於這個問題的討論就沒有停止過。無論是初級程式設計師,還是資深專家,都應該考慮過這個問題,只是層次角度不同罷了。一般程式設計師而言,搞清楚二者的概念,在工作實際中去運用成為了焦點。而資深工程師則在考慮系統層面如

Windows檢視程序執行的相關工具

pslist是用命令列檢視程序/執行緒;ProcessExplorer是圖形化的檢視程序/執行緒。 ======================================================================================================

Linux程序執行的區別——不要太經典

Linux程序與執行緒的區別 程序與執行緒的區別,早已經成為了經典問題。自執行緒概念誕生起,關於這個問題的討論就沒