如何加入其中有分叉的线程?

How to join a thread which have fork in it?

情况如下

{
    ...
    pthread_create(thread_id, NULL, thread_fun, NULL);
    pthread_join(thread_id, NULL);
    ...
}
void * thread_fun(void * arg)
{
    if(fork())
    {
        printf("In Parent\n");
        pthread_exit(NULL);
    }
    else
    {
         printf("In Child\n");
         pthread_exit(NULL);
    }
}

如何使用 pthread_join() 以便我可以在线程中等待子进程和父进程?

将所有线程置于无限循环中,然后使用pstophtop或类似工具检查整个程序状态。你会发现子进程只有一个线程,而父进程有(至少)两个。

现在,关于你的问题如何使用pthread_join()等待子进程,你根本做不到,因为你只能用它来等待同一个进程中的线程。您可以等待子进程终止 (waitpid())。

如果以上没有回答你的问题(有点不清楚,因为你想"wait for both child and parent process",这是我想知道从哪个进程的上下文)退后一步并描述更高将你想要达到的目标水平。换句话说,这可能是所谓的"XY Problem"。对那个术语做一点研究,无论如何学习和理解都是一件好事。

基本上有两种方法可以做到这一点。您可以让子线程在退出之前等待子进程,或者您可以将子进程的 PID 传递给父线程,以便它可以等待。这是第一种方法:

#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

void *thread_fun(void *arg);

int main(void) {
    pthread_t thread;
    pthread_create(&thread, NULL, thread_fun, NULL);
    pthread_join(thread, NULL);
    return 0;
}

void *thread_fun(void *arg) {
    pid_t pid = fork();
    if(pid) {
        printf("In Parent\n");
        waitpid(pid, NULL, 0);
        pthread_exit(NULL);
    } else {
        printf("In Child\n");
        exit(0);
    }
}

这是第二个:

#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>

struct locked_pid {
    sem_t sem;
    pid_t pid;
};

void *thread_fun(void *arg);

int main(void) {
    pthread_t thread;
    struct locked_pid s;
    sem_init(&s.sem, 0, 0);
    pthread_create(&thread, NULL, thread_fun, &s);
    sem_wait(&s.sem);
    waitpid(s.pid, NULL, 0);
    pthread_join(thread, NULL);
    sem_destroy(&s.sem);
    return 0;
}

void *thread_fun(void *arg) {
    pid_t pid = fork();
    if(pid) {
        struct locked_pid *s = arg;
        s->pid = pid;
        sem_post(&s->sem);
        printf("In Parent\n");
        pthread_exit(NULL);
    } else {
        printf("In Child\n");
        exit(0);
    }
}

请注意,第一个比第二个简单得多。这是因为在第二种情况下,您需要一个信号量,以便父进程知道何时写入子 PID。

顺便说一下,在将此代码用于任何重要的事情之前,您应该了解以下两点:

  1. 它没有任何错误检查,即使它使用的大部分功能都可能失败。
  2. POSIX says "If a multi-threaded process calls fork() ... the child process may only execute async-signal-safe operations until such time as one of the exec 函数被调用。”这意味着你不应该做 printf("In Child\n");.