Skip to content

Files

Latest commit

b9246b1 · May 10, 2020

History

History
83 lines (53 loc) · 4.56 KB

26.md

File metadata and controls

83 lines (53 loc) · 4.56 KB

Pthreads,第 1 部分:简介

原文:https://github.com/angrave/SystemProgramming/wiki/Pthreads%2C-Part-1%3A-Introduction

线程简介

什么是线程?

线程是“执行线程”的缩写。它表示 CPU 具有(并将执行)的指令序列。要记住如何从函数调用返回,并存储自动变量和参数的值,线程使用栈。

什么是轻量级过程(LWP)?它与线程有什么关系?

好吧,对于所有意图和目的,线程是一个过程(意味着创建一个线程类似于fork),除了没有复制意味着没有写入副本。这允许进程共享相同的地址空间,变量,堆,文件描述符等。

创建线程的实际系统调用类似于fork;这是clone。我们不会详细说明,但您可以阅读手册页,请记住它不在本课程的直接范围内。

LWP 或线程更倾向于分配许多场景,因为创建它们的开销要少得多。但在某些情况下(特别是 python 使用它)多处理是使代码更快的方法。

线程的栈如何工作?

您的主要功能(以及您可能调用的其他功能)具有自动变量。我们将使用栈将它们存储在内存中,并使用简单的指针(“栈指针”)跟踪栈的大小。如果线程调用另一个函数,我们将栈指针向下移动,这样我们就有更多的空间用于参数和自动变量。一旦从函数返回,我们就可以将栈指针移回其先前的值。我们保留旧栈指针值的副本 - 在栈上!这就是为什么从函数返回非常快 - 很容易“释放”自动变量使用的内存 - 我们只需要更改栈指针。

在多线程程序中,有多个栈但只有一个地址空间。 pthread 库分配一些栈空间(在堆中或使用主程序栈的一部分)并使用clone函数调用在该栈地址处启动线程。总地址空间可能看起来像这样。

我的进程可以有多少个线程?

您可以在进程内运行多个线程。你免费得到第一个帖子!它运行你在'main'中编写的代码。如果需要更多线程,可以使用 pthread 库调用pthread_create创建新线程。您需要将指针传递给函数,以便线程知道从哪里开始。

您创建的线程都存在于同一个虚拟内存中,因为它们是同一进程的一部分。因此,他们都可以看到堆,全局变量和程序代码等。因此,您可以在同一个进程内同时处理两个(或多个)CPU。由操作系统决定将线程分配给 CPU。如果你有比 CPU 更多的活动线程,那么内核会将线程分配给 CPU 很短的时间(或直到它用完了要做的事情),然后自动切换 CPU 在另一个线程上工作。例如,一个 CPU 可能正在处理游戏 AI 而另一个线程正在计算图形输出。

简单用法

你好世界 pthread 的例子

要使用 pthread,您需要包含pthread.h并且需要使用-pthread(或-lpthread)编译器选项进行编译。此选项告诉编译器您的程序需要线程支持

要创建线程,请使用函数pthread_create。这个函数有四个参数:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                   void *(*start_routine) (void *), void *arg);
  • 第一个是指向一个变量的指针,该变量将保存新创建的线程的 id。
  • 第二个是指向属性的指针,我们可以使用它来调整和调整 pthreads 的一些高级功能。
  • 第三个是指向我们想要运行的函数的指针
  • 第四个是指向我们的函数的指针

论点void *(*start_routine) (void *)很难读懂!它表示一个指针,它接受一个void *指针并返回一个void *指针。它看起来像一个函数声明,除了函数的名称用(* .... )包装

这是最简单的例子:

#include <stdio.h>
#include <pthread.h>
// remember to set compilation option -pthread

void *busy(void *ptr) {
// ptr will point to "Hi"
    puts("Hello World");
    return NULL;
}
int main() {
    pthread_t id;
    pthread_create(&id, NULL, busy, "Hi");
    while (1) {} // Loop forever
}

如果我们想等待我们的线程完成使用pthread_join

void *result;
pthread_join(id, &result);

在上面的例子中,result将是null,因为 busy 函数返回null。我们需要传递结果地址,因为pthread_join将写入指针的内容。

Pthreads 第 2 部分