欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
reentrant函數與thread safe函數淺析
記得以前討論過(guò)一個(gè)關(guān)于reentrant函數與thread safe函數的帖子
很多人對于這兩種函數不是很了解,
尤其是發(fā)現malloc等函數是non-reentrant函數時(shí),對多線(xiàn)程編程都產(chǎn)生了"恐懼"
這里是我對這兩種函數的一些理解,希望和大家探討一些.歡迎批評指正.
1. reentrant函數
一個(gè)函數是reentrant的,如果它可以被安全地遞歸或并行調用。要想成為reentrant式的函數,該函數不能含有(或使用)靜態(tài)(或全局)數據(來(lái)存儲函數調用過(guò)程中的狀態(tài)信息),也不能返回指向靜態(tài)數據的指針,它只能使用由調用者提供的數據,當然也不能調用non-reentrant函數.
比較典型的non-reentrant函數有g(shù)etpwnam, strtok, malloc等.
reentrant和non-reentrant函數的例子
 
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <math.h>
int* getPower(int i)
{
  static int result;
  result = pow(2, i);
  getchar();
  return &result;
}
void getPower_r(int i, int* result)
{
  *result = pow(2, i);
}
void handler (int signal_number) /*處理SIGALRM信號*/
{
  getPower(3);
}
int main ()
{
  int *result;
  struct sigaction sa;
  memset(&sa, 0, sizeof(sa));
  sa.sa_handler = &handler;
  sigaction(SIGALRM, &sa, NULL);
  result = getPower(5);
  printf("2^5 = %d\n", *result);
  return 0;
}
 

試驗方法:
1. 編譯 gcc test.c -lpthread
在一個(gè)終端中運行 ./a.out, 在另一個(gè)終端中運行 ps -A|grep a.out可以看到該進(jìn)程的id
2. 用如下方式運行a.out:
運行./a.out,在按回車(chē)前,在另外一個(gè)終端中運行kill -14 pid (這里的pid是運行上面的ps時(shí)看到的值)
然后,按回車(chē)繼續運行a.out就會(huì )看到2^5 = 8 的錯誤結論

對于函數int* getPower(int i)
由于函數getPower會(huì )返回一個(gè)指向靜態(tài)數據的指針,在第一次調用getPower的過(guò)程中,再次調用getPower,則兩次返回的指針都指向同一塊內存,第二次的結果將第一次的覆蓋了(很多non-reentrant函數的這種用法會(huì )導致不確定的后果).所以是non-reentrant的.

對于函數void getPower_r(int i, int* result)
getPower_r會(huì )將所得的信息存儲到result所指的內存中,它只是使用了由調用者提供的數據,所以是reentrant.在信號處理函數中可以正常的使用它.

2. thread-safe函數
Thread safety是多線(xiàn)程編程中的概念,thread safe函數是指那些能夠被多個(gè)線(xiàn)程同時(shí)并發(fā)地正確執行的函數.
thread safe和non thread safe的例子
 
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t sharedMutex=PTHREAD_MUTEX_INITIALIZER;
int count; /*共享數據*/
void* func (void* unused)
{
  if (count == 0)
    count++;
}
void* func_s (void* unused)
{
  pthread_mutex_lock(&sharedMutex);    /*進(jìn)入臨界區*/
  if (count == 0)
    count++;
  pthread_mutex_unlock(&sharedMutex);  /*離開(kāi)臨界區*/
}

int main ()
{
  pthread_t pid1, pid2;
  pthread_create(&pid1, NULL, &func, NULL);
  pthread_create(&pid2, NULL, &func, NULL);
  pthread_join(pid1, NULL);
  pthread_join(pid2, NULL);
  return 0;
}
 

函數func是non thread safe的,這是因為它不能避免對共享數據count的race condition,
設想這種情況:一開(kāi)始count是0,當線(xiàn)程1進(jìn)入func函數,判斷過(guò)count == 0后,線(xiàn)程2進(jìn)入func函數
線(xiàn)程2判斷count==0,并執行count++,然后線(xiàn)程1開(kāi)始執行,此時(shí)count != 0 了,但是線(xiàn)程1仍然要執行
count++,這就產(chǎn)生了錯誤.
func_s通過(guò)mutex鎖將對共享數據的訪(fǎng)問(wèn)鎖定,從而避免了上述情況的發(fā)生.func_s是thread safe的
只要通過(guò)適當的"鎖"機制,thread safe函數還是比較好實(shí)現的.
3. reentrant函數與thread safe函數的區別
reentrant函數與是不是多線(xiàn)程無(wú)關(guān),如果是reentrant函數,那么要求即使是同一個(gè)進(jìn)程(或線(xiàn)程)同時(shí)多次進(jìn)入該函數時(shí),該函數仍能夠正確的運作.
該要求還蘊含著(zhù),如果是在多線(xiàn)程環(huán)境中,不同的兩個(gè)線(xiàn)程同時(shí)進(jìn)入該函數時(shí),該函數也能夠正確的運作.
thread safe函數是與多線(xiàn)程有關(guān)的,它只是要求不同的兩個(gè)線(xiàn)程同時(shí)對該函數的調用在邏輯上是正確的.
從上面的說(shuō)明可以看出,reentrant的要求比thread safe的要求更加嚴格.reentrant的函數必是thread safe的,而thread safe的函數
未必是reentrant的. 舉例說(shuō)明:
 
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
pthread_mutex_t sharedMutex=PTHREAD_MUTEX_INITIALIZER;
int count; /*共享數據*/
void* func_s (void* unused)
{
  pthread_mutex_lock(&sharedMutex);    /*進(jìn)入臨界區*/
  printf("locked by thead %d\n", pthread_self());
  if (count == 0)
    count++;
  getchar();
  pthread_mutex_unlock(&sharedMutex);  /*離開(kāi)臨界區*/
  printf("lock released by thead %d\n", pthread_self());
}
void handler (int signal_number) /*處理SIGALRM信號*/
{
  printf("handler running in %d\n", pthread_self());
  func_s(NULL);
}

int main ()
{
  pthread_t pid1, pid2;
  struct sigaction sa;
  memset(&sa, 0, sizeof(sa));
  sa.sa_handler = &handler;
  sigaction(SIGALRM, &sa, NULL);
  printf("main thread's pid is: %d\n", pthread_self());
  func_s(NULL);
  pthread_create(&pid1, NULL, &func_s, NULL);
  pthread_create(&pid2, NULL, &func_s, NULL);
  pthread_join(pid1, NULL);
  pthread_join(pid2, NULL);
  func_s(NULL);
  return 0;
}
 

試驗方法:
1. 編譯 gcc test.c -lpthread
在一個(gè)終端中運行 ./a.out, 在另一個(gè)終端中運行 ps -A|grep a.out可以看到該進(jìn)程的id
2. 進(jìn)行下面4次運行a.out:
每次運行分別在第1,2,3,4次回車(chē)前,在另外一個(gè)終端中運行kill -14 pid (這里的pid是上面ps中看到的值)
試驗結果:
1. 該進(jìn)程中有3個(gè)線(xiàn)程:一個(gè)主線(xiàn)程,兩個(gè)子線(xiàn)程
2. func_s是thread safe的
3. func_s不是reentrant的
4. 信號處理程序會(huì )中斷主線(xiàn)程的執行,不會(huì )中斷子線(xiàn)程的執行
5. 在第1,4次回車(chē)前,在另外一個(gè)終端中運行kill -14 pid會(huì )形成死鎖,這是因為
主線(xiàn)程先鎖住了臨界區,主線(xiàn)程被中斷后,執行handler(以主線(xiàn)程執行),handler試圖鎖定臨界區時(shí),
由于同一個(gè)線(xiàn)程鎖定兩次,所以形成死鎖
6. 在第2,3次回車(chē)前,在另外一個(gè)終端中運行kill -14 pid不會(huì )形成死鎖,這是因為一個(gè)子線(xiàn)程先鎖住
了臨界區,主線(xiàn)程被中斷后,執行handler(以主線(xiàn)程執行),handler試圖鎖定臨界區時(shí),被掛起,這時(shí),子線(xiàn)程
可以被繼續執行.當該子線(xiàn)程釋放掉鎖以后,handler和另外一個(gè)子線(xiàn)程可以競爭進(jìn)入臨界區,然后繼續執行.
所以不會(huì )形成死鎖.
結論:
1. reentrant是對函數相當嚴格的要求,絕大部分函數都不是reentrant的(APUE上有一個(gè)reentrant函數
的列表).
什么時(shí)候我們需要reentrant函數呢?只有一個(gè)函數需要在同一個(gè)線(xiàn)程中需要進(jìn)入兩次以上,我們才需要
reentrant函數.這些情況主要是異步信號處理,遞歸函數等等.(non-reentrant的遞歸函數也不一定會(huì )
出錯,出不出錯取決于你怎么定義和使用該函數). 大部分時(shí)候,我們并不需要函數是reentrant的.
2. 在多線(xiàn)程環(huán)境當中,只要求多個(gè)線(xiàn)程可以同時(shí)調用一個(gè)函數時(shí),該函數只要是thread safe的就可以了.
我們常見(jiàn)的大部分函數都是thread safe的,不確定的話(huà)請查閱相關(guān)文檔.
3. reentrant和thread safe的本質(zhì)的區別就在于,reentrant函數要求即使在同一個(gè)線(xiàn)程中任意地進(jìn)入兩次以上,
也能正確執行.
大家常用的malloc函數是一個(gè)典型的non-reentrant但是是thread safe函數,這就說(shuō)明,我們可以方便的
在多個(gè)線(xiàn)程中同時(shí)調用malloc,但是,如果將malloc函數放入信號處理函數中去,這是一件很危險的事情.
4. reentrant函數肯定是thread safe函數,也就是說(shuō),non thread safe肯定是non-reentrant函數
不能簡(jiǎn)單的通過(guò)加鎖,來(lái)使得non-reentrant函數變成 reentrant函數
這個(gè)鏈接是說(shuō)明一些non-reentrant ===> reentrant和non thread safe ===>thread safe轉換的
http://www.unet.univie.ac.at/aix/aixprggd/genprogc/writing_reentrant_thread_safe_code.htm
[ 本帖最后由 ypxing 于 2007-8-4 01:06 編輯 ]
 
--------------------------------------------------------------------------------
 lenovo 回復于:2007-08-02 21:38:57
不錯,很好的帖子。

--------------------------------------------------------------------------------
 科技牛 回復于:2007-08-03 15:38:14
受教很深!

--------------------------------------------------------------------------------
 ypxing 回復于:2007-08-03 15:58:22
調用了malloc的函數肯定是non-reentrant的
引用:原帖由 bluster 于 2007-8-3 15:55 發(fā)表 [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=7155171&ptid=971102]
最后一點(diǎn)是錯的,比如一個(gè)函數調用malloc并不影響這個(gè)函數是否是reentrant。
 
--------------------------------------------------------------------------------
 ypxing 回復于:2007-08-03 15:59:35
這家伙,怎么把自己的帖子給刪了?

--------------------------------------------------------------------------------
 bluster 回復于:2007-08-03 16:01:11
引用:原帖由 ypxing 于 2007-8-3 15:58 發(fā)表 [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=7155198&ptid=971102]
調用了malloc的函數肯定是non-reentrant的
 
你是對的,我一時(shí)有點(diǎn)繞。
其實(shí),是對reentrant的定義有問(wèn)題。
可重入的意思,差不多是函數的任意部分都可以并行,而線(xiàn)程安全的意思則是多線(xiàn)程環(huán)境下使用沒(méi)有問(wèn)題,對于非可重入的函數,使用lock來(lái)保護不可并行的部分從而線(xiàn)程安全。
引用:原帖由 ypxing 于 2007-8-3 15:59 發(fā)表 [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=7155214&ptid=971102]
這家伙,怎么把自己的帖子給刪了?
無(wú)價(jià)值糊涂帖,所以刪了。
[ 本帖最后由 bluster 于 2007-8-3 16:05 編輯 ]

--------------------------------------------------------------------------------
 jigloo 回復于:2007-08-03 16:11:55
>>3. reentrant和thread safe的本質(zhì)的區別就在于,reentrant函數要求在同一個(gè)線(xiàn)程中需要進(jìn)入兩次以上,
并能正確執行.
這個(gè)說(shuō)的不對,可重入區別在于允許任意中斷函數的執行并恢復(比如信號)
http://www.ibm.com/developerworks/cn/linux/l-reent.html

--------------------------------------------------------------------------------
 思一克 回復于:2007-08-03 17:03:49
這個(gè)問(wèn)題很復雜。
LZ的帖子很好。改進(jìn)的地方是LZ應該多講WHY不可重入,如何才可重入,而不是下結論。
1)調用了不可重入函數的函數不一定是不可重入的。比如LINUX KERNEL中,設備中斷處理函數是不可重入的,而__do_IRQ()調用了他們,但__do_IRQ卻是可重入的。
只要保證被調用的函數部分沒(méi)有重入就可以了。
2)使用的全局變量的函數也不一定是不可重入的。還比如__do_IRQ()使用了全局變量來(lái)存儲數據,但它是可重入的。
類(lèi)似的例子:
[CODE]
int ia[32];
int func(int i)
{
    ia++;
    printf("%p i %d %d\n", &i, i, ia);
    if(i == 31) return;
    func(i+1);
}
main()
{
    func(0);
}
[/CODE]
關(guān)于這個(gè)問(wèn)題,看LINUX中斷處理部分非常有啟發(fā)。那里邏輯復雜,各種重入(硬,軟中斷,多CPU)處理的非常巧妙。

--------------------------------------------------------------------------------
 ypxing 回復于:2007-08-03 18:50:12
思一克,你好
首先謝謝你的鼓勵.
你給出的這個(gè)例子,函數func,既不是可重入的,也不是線(xiàn)程安全的,
原因如下:
假設有一個(gè)信號處理函數handler,里面調用了func
考慮這種情況:
主函數中調用了func(0) (這個(gè)時(shí)候,你的本意是先要ia[0]++,然后打印現在ia[0]的值,
再然后繼續后面的操作),
在func剛執行完ia[0]++時(shí),信號觸發(fā)了handler函數,
handler函數會(huì )調用func函數,然后執行對ia的一系列操作,完成后返回.
這時(shí),你的主函數調用的func繼續執行,也就是要printf了,
這時(shí)printf的東東就不是你想要的了,而且你無(wú)法確定現在ia[0]的值是什么(因為信號
可以中斷很多次很多層).所以func不是可重入的.
而且也不是線(xiàn)程安全的.
可重入的一個(gè)判定方法就是將它放入信號處理函數中,仔細推敲各種中斷情況下,
你是不是還能得到你想要的結果.
"使用的全局變量的函數也不一定是不可重入的。"這句是正確的,只要正確使用就可以了,
但是不使用全局變量是寫(xiě)可重入函數的簡(jiǎn)單方法.
"調用了不可重入函數的函數不一定是不可重入的。"這句是不對的,
因為你無(wú)法保證被調用的不可重入函數部分不被重入

int ia[32];
int func(int i)
{
    ia++;
    printf("%p i %d %d\n", &i, i, ia);
    if(i == 31) return;
    func(i+1);
}
main()
{
    func(0);
}
 

--------------------------------------------------------------------------------
 思一克 回復于:2007-08-03 19:39:57
你寫(xiě)可重入函數時(shí)候要考慮到保證不可重入部分不重入, 還有保證整個(gè)函數必須可重入.
__do_IRQ就是如此.
所以說(shuō)"調用了不可重入函數的函數不一定是不可重入的"是正確的.
而"調用了不可重入函數的函數一定是不可重入的"是不對的.因為有十分多的反例.

調用了不可重入函數的函數不一定是不可重入的。"這句是不對的,
因為你無(wú)法保證被調用的不可重入函數部分不被重入

--------------------------------------------------------------------------------
 feasword 回復于:2007-08-03 20:09:35
一直想找這兩個(gè)概念是此非彼的例子,受教了
關(guān)于死鎖的問(wèn)題,apue里也有講,以前也遇到過(guò),當時(shí)干脆都弄成遞歸鎖了

--------------------------------------------------------------------------------
 ypxing 回復于:2007-08-03 20:49:04
那么,怎么才能保證不可重入的部分不被重入呢?
引用:原帖由 思一克 于 2007-8-3 19:39 發(fā)表 [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=7156157&ptid=971102]
你寫(xiě)可重入函數時(shí)候要考慮到保證不可重入部分不重入, 還有保證整個(gè)函數必須可重入.
__do_IRQ就是如此.
所以說(shuō)"調用了不可重入函數的函數不一定是不可重入的"是正確的.
而"調用了不可重入函數的函數一定是不可 ...
 
--------------------------------------------------------------------------------
 cugb_cat 回復于:2007-08-03 22:12:05
引用:原帖由 ypxing 于 2007-8-3 20:49 發(fā)表 [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=7156295&ptid=971102]
那么,怎么才能保證不可重入的部分不被重入呢?
 
我有同樓主相同的疑問(wèn)。
另外,從lz的例子中學(xué)到一些技巧,關(guān)于調試多線(xiàn)程程序,感謝lz。
[ 本帖最后由 cugb_cat 于 2007-8-3 22:45 編輯 ]

--------------------------------------------------------------------------------
 飛灰橙 回復于:2007-08-03 22:18:09
引用:原帖由 思一克 于 2007-8-3 19:39 發(fā)表 [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=7156157&ptid=971102]
你寫(xiě)可重入函數時(shí)候要考慮到保證不可重入部分不重入, 還有保證整個(gè)函數必須可重入.
__do_IRQ就是如此.
所以說(shuō)"調用了不可重入函數的函數不一定是不可重入的"是正確的.
而"調用了不可重入函數的函數一定是不可重入的"是不對的(語(yǔ)句A).因為有十分多的反例.

調用了不可重入函數的函數不一定是不可重入的。"這句是不對的(語(yǔ)句B),
因為你無(wú)法保證被調用的不可重入函數部分不被重入

越看越糊涂了,撇開(kāi)討論的問(wèn)題不談, 上面的語(yǔ)句A和語(yǔ)句B,必定有一句是錯的

--------------------------------------------------------------------------------
 cugb_cat 回復于:2007-08-03 22:44:57
引用:原帖由 飛灰橙 于 2007-8-3 22:18 發(fā)表 [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=7156605&ptid=971102]

越看越糊涂了,撇開(kāi)討論的問(wèn)題不談, 上面的語(yǔ)句A和語(yǔ)句B,必定有一句是錯的
兩句意思相反~:mrgreen:

--------------------------------------------------------------------------------
 ypxing 回復于:2007-08-03 23:30:14
俺也看了好一會(huì )才看懂:em02: 
引用:原帖由 飛灰橙 于 2007-8-3 22:18 發(fā)表 [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=7156605&ptid=971102]

越看越糊涂了,撇開(kāi)討論的問(wèn)題不談, 上面的語(yǔ)句A和語(yǔ)句B,必定有一句是錯的
 
--------------------------------------------------------------------------------
 mingyanguo 回復于:2007-08-04 00:08:35
完了,簡(jiǎn)單的問(wèn)題復雜化了 :mrgreen:

--------------------------------------------------------------------------------
 hakase 回復于:2007-08-08 20:37:06
好帖,受教了~~

--------------------------------------------------------------------------------
 ypxing 回復于:2007-08-08 23:05:51
這兩天寫(xiě)了一個(gè)測試程序來(lái)驗證malloc的不可重入性
但是malloc一直沒(méi)有crash,有點(diǎn)郁悶
過(guò)段時(shí)間把自己的測試代碼貼出來(lái),讓大家來(lái)幫忙看看

--------------------------------------------------------------------------------
 bluster 回復于:2007-08-09 10:08:56
引用:原帖由 ypxing 于 2007-8-8 23:05 發(fā)表 [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=7176529&ptid=971102]
這兩天寫(xiě)了一個(gè)測試程序來(lái)驗證malloc的不可重入性
但是malloc一直沒(méi)有crash,有點(diǎn)郁悶
過(guò)段時(shí)間把自己的測試代碼貼出來(lái),讓大家來(lái)幫忙看看
多線(xiàn)程條件下,signal的handler有可能在一個(gè)單獨的線(xiàn)程中執行,如果這樣那么malloc用鎖保護就夠了。

--------------------------------------------------------------------------------
 ypxing 回復于:2007-08-09 10:29:51
在多線(xiàn)程條件下,
理論上,將malloc放入signal的handler也是會(huì )出問(wèn)題的,
鎖是不行的,會(huì )死鎖
引用:原帖由 bluster 于 2007-8-9 10:08 發(fā)表 [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=7177603&ptid=971102]
多線(xiàn)程條件下,signal的handler有可能在一個(gè)單獨的線(xiàn)程中執行,如果這樣那么malloc用鎖保護就夠了。
 
--------------------------------------------------------------------------------
 ypxing 回復于:2007-08-09 16:22:20
試圖測試malloc不可重入性的代碼如下:

main.c
/*這是主程序,用來(lái)調用malloc*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
void setUnblock()
{
  sigset_t sigset;
  sigemptyset(&sigset);
  sigprocmask(SIG_SETMASK, &sigset, NULL);
     
}

void usr1Handler (int signal_number)        /*處理SIGUSR1信號*/
{
  setUnblock(); /*使得SIGUSR1可以被嵌套*/
  free((int*)malloc(sizeof(int)*1000));
  //printf("enter handler\n");
  //getchar();
}
int main ()
{
  int *pi;
  struct sigaction sa;
 
  memset(&sa, 0, sizeof(sa));
  sa.sa_handler = &usr1Handler;
  sigaction(SIGUSR1, &sa, NULL);
  pause();
 
  return 0;
}
 
 

kill.c
/*這個(gè)是用來(lái)發(fā)送SIGUSR1信號的*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc,char *argv[])
{
  int i;
  char killstr[30]="kill -USR1 ";
  if (argc == 2)
  {
    strcat(killstr, argv[1]);
  }
   for (i=0; i<3; i++)
  {
   fork();        /*這樣會(huì )有8個(gè)進(jìn)程同時(shí)發(fā)送*/
  }
 
  while(1)
  {
    system(killstr);
  }
 
  return 0;
}
 

驗證方法是:
1. 編譯main.c 和kill.c
gcc main.c -o main
gcc kill.c -o kill
2. 運行./main
并在另外一個(gè)終端運行ps -A|grep main查找出該進(jìn)程的進(jìn)程號為pid
3. 運行./kill pid (此處pid為第二步查到的pid)
運行了很長(cháng)時(shí)間,也沒(méi)有crash
請大家看看我的程序,討論一個(gè)測試方案出來(lái)
引用:原帖由 ypxing 于 2007-8-8 23:05 發(fā)表 [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=7176529&ptid=971102]
這兩天寫(xiě)了一個(gè)測試程序來(lái)驗證malloc的不可重入性
但是malloc一直沒(méi)有crash,有點(diǎn)郁悶
過(guò)段時(shí)間把自己的測試代碼貼出來(lái),讓大家來(lái)幫忙看看
 
--------------------------------------------------------------------------------
 mingyanguo 回復于:2007-08-09 17:36:23
引用:原帖由 ypxing 于 2007-8-9 16:22 發(fā)表 [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=7180404&ptid=971102]
試圖測試malloc不可重入性的代碼如下:

main.c
/*這是主程序,用來(lái)調用malloc*/
#include 
#include 
#include 
#include 
#include 
#include 
void setUnblock()
{
  sigset_t sigset;
  s ...
我估計是因為現在的malloc是線(xiàn)程安全的原因所以不會(huì )crash但是死鎖。
我在debian上面的一個(gè)測試代碼,會(huì )死鎖,top一下會(huì )發(fā)現進(jìn)程狀態(tài)總是sleep
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#if 0
#define PRINT(a) do { \
 printf a;  \
 fflush(stdout);  \
}while(0)
#else
#define PRINT(a)
#endif
static void
run_malloc(void)
{
 void *mem[8];
 int sz;
 int i;
 for (i = 0; i < (sizeof(mem)/sizeof(mem[0])); i++) {
  sz = random() % (1024 * 1024);
  if (sz <= 0)
   sz = 1024;
  mem = malloc(sz);
  if (mem == NULL) {
   PRINT (("[%d] malloc null...\n", i));
   exit(-1);
  }
  PRINT(("%d\n", i));
  snprintf(mem, sz, "this is a test...");
 }
 for (--i; i >= 0; i--) {
  free(mem);
 }
}
static void
sighandler(int signo)
{
 static void *mem = NULL;
 PRINT ((".\n"));
 if (mem == NULL) {
  mem = malloc(1024);
 } else {
  free(mem);
  mem = NULL;
 }
}
static void
malloc_loop(void)
{
 for (;;)
  run_malloc();
}
static void
signal_loop(pid_t child)
{
 int usec;
 for (;;) {
  kill(child, SIGUSR1);
  usec = ((unsigned int)random()) % 10;
  usleep(usec);
 }
}
int
main(int argc, char **argv)
{
 pid_t child;
 if ((child = fork()) < 0) {
  perror("fork()");
  exit(-1);
 } else if (child == 0) {
  /* child */
  if (signal(SIGUSR1, sighandler) < 0) {
   perror("signal");
   exit(-1);
  }
  malloc_loop();
 } else {
  /* parent */
  signal_loop(child);
 }
 return 0;
}
 
 

--------------------------------------------------------------------------------
 haohao06 回復于:2007-08-10 11:45:06
謝謝樓主講解.收藏先

--------------------------------------------------------------------------------
 system888net 回復于:2008-02-23 12:12:14
頂...

--------------------------------------------------------------------------------
 dxcnjupt 回復于:2008-02-23 19:46:50
不知道這個(gè)理解對不對:
thread-safe和reentrant的區別:在發(fā)生中斷時(shí),高優(yōu)先級代碼搶占,此時(shí)若低優(yōu)先級代碼持有鎖,則高優(yōu)先級代碼會(huì )一直等待鎖打開(kāi),但是低優(yōu)先級代碼失去了調度機會(huì ),于是造成死鎖。thread-safe不考慮這種情況,但是reentrant需要。
實(shí)現reentrant的幾種方法:
1不使用臨界區,把原先的全局/靜態(tài)變量變成函數參數,由函數調用者維護。優(yōu)點(diǎn)是實(shí)現簡(jiǎn)單,缺點(diǎn)是函數功能的封裝性可能會(huì )受到影響。
2在進(jìn)入臨界區之前,關(guān)中斷(屏蔽信號)。優(yōu)點(diǎn)是實(shí)現簡(jiǎn)單,缺點(diǎn)是影響實(shí)時(shí)性能,在多核機器上可能引起瓶頸(幾個(gè)核等待一個(gè)核釋放信號量)。
3嘗試加鎖,無(wú)法加鎖返回一個(gè)出錯值,而不是一直等待下去。缺點(diǎn)是出錯處理比較麻煩
4為一組臨界量開(kāi)啟一個(gè)專(zhuān)門(mén)的線(xiàn)程進(jìn)行處理。優(yōu)點(diǎn)是可以對臨界區的訪(fǎng)問(wèn)按優(yōu)先級排序,以及其它可擴展操作,缺點(diǎn)是性能受到IPC的影響。
5使用lock-free結構取代鎖。缺點(diǎn)是lock-free算法很多都需要memory-copy,影響效率。
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
為何中斷處理程序中不能使用printf?
Linux 線(xiàn)程學(xué)習(一)
可重入函數的概念
Linux多線(xiàn)程編程小結
linux下的C語(yǔ)言開(kāi)發(fā)(多線(xiàn)程編程)
malloc是否是線(xiàn)程安全的?
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久