清楚說明 同步+擱置 , 同步+不擱置, 異步+擱置, 異步+不擱置 四種方式
1. 詳解 異步+擱置模式的 select()
2. 詳解 異步+非擱置模式的AIO
3. linux上最佳的處理方法 epoll...
Read more ...
2008年12月31日 星期三
2008年12月26日 星期五
2008年12月17日 星期三
fork與vfork的區別
vfork用於創建一個新進程,而該新進程的目的是exec一個新進程,vfork和fork一樣都創建一個子進程,但是它並不將父進程的地址空間完全複製到子進程中,不會複製頁表。因為子進程會立即調用exec,於是也就不會存放該地址空間。不過在子進程中調用exec或exit之前,他在父進程的空間中運行。
為什麼會有vfork,因為以前的fork當它創建一個子進程時,將會創建一個新的地址空間,並且拷貝父進程的資源,而往往在子進程中會執行exec調用,這樣,前面的拷貝工作就是白費力氣了,這種情況下,聰明的人就想出了vfork,它產生的子進程剛開始暫時與父進程共享地址空間(其實就是線程的概念了),因為這時候子進程在父進程的地址空間中運行,所以子進程不能進行寫操作,並且在兒子「霸佔」著老子的房子時候,要委屈老子一下了,讓他在外面歇著(阻塞),一旦兒子執行了exec或者exit後,相當於兒子買了自己的房子了,這時候就相當於分家了。
vfork和fork之間的另一個區別是: vfork保證子進程先運行,在她調用exec或exit之後父進程才可能被調度運行。如果在調用這兩個函數之前子進程依賴於父進程的進一步動作,則會導致死鎖。
由此可見,這個系統調用是用來啟動一個新的應用程序。其次,子進程在vfork()返回後直接運行在父進程的棧空間,並使用父進程的內存和數據。這意味著子進程可能破壞父進程的數據結構或棧,造成失敗。
為了避免這些問題,需要確保一旦調用vfork(),子進程就不從當前的棧框架中返回,並且如果子進程改變了父進程的數據結構就不能調用exit函數。子進程還必須避免改變全局數據結構或全局變量中的任何信息,因為這些改變都有可能使父進程不能繼續。
通常,如果應用程序不是在fork()之後立即調用exec(),就有必要在fork()被替換成vfork()之前做仔細的檢查。
用fork函數創建子進程後,子進程往往要調用一種exec函數以執行另一個程序,當進程調用一種exec函數時,該進程完全由新程序代換,而新程序則從其main函數開始執行,因為調用exec並不創建新進程,所以前後的進程id 並未改變,exec只是用另一個新程序替換了當前進程的正文,數據,堆和棧段。...
Read more ...
為什麼會有vfork,因為以前的fork當它創建一個子進程時,將會創建一個新的地址空間,並且拷貝父進程的資源,而往往在子進程中會執行exec調用,這樣,前面的拷貝工作就是白費力氣了,這種情況下,聰明的人就想出了vfork,它產生的子進程剛開始暫時與父進程共享地址空間(其實就是線程的概念了),因為這時候子進程在父進程的地址空間中運行,所以子進程不能進行寫操作,並且在兒子「霸佔」著老子的房子時候,要委屈老子一下了,讓他在外面歇著(阻塞),一旦兒子執行了exec或者exit後,相當於兒子買了自己的房子了,這時候就相當於分家了。
vfork和fork之間的另一個區別是: vfork保證子進程先運行,在她調用exec或exit之後父進程才可能被調度運行。如果在調用這兩個函數之前子進程依賴於父進程的進一步動作,則會導致死鎖。
由此可見,這個系統調用是用來啟動一個新的應用程序。其次,子進程在vfork()返回後直接運行在父進程的棧空間,並使用父進程的內存和數據。這意味著子進程可能破壞父進程的數據結構或棧,造成失敗。
為了避免這些問題,需要確保一旦調用vfork(),子進程就不從當前的棧框架中返回,並且如果子進程改變了父進程的數據結構就不能調用exit函數。子進程還必須避免改變全局數據結構或全局變量中的任何信息,因為這些改變都有可能使父進程不能繼續。
通常,如果應用程序不是在fork()之後立即調用exec(),就有必要在fork()被替換成vfork()之前做仔細的檢查。
用fork函數創建子進程後,子進程往往要調用一種exec函數以執行另一個程序,當進程調用一種exec函數時,該進程完全由新程序代換,而新程序則從其main函數開始執行,因為調用exec並不創建新進程,所以前後的進程id 並未改變,exec只是用另一個新程序替換了當前進程的正文,數據,堆和棧段。...
Read more ...
2008年9月23日 星期二
pid hash table
1. 基本概念
每個進程控制塊都有4個有關ID、含義不同的值,內核根據它們組成了4個全局的2維的HASH表,每個進程都要鏈接到這四個不同含義的Hash表當中。
/* 4種類型的值*/
enum pid_type
{
PIDTYPE_PID, 進程的PID
PIDTYPE_TGID, 線程組ID
PIDTYPE_PGID, 進程組ID
PIDTYPE_SID, 會話ID
PIDTYPE_MAX
};
struct task_struct {
......
/* PID/PID hash table linkage. */
struct pid pids[PIDTYPE_MAX];
......
}
2. Hash表的數組
四個全局的Hash表頭位於: static struct hlist_head *pid_hash[PIDTYPE_MAX];
每一個Hash表都是一個數組,每一個元素是一個Hash值的鏈表頭。默認有2048個元素
-----------------------------------------------------------------------------
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |...|2047| |
-----------------------------------------------------------------------------
3. Hash表數組元素的鏈表
我們拿進程的進程組ID(PIDTYPE_PGID)來舉例,假如有3個進程組,分別是:
GROUP1:
PID PGIP HASH_PGID (根據進程組ID[PGIP]得到的Hash值)
10 10 hash(10)=88 (進程組領頭)
11 10 hash(10)=88
12 10 hash(10)=88
GROUP2:
PID PGIP HASH_PGID (根據進程組ID[PGIP]得到的Hash值)
100 100 hash(100)=99 (進程組領頭)
101 100 hash(100)=99
102 100 hash(100)=99
GROUP3:
PID PGIP HASH_PGID (根據進程組ID[PGIP]得到的Hash值)
550 550 hash(550)=88 (進程組領頭)
551 550 hash(550)=88
552 550 hash(550)=88
struct pid
{
/* Try to keep pid_chain in the same cacheline as nr for find_pid */
/* 值 */
int nr;
/* HASH_PGID 值相同、且為進程組領頭的進程鏈在這裡,如PID值為10和550的兩個進程會通過這個字段鏈接,這裡可以認為是1個維度鏈,非進程組的進程的這個域為NULL(這裡不考慮其它3種類型的值) */
struct hlist_node pid_chain;
/* PGID 值相同的進程鏈在這裡,如上3個進程組,分別各自通過這個域鏈接起來,這裡可以認為是第2個維度鏈 */
/* list of pids with the same nr, only one of them is in the hash */
struct list_head pid_list;
};
PGID的Hash表(即全局的pid_hash[PIDTYPE_PGID])
----
0
----
1
----
2
----
88 ---> 10 ---> 11 ---> 12 通過pid_list域鏈接
---- |
... | 通過pid_chain域鏈接
---- |
90 550 ---> 551 ---> 552 通過pid_list域鏈接
----
..
----
99 ---> 100 ---> 101 ---> 102 通過pid_list域鏈接
----
2047
文章出處:http://www.diybl.com/course/6_system/linux/Linuxjs/200888/135051.html...
Read more ...
每個進程控制塊都有4個有關ID、含義不同的值,內核根據它們組成了4個全局的2維的HASH表,每個進程都要鏈接到這四個不同含義的Hash表當中。
/* 4種類型的值*/
enum pid_type
{
PIDTYPE_PID, 進程的PID
PIDTYPE_TGID, 線程組ID
PIDTYPE_PGID, 進程組ID
PIDTYPE_SID, 會話ID
PIDTYPE_MAX
};
struct task_struct {
......
/* PID/PID hash table linkage. */
struct pid pids[PIDTYPE_MAX];
......
}
2. Hash表的數組
四個全局的Hash表頭位於: static struct hlist_head *pid_hash[PIDTYPE_MAX];
每一個Hash表都是一個數組,每一個元素是一個Hash值的鏈表頭。默認有2048個元素
-----------------------------------------------------------------------------
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |...|2047| |
-----------------------------------------------------------------------------
3. Hash表數組元素的鏈表
我們拿進程的進程組ID(PIDTYPE_PGID)來舉例,假如有3個進程組,分別是:
GROUP1:
PID PGIP HASH_PGID (根據進程組ID[PGIP]得到的Hash值)
10 10 hash(10)=88 (進程組領頭)
11 10 hash(10)=88
12 10 hash(10)=88
GROUP2:
PID PGIP HASH_PGID (根據進程組ID[PGIP]得到的Hash值)
100 100 hash(100)=99 (進程組領頭)
101 100 hash(100)=99
102 100 hash(100)=99
GROUP3:
PID PGIP HASH_PGID (根據進程組ID[PGIP]得到的Hash值)
550 550 hash(550)=88 (進程組領頭)
551 550 hash(550)=88
552 550 hash(550)=88
struct pid
{
/* Try to keep pid_chain in the same cacheline as nr for find_pid */
/* 值 */
int nr;
/* HASH_PGID 值相同、且為進程組領頭的進程鏈在這裡,如PID值為10和550的兩個進程會通過這個字段鏈接,這裡可以認為是1個維度鏈,非進程組的進程的這個域為NULL(這裡不考慮其它3種類型的值) */
struct hlist_node pid_chain;
/* PGID 值相同的進程鏈在這裡,如上3個進程組,分別各自通過這個域鏈接起來,這裡可以認為是第2個維度鏈 */
/* list of pids with the same nr, only one of them is in the hash */
struct list_head pid_list;
};
PGID的Hash表(即全局的pid_hash[PIDTYPE_PGID])
----
0
----
1
----
2
----
88 ---> 10 ---> 11 ---> 12 通過pid_list域鏈接
---- |
... | 通過pid_chain域鏈接
---- |
90 550 ---> 551 ---> 552 通過pid_list域鏈接
----
..
----
99 ---> 100 ---> 101 ---> 102 通過pid_list域鏈接
----
2047
文章出處:http://www.diybl.com/course/6_system/linux/Linuxjs/200888/135051.html...
Read more ...
訂閱:
文章 (Atom)