我正在遵循关于pthread
和fork
的指南,但我对以下代码的工作方式感到困惑。以下代码来自https://github.com/angrave/SystemProgramming/wiki/Pthreads%2C-第2部分%3A在实践中的应用
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
static pid_t child = -2;
void *sleepnprint(void *arg) {
printf("%d:%s starting up...n", getpid(), (char *) arg);
while (child == -2) {sleep(1);} /* Later we will use condition variables */
printf("%d:%s finishing...n",getpid(), (char*)arg);
return NULL;
}
int main() {
pthread_t tid1, tid2;
pthread_create(&tid1,NULL, sleepnprint, "New Thread One");
pthread_create(&tid2,NULL, sleepnprint, "New Thread Two");
child = fork();
printf("%d:%sn",getpid(), "fork()ing complete");
sleep(3);
printf("%d:%sn",getpid(), "Main thread finished");
pthread_exit(NULL);
return 0; /* Never executes */
}
8970:New Thread One starting up...
8970:fork()ing complete
8973:fork()ing complete
8970:New Thread Two starting up...
8970:New Thread Two finishing...
8970:New Thread One finishing...
8970:Main thread finished
8973:Main thread finished
- 8970是父进程吗
- 从网站上看,它说孩子只有一个线程,那么这是否意味着孩子进程不去
sleepnprint
函数 - 为什么
8970:fork()ing complete
8973:fork()ing complete
在8970:New Thread Two starting up...
之前打印?线程和进程的顺序是随机的吗
主线程(main((函数(使用pthread_create((创建两个线程,但由于它们是线程,所以它们是同一进程的一部分(getpid((为主线程和次线程返回8970(。如果您想要任务标识符,请在线程入口点调用gettid(((您将分别获得8971和8972(。
然后,父进程分叉,父进程和子进程都在main((函数中继续。它们分别显示它们的pid:8970和8973。
当一个多线程进程分叉时,只有调用线程是"叉";"再现";在子进程中(父进程的其他线程没有分叉:子进程是单线程的,直到它在自己一侧创建新线程为止(。因此,在您的示例中,编号为8973的子进程没有在父进程(编号为8970(中创建的两个线程。
是的,所有线程和进程都是并行运行的(按任何顺序(。
为了说明前面的内容,这里有一个稍微增强的程序版本:
#define _GNU_SOURCE // To get gettid()
#include <pthread.h>
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
static volatile pid_t child = -2;
void *sleepnprint(void *arg)
{
printf("Process %d, Task %d:%s starting up...n", getpid(), gettid(), (char *) arg);
// This is not the best way to synchronize threads but this works here:
// once the main thread returns from fork(), child = pid of child process
// (i.e. != -2)
while (child == -2) {sleep(1);} /* Later we will use condition variables */
printf("Process %d, Task %d:%s finishing...n", getpid(), gettid(), (char*)arg);
return NULL;
}
int main() {
pthread_t tid1, tid2;
pthread_create(&tid1,NULL, sleepnprint, "New Thread One");
pthread_create(&tid2,NULL, sleepnprint, "New Thread Two");
child = fork();
// In father process: child = child process pid
// In child process: child = 0
if (child == 0) {
// This is the child process
printf("%d:%sn",getpid(), "Child process finished");
exit(0);
}
// Father process
printf("%d:%sn",getpid(), "fork()ing complete");
sleep(3);
printf("%d:%sn",getpid(), "Main thread finished");
pthread_exit(NULL);
return 0; /* Never executes */
}
编译和执行:
$ gcc example.c -l pthread
$ ./a.out
Process 6141, Task 6142:New Thread One starting up...
Process 6141, Task 6142:New Thread One finishing...
Process 6141, Task 6143:New Thread Two starting up...
Process 6141, Task 6143:New Thread Two finishing...
6144:Child process finished
6141:fork()ing complete
6141:Main thread finished