pthread

xiaoxiao2021-02-28  22

apue中的对pthread_atfork的使用说明: pthread_atfork(void (*prepare)(void),void (*parent)(void), void(*child)(void)) prepare在父进程fork创建子进程之前调用,这里可以获取父进程定义的所有锁; child fork返回之前在子进程环境中调用,在这里unlock prepare获得的锁; parent fork创建了子进程以后,但在fork返回之前在父进程的进程环境中调用的,在这里对prepare获得的锁进行解锁; 1、使用场景 当父进程有多线程时,子进程继承父进程所有的互斥量、读写锁和条件变量的状态,子进程只存在一个线程,它是由父进程中调用fork的线程的副本构成的。如果父进程中的线程占有锁(任一线程),子进程同样占有这些锁。如果父进程马上调用exec,老的地址空间被丢弃,所以锁的状态无关紧要。否则,则要清除锁的状态。 2、猜想 (1)如果子进程并不访问从父进程继承来的互斥量,不使用pthread_atfork是否会影响父进程,子进程的运行? (2)如果子进程也需要访问从父进程继承来的locked互斥量,不使用pthread_atfork是否会影响父进程,子进程的运行? (3)如果子进程主动释放从父进程继承来的互斥量,不使用pthread_atfork是否会影响父进程,子进程的运行? 带着这几个疑问,下面进行了几组实验。 3、验证 实验一:子进程并不访问从父进程继承来的互斥量 (1)执行顺序(“|”代表线程的生命周期): 父进程主线程:|                                                          ,lock, unlock           | 父进程子线程:      |    lock, fork,           ,unlock                                | 子进程主线程:                                |                                                   | (2)结果: 父进程的new thread, 能够正常unlock, 主线程能够正常lock, unlock 不使用pthread_atfork并不会影响父进程,子进程的运行。 (3)代码: 为了简化实验代码,使用了sleep来控制线程之间的同步。 实验二:子进程访问从父进程继承来的locked的互斥量 (1)执行顺序(“|”代表线程的生命周期): 父进程主线程:|                                                                                  | 父进程子线程:    |    lock, fork,           unlock,lock, unlock   | 子进程主线程:                              | run,     lock, unlock        | (2)结果: 父进程中的子线程,能够正常unlock, 但是子进程一直没能够getlock 不使用pthread_atfork并不会影响父进程,但是会影响子进程的运行。 (3)代码: 为了简化实验代码,使用了sleep来控制线程之间的同步。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 void * thr_main ( void * arg ) { printf ( "parent process: new thread start \n " ); pthread_mutex_lock ( & lock ); printf ( "parent process: new thread get lock \n " ); pid_t pid ; if (( pid = fork ()) < 0 ) { perror ( "fork" ); pthread_exit ( 0 ); } else if ( pid == 0 ) // child process { printf ( "child process: start \n " ); printf ( "child process: unlock and get lock \n " ); pthread_mutex_unlock ( & lock ); pthread_mutex_lock ( & lock ); printf ( "child process: exit \n " ); } else // parent process { sleep ( 10 ); pthread_mutex_unlock ( & lock ); printf ( "parent process: new thread unlock \n " ); printf ( "parent process: new thread exit \n " ); } return (( void * ) 0 ); } int main ( void ) { printf ( "parent process: main thread start \n " ); int err = 0 ; pthread_t tid ; err = pthread_create ( & tid , NULL , thr_main , NULL ); if ( err != 0 ) { perror ( "pthread_create" ); exit ( 1 ); } sleep ( 50 ); printf ( "parent process: main thread exit \n " ); return 0 ; }
 来自CODE的代码片 snippet_file_0.c
实验三:子进程主动释放从父进程继承来的互斥量 (1)执行顺序(“|”代表线程的生命周期): 父进程主线程:|                                                                                    | 父进程子线程:    |    lock, fork,                                    , unlock   | 子进程主线程:                              | run,  unlock, lock   | (2)结果: 父子进程都能够正常运行。 (3)代码: 为了简化实验代码,使用了sleep来控制线程之间的同步。 4、进一步思考 既然,子进程中主动释放锁能够起到跟pthread_atfork一样的效果,相比而言,pthread_atfork有些什么好处呢? 有可能是为了更好的管理代码,使用pthread_atfork,只需要处理自己写的代码;而前者需要做统一的管理,容易出现遗漏; 5、更进一步思考 第三方库(如libc库),如果大量使用了锁(如malloc),但是库并没有使用pthread_atfork来注册清理函数,则我们需要谨慎在多线程中使用fork。
转载请注明原文地址: https://www.6miu.com/read-1000284.html

最新回复(0)