[ 永遠的UNIX::UNIX技術資料的寶庫 ]   GB | BIG5

首頁 > 編程技術 > C/C++ > 正文
Solaris2.4 多線程編程指南5--安全和不安全的接口函數
本文出自:BBS水木清華站 作者:Mccartney (coolcat) (2002-01-29 20:32:05)
5. 安全和不安全的接口

本章定義了函數和庫的多線程安全等級。
線程安全
多線程接口安全等級
異步安全函數
庫的多線程安全等級

5.1線程安全

線程安全是為了避免數據競爭--數據設置的正確性依賴多個線程修改數據的順序。
如果不需要共享,則給每個線程分配一個私有的數據拷貝。如果數據必須共享,一定要用同步機制來保証操作的唯一性。
如果一個線程在幾個線程同時執行時在邏輯上是正..的。在一個實際的水平上,把安全等級劃分為3層比較方便。
﹒ 不安全
﹒ 線程安全--非並行
﹒ 線程安全--多線程安全
一個不安全的過程可以用在操作前加互斥鎖,操作解互斥鎖的辦法來使操作序列化(即消除並發)。示例5-1首先顯示了一個簡化的fputs()的非線程安全實現。
接下來是用單互斥鎖保護使操作序列化的版本。實際上,使用了比需要的更強的同步。如果兩個線程調用fputs()來打印到不同的文件時,其中一個用不著等待另一個--它們可以同時操作。
最一個版本是多線程安全版。它給每個文件加一個鎖,允許兩個線程同時指向不同的文件。所以,MT-SAFE(即多線程安全)的函數是線程安全的,並不會使運行性能變壞。

Code Example 5-1 線程安全的程度
/*not thread-safe */
fputs(const char *s, FILE *stream){
char *p;
for(p=s; *p; p++)
putc((int)*p,stream);
}
/*serializable*/
fputs(const char *s,FILE *stream){
static mutex_t mut;
char *p;
mutex_lock(&m);
for(p=s;*p;p++)
putc((int)*p,stream);
mutex_unlock(&m);
}
/*MT-SAFE*/
mutex_t m[NFILE];
fputs(const char *s, FILE *stream){
static mutex_t mut;
char *p;
mutex_lock(&m[fileno(stream)]);
for (p=s;*p;p++)
putc((int)*p,stream);
mutex_unlock(&m[fileno(stream)]);
}

5.2多線程接口安全等級

man page(3):庫函數用下面的分類來描述一個接口支持多線程到什程度(這些分類在Intro(3) man page中解釋地更為詳細)。
Safe 可以被多線程應用程序調用
Safe with exceptions 例外的部分請參見NOTES部分
Unsafe 這個接口只有在應用程序保証一個時刻只有一個線程執行時才
能安全調用
MT-Safe 完全為多線程設計,不但安全,還支持一些並發性
MT-Safe with exceptions 例外的部分請參見NOTES部分
Async-Safe 可以被一個信號控制器安全調用。一個線程在執行Async-Safe函數時被信號中斷將不會產生死鎖。
有關safe接口請看附錄B的表"MT Safety Levels:Library Interfaces.", 它來自man pages(3)。如果一個第三部分的接口不在表內,它就有可能是不 安全的(不包括源兼容庫Source Compatibility Library)。檢查man page才 能確定。
在"man pages(2):系統調用"中描述的所有函數,除了vfork(2)外都是MT-Safe的。
一些函數有意地不作成安全,因為如下原因。
對單線程的應用程序,MT-Safe回在一定程度上降低性能。
函數本身有一個不安全接口。例如,一個函數會返回一個指向堆棧緩沖區的指針。你可以用這些函數"再進入"的對等函數???(原文為
reentrant counterparts)。再進入函數的名字是原函數加"_r"綴。
-------------------------------------
注意--除非通過查詢手冊頁(man pages),否則無法確定一個不以"_r"結尾的 函數是否MT-safe。非MT-safe的函數一定要有同步機制的保護,或者被限制在 初始線程裡。
------------------------------------

*非安全接口的替代(重入 Reentrant)函數

對大多數非安全接口的函數,都存在一個MT-safe的版本。新的MT-safe函數一般是舊的非安全函數加上"_r"綴。Solaris系統提供以下的"_r"函數。

Table 5-1 替代函數
asctime_r(3C) ctermid_r(3S) ctime_r(3C)
fgetgrent_r(3C) fgetpwent_r(3C) fgetspent_r(3C)
Gamma_r(3M) getgrgid_r(3C) getgrnam_r(3C)
getlogin_r(3C) getpwnam_r(3C) getpwuid_r(3C)
getgrent_r(3C) gethostbyaddr_r(3N) gethostbyname_r(3N)
gethostent_r(3N) getnetbyaddr_r(3N) getnetbyname_r(3N)
getnetent_r(3N) Getprotobyname_r(3N) getprotobynumber_r(3N)
getprotoent_r(3N) getpwent_r(3C) getrpcbyname_r(3N)
getrpcbynumber_r(3N) getrpcent_r(3N) getservbyname_r(3N)
getservbyport_r(3N) getservent_r(3N) getspent_r(3C)
getspnam_r(3C) gmtime_r(3C) lgamma_r(3M)
localtime_(3C)r nis_sperror_r(3N) rand_r(3C)
readdir_r(3C) strtok_r(3C) tmpnam_r(3C)
ttyname_r(3C)

5.3異步安全函數

可以被信號控制器安全調用的函數被稱為Async-Safe的。POSIX標準定義並 詳列了異步安全函數(IEEE Std 1003.1-1990.3.3.1.3(3)(f), page 55)。除 了POSIX異步安全函數外,下列三個函數也是異步安全的。
﹒ sema_post(3T)
﹒ thr_sigsetmask(3T)
﹒ thr_kill(3T)

5.4庫的多線程安全等級

所有可能被多線程程序的線程調用的函數都應當是MT-Safe的。
這意味著過程可以同時正確地執行兩個操作。所以,每一個被多線程程序使用的接口都應是MT-Safe。
並不是所有的庫都是MT-Safe的。通常被使用的MT-Safe的庫詳列表5-2中。其他的庫也將最終被改寫成MT-Safe的。
表5-2 一些MT-Safe庫
------------------------------------
庫 說明
------------------------------------
lib/libc getXXbyYY接口(例如gethostbyname(3N))是MT-Safe的
lib/libdl_stubs (支持static switch compiling)
lib/libintl
lib/libm 僅當為共享庫編譯時是MT-Safe的,但與文檔庫連接時
不是MT-Safe的
lib/libmalloc
lib/libmapmalloc
lib/libnsl 包括TLI接口,XDR,RPC客戶方和服務方,netdir和
netselect。 GetXXbyYY是不安全的,但有線程安全版本
GetXXbyYY_r
lib/libresolv 支持因線程而異的錯誤碼
lib/libsocket
lib/libw
lib/nametoaddr
lib/nametoaddr
lib/nsswitch
libX11
libC (不是Solaris系統的部分;可以分開購買)
------------------------------------

*不安全庫

如果庫中的函數不是MT-Safe的,則只有在一個線程的調用時才是安全的。 (http://www.fanqiang.com)
    進入【UNIX論壇

相關文章
Solaris2.4 多線程編程指南7--編程指南 (2002-01-29 20:33:46)
Solaris2.4 多線程編程指南6--編譯和調試 (2002-01-29 20:32:52)
Solaris2.4 多線程編程指南5--安全和不安全的接口函數 (2002-01-29 20:32:05)
Solaris2.4 多線程編程指南4--操作系統編程 (2002-01-29 20:29:36)
Solaris2.4 多線程編程指南3--使用同步對象編程 (2002-01-29 20:28:07)
Solaris2.4 多線程編程指南2--用多線程編程 (2002-01-29 20:26:32)
Solaris2.4 多線程編程指南1--線程基礎 (2002-01-29 20:25:25)
Linux下的多線程編程 (2001-08-11 09:05:00)
 

★  樊強制作 歡迎分享  ★