gethostbyname() 进程即使在不同的线程中也能一致地解析吗?

Ole*_*g G 2 c linux multithreading gethostbyname

我通过不同线程的 gethostbyname() 进行了 DNS 解析实验。我关闭了网络链接并运行了下面的程序。输出是这样的

gethostbyname 开始于 1411234734
gethostbyname 开始于 1411234734
gethostbyname 开始于 1411234734
gethostbyname 完成于 1411234774
gethostbyname 完成于 1411234814
gethostbyname 完成于 1411234854

gethostbyname() 同时开始,但在 40 秒超时后一一完成。

然后我尝试了 getaddrinfo()。看起来这个函数没有遇到这个问题

getaddrinfo 开始于 1411235759
getaddrinfo 开始于 1411235759
getaddrinfo 开始于 1411235759
getaddrinfo 完成于 1411235799
getaddrinfo 完成于 1411235799
getaddrinfo 完成于 1411235799

那么,为什么我得到这个结果,这种行为是否仅针对 Linux?

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <time.h>
#include <pthread.h>

void *resolve_ghbn(void *host) {
    printf("gethostbyname started at %d\n", time(NULL));
    struct hostent *rslv = gethostbyname((char*)host);
    printf("gethostbyname finished at %d\n", time(NULL));

    return NULL;
}

void *resolve_gai(void *host) {
    struct addrinfo *result;
    printf("getaddrinfo started at %d\n", time(NULL));
    int res = getaddrinfo(host, NULL, NULL, &result);
    printf("getaddrinfo finished at %d\n", time(NULL));
    if (res == 0)
        freeaddrinfo(result);

    return NULL;
}

int main() {
    char *domains[] = {"google.com", "google.cy", "google.us"};
    pthread_t threads[3];
    int i;

    for (i=0; i<3; i++) {
        pthread_create(&threads[i], NULL, resolve_ghbn, domains[i]);
    }

    void *retval;

    for (i=0; i<3; i++) {
        pthread_join(threads[i], &retval);
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Pav*_*rda 5

getaddrinfo()函数不共享任何全局/静态变量,因此是可重入的,因此是线程安全的。它返回使用分配的内存中的结果malloc(),用户负责使用,freeaddrinfo()然后使用它free()来分配数据。因此,您可以getaddrinfo()从多个线程同时运行,并且各个实例并行运行。

另一方面,gethostbyname()返回指向全局/静态数据的指针,因此不可重入。用户不负责释放数据。因此,不允许您从多个线程同时运行gethostbyname()。根据您的测试,GNU C 库显然会序列化调用以避免并行运行导致的错误。

你通常应该避免使用 using ,gethostbyname()因为它已经被淘汰了getaddrinfo(),但后者并不是一个完美的替代品,至少在 glibc 中是这样。我建议getaddrinfo()在适当的情况下使用并采用解决方法来解决其错误。

您可以通过检查源代码了解更多信息。