nptl是乙個1×1的執行緒模型,即乙個執行緒對於乙個作業系統的排程程序,優點是非常簡單。而其他一些作業系統比如solaris則是mxn的,m對應建立的執行緒數,n對應作業系統可以執行的實體。(n轉
**:全選
937 struct task_struct ;
pid,從字面上是process id,但其實是thread id。
tgid,從字面上,應該是thread group id,也就是真正的process id。
這一點,可以從系統呼叫getpid和gettid中看出來(位於kernel/timer.c)。
**:全選
954 asmlinkage long sys_getpid(void)
955
1100 asmlinkage long sys_gettid(void)
1101
group_leader欄位,指向執行緒組中的第乙個執行緒,建立第乙個執行緒的時候,group_leader指向自己,建立其後的執行緒時,指向第乙個執行緒的task_struct結構;
thread_group,當前程序所有執行緒的佇列,對於group_leader,這是個佇列頭,對於其後的程序而言,通過這個字段,掛入佇列中,可以通過此佇列,遍歷所有執行緒。
執行緒組中各個執行緒的關係,是在do_fork中設定的,具體的**在copy_process中(位於kernel/fork.c):**:全選
959 copy_process()
960
1254 if (likely(p->pid))
...
1271 }
...
1320 }
1113-1114行說明在建立執行緒時,從父程序獲取tgid,表明他們在同乙個執行緒組中;1181-1182則對group_leader和thread_group初始化,對於第乙個執行緒,則group_leader就是它自己;1234-1236行,將新建立的執行緒的group_leader設定成為父程序得group_leader,無論父程序是不是執行緒組中的第乙個執行緒,它的group_leader都是指向第乙個執行緒的task_struct,同時通過thread_group欄位,掛入到第乙個執行緒的thread_group佇列中;1266行表明只有執行緒組中的第乙個執行緒,才會通過tasks欄位,掛入到init_task佇列中。
在引入執行緒組概念後,退出部分也引入了乙個新的系統呼叫exit_group(位於kernel/exit.c)
1055 noret_type void
1056 do_group_exit(int exit_code)
1057
1073 spin_unlock_irq(&sighand->siglock);
1074 }
1075
1076 do_exit(exit_code);
1077 /* notreached */
1078 }
在1060行中,current->signal其實是執行緒組中所有執行緒共享的,對於呼叫exit_group的那個執行緒,如果是乙個多執行緒的程序,就會進入1062-1074這部分**,如果是單執行緒,則直接進入do_exit退出程序。這部分**的主要操作在zap_other_threads中(位於kernel/signal.c)
void zap_other_threads(struct task_struct *p)
982
1002 }
next_thread定義在include/linux/sched.h中,如下
651 static inline struct task_struct *next_thread(const struct task_struct *p)
1652
其實就是通過task_struct中的thread_group佇列來遍歷執行緒組中的所有執行緒。
在其中,會在signal->flags中設定signal_group_exit,同時,搜尋執行緒組中所有程序,在每個執行緒中掛上乙個sigkill訊號,這樣,當那些執行緒排程到執行的時候,就會處理sigkill訊號,對於sigkill訊號的處理,會呼叫do_group_exit,不過,當這次呼叫到do_group_exit的時候,將執行到1061行,然後就到了1076行的do_exit。這樣,當執行緒組中的每個執行緒都執行過一遍後,整個執行緒組就退出了。
posix thread library (nptl)使linux核心可以非常有效的執行使用posix執行緒標準寫的程式。這裡有乙個測試資料,在32位機下,nptl成功啟動100000個執行緒只用了2秒,而不使用nptl將需要大約15分鐘左右的時間。
歷史在核心2.6以前的排程實體都是程序,核心並沒有真正支援執行緒。它是能過乙個系統呼叫clone()來實現的,這個呼叫建立了乙份呼叫程序的拷貝,跟fork()不同的是,這份程序拷貝完全共享了呼叫程序的位址空間。linuxthread就是通過這個系統呼叫來提供執行緒在核心級的支援的(許多以前的執行緒實現都完全是在使用者態,核心根本不知道執行緒的存在)。非常不幸的是,這種方法有相當多的地方沒有遵循posix標準,特別是在訊號處理,排程,程序間通訊原語等方面。
很顯然,為了改進linuxthread必須得到核心的支援,並且需要重寫執行緒庫。為了實現這個需求,開始有兩個相互競爭的專案:ibm啟動的ngtp(next generation posix threads)專案,以及redhat公司的nptl。在2023年的年中,ibm放棄了ngtp,也就是大約那時,redhat發布了最初的nptl。
nptl最開始在redhat linux 9裡發布,現在從rhel3起核心2.6起都支援nptl,並且完全成了gnu c庫的一部分。
設計nptl使用了跟linuxthread相同的辦法,在核心裡面執行緒仍然被當作是乙個程序,並且仍然使用了clone()系統呼叫(在nptl庫里呼叫)。但是,nptl需要核心級的特殊支援來實現,比如需要掛起然後再喚醒執行緒的執行緒同步原語futex.
nptl也是乙個1*1的執行緒庫,就是說,當你使用pthread_create()呼叫建立乙個執行緒後,在核心裡就相應建立了乙個排程實體,在linux裡就是乙個新程序,這個方法最大可能的簡化了執行緒的實現。
有乙個問題一直沒有想清楚,請教牛人,謝謝。
資源描述:
系統環境:4個cpu, linux2.6核心,nptl,smp。
問題:(程序是資源單元;執行緒是執行單元。)
乙個程序擁有4個執行緒,這4個執行緒同時在4個cpu上執行。
問1:系統的排程單位是程序還是執行緒呢?(針對linux2.6核心);
問2:如果排程單位是執行緒,每個執行緒都應該執行在同乙個程序的上下文中,如果這樣的話就需要對程序上下文加鎖;同時如果有其他程序的執行緒也執行在同乙個cpu上,那麼程序的上下文切換會非常頻繁?
如果排程單位是程序,又沒有辦法解釋同乙個程序中的4個執行緒同時跑在4個cpu上?
問3:看到一篇文章說「smp的負載均衡是按程序數計算的」不知道是否正確。
如果正確,同乙個程序的所有執行緒應該分配到同乙個cpu上,不解?
答:問題1:
linux核心中的排程單位總是乙個程序。但是核心中有對執行緒的支援。
問題2:
既然在linux的執行緒就是乙個程序.就不存在什麼所有執行緒都在同一程序上下文。而且這個觀點是錯誤的。乙個執行緒是什麼?執行緒只是乙個程序的子集。也就是說是乙個程序上下文的子集。而且每個執行緒的上下文的很少有交集。除非兩個執行緒之間需要通訊。linux中程序所傳建的執行緒本質就是程序。只不過這些子程序和父程序看到的都是同一位址空間,共享資源。 恢復乙個執行緒的執行只需要恢復執行緒上下文。既然是執行緒在執行,何來程序上下文? 執行緒的實現方式不同.但原理本質一樣。 既然linux的排程單位是程序,而執行緒又是以程序實現的.所以程序的四個執行緒在4個cpu上同時執行是可能的.只要不存在互斥。
問題3:
這個是高階問題... 不清楚...樓主可以goolge下.應該很多文章和**的。
Linux 2 6核心編譯,核心公升級
本文描述了在fc8下公升級linux核心為2.6.25的詳細步驟.1.首先從如下 得到linux 2.6.25.2.然後在 usr src下untar這個包.tar xjfv linux 2.6.25.tar.bz2 3.配置核心 cd usr src linux 2.6.25 make mrpro...
Linux2 6核心啟動分析
我們已知u boot的終極目的是啟動核心,那麼核心啟動的開始必定是u boot傳入的引數。開啟armlinux.c 發現有一行的 為 thekernel 0,bd bi arch number,bd bi boot params 帶入三個引數 第乙個引數是0,第二個引數是機器id,第三個引數是引數所...
Linux 2 6 核心驅動移植
隨著 linux 2.6的發布,由於2.6核心做了教的改動,各個裝置的 驅動程式在不同程度上要進行改寫。為了方便各位linux愛好者我把自己整理的這分文件share出來。該文當列舉了2.6核心同以前版本的絕大多數變化,可惜的是由於時間和精力有限沒有詳細列出各個函式的用法。1 使用新的入口 必須包含 ...