# 12.7.3 在线程化的程序中使用已存在的库函数

大多数 Linux 函数,包括定义在标准 C 库中的函数(例如 mallocfreereallocprintfscanf)都是线程安全的,只有一小部分是例外。图 12-41 列出了常见的例外。(参考 [110] 可以得到一个完整的列表。)strtok 函数是一个已弃用的(不推荐使用)函数。asctimectimelocaltime 函数是在不同时间和数据格式间相互来回转换时经常使用的函数。gethostbynamegethostbyaddrinet_ntoa 函数是已弃用的网络编程函数,已经分别被可重入的 getaddrinfogetnameinfoinet_ntop 函数取代(见第 11 章)。除了 randstrtok 以外,所有这些线程不安全函数都是第 3 类的,它们返回一个指向静态变量的指针。如果我们需要在一个线程化的程序中调用这些函数中的某一个,对调用者来说最不惹麻烦的方法是加锁-复制。然而,加锁-复制方法有许多缺点。首先,额外的同步降低了程序的速度。第二,像 gethostbyname 这样的函数返回指向复杂结构的结构的指针,要复制整个结构层次,需要深层复制 (deep copy) 结构。第三,加锁-复制方法对像 rand 这样依赖跨越调用的静态状态的第 2 类函数并不有效。

线程不安全函数 线程不安全类 Linux 线程安全版本
rand 2 rand_r
strtok 2 strtok_r
asctime 3 asctime_r
ctime 3 ctime_r
gethostbyaddr 3 gethostbyaddr_r
gethostbyname 3 gethostbyname_r
inet_ntoa 3 (无)
localtime 3 localtime_r

图 12-41 常见的线程不安全的库函数

因此,Linux 系统提供大多数线程不安全函数的可重入版本。可重入版本的名字总是以“_r”后缀结尾。例如,asctime 的可重入版本就叫做 asctime_r。我们建议尽可能地使用这些函数。