zoukankan      html  css  js  c++  java
  • fork安全的gettid高效实现

    进程有id,可以通过getpid()获得,线程也有id,但是glibc没有提供封装。需要自己发出系统调用。在关键路径,系统调用还是对性能有影响的。因此我们可以想到类似glibc对getpid做的cache化封装,用thread local的方式缓存每个线程的id,每个线程只有第一次调用gettid时才真正发起系统调用。

    #include <stdio.h>
    #include <syscall.h>
    #include <unistd.h>
    
    pid_t gettid() {
        static __thread pid_t cached_tid;
        if (cached_tid == 0) {
            cached_tid = syscall(SYS_gettid);
        }
        return cached_tid;
    }

    这段代码运行的很好,直到遇到fork。在我看来,fork是单线程时代的东西,与多线程格格不入,所以我们的代码中很少用到。其实这个问题除了对调用fork的线程来说是诡异的,因为fork时,其他线程是不会被fork的。但是对于主线程或者单线程程序,这个问题也还是存在的,存在就不爽。

    或许可以想到用pthread_atfork来做这个事情,其原型是这样的。

    int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void));

    文档说,child会在子进程中被调用。但是这里有个问题,cached_tid是线程局部变量,每个线程里的地址是不一样的,而child函数不支持传地址,难道我们要用动态生成代码(thunk)的猥琐方式?

    其实不必那么复杂,虽然glibc缓存了getpid,但是fork后getpid是会变的,因此我们可以在每次调用时再多比较一下pid是否发生了变化:

    pid_t gettid() {
        static __thread pid_t cached_pid;
        static __thread pid_t cached_tid;
        pid_t pid = getpid();
        if (cached_pid != pid || cached_tid == 0) {
            cached_pid == pid;
            cached_tid = syscall(SYS_gettid);
        }
        return cached_tid;
    }

    getpid是高效的,因此这段代码也是高校的。

    查阅glibc的源代码,getpid是从当前线程控制块里读取的,其实里面也有线程id,但是glibc却迟迟不肯提供封装,让我想起了一句话,程序员何苦为难程序员。

    测一下:

    int main() {
        printf("Parent: pid=%d, tid=%d
    ", getpid(), gettid());
        if (fork() == 0) {
            printf("Child: pid=%d, tid=%d
    ", getpid(), gettid());
        } else {
            printf("Parent after fork: pid=%d, tid=%d
    ", getpid(), gettid());
        }
    }

    Parent: pid=10776, tid=10776
    Parent after fork: pid=10776, tid=10776
    Child: pid=10777, tid=10777

    行为符合预期。

  • 相关阅读:
    self 和 super 关键字
    NSString类
    函数和对象方法的区别
    求两个数是否互质及最大公约数
    TJU Problem 1644 Reverse Text
    TJU Problem 2520 Quicksum
    TJU Problem 2101 Bullseye
    TJU Problem 2548 Celebrity jeopardy
    poj 2586 Y2K Accounting Bug
    poj 2109 Power of Cryptography
  • 原文地址:https://www.cnblogs.com/chen3feng/p/4139730.html
Copyright © 2011-2022 走看看