pthread_create(3) Linux 手册页:

man7.org > Linux > man-pages
Linux/UNIX 系统编程培训
pthread_create(3) — Linux 手册页

名称 (NAME) | 库 (LIBRARY) | 概要 (SYNOPSIS) | 描述 (DESCRIPTION) | 返回值 (RETURN VALUE) | 错误 (ERRORS) | 属性 (ATTRIBUTES) | 标准 (STANDARDS) | 历史 (HISTORY) | 注解 (NOTES) | 缺陷 (BUGS) | 示例 (EXAMPLES) | 参见 (SEE ALSO) | 跋 (COLOPHON)


名称 (NAME)

pthread_create - 创建一个新线程

库 (LIBRARY)

POSIX 线程库 (libpthread, -lpthread)

概要 (SYNOPSIS)

#include <pthread.h>

int pthread_create(pthread_t *restrict thread,
                   const pthread_attr_t *_Nullable restrict attr,
                   typeof(void *(void *_Nullable)) *start_routine,
                   void *_Nullable restrict arg);

描述 (DESCRIPTION)

pthread_create() 函数在调用它的进程中启动一个新线程。新线程通过调用 start_routine() 函数开始执行;arg 作为唯一参数传递给 start_routine()

新线程将以下列方式之一终止:

  • 它调用 pthread_exit(3),并指定一个退出状态值。同一进程中调用 pthread_join(3) 的另一个线程可以获取此值。
  • 它从 start_routine() 中返回。这等同于使用 return 语句中提供的值来调用 pthread_exit(3)
  • 它被取消(参见 pthread_cancel(3))。
  • 进程中的任何线程调用了 exit(3),或者主线程从 main() 中返回。这会导致进程中的所有线程终止。

attr 参数指向一个 pthread_attr_t 结构体,该结构体的内容在创建线程时用于决定新线程的属性;此结构体使用 pthread_attr_init(3) 及相关函数进行初始化。如果 attr 为 NULL,则使用默认属性创建线程。

在成功返回之前,pthread_create() 会将新线程的 ID 存储在由 thread 指向的缓冲区中;此标识符在后续调用其他 pthreads 函数时用于指代该线程。

新线程会继承创建它的线程的信号掩码副本 (pthread_sigmask(3))。新线程的挂起信号集为空 (sigpending(2))。新线程不会继承创建者的备用信号栈 (sigaltstack(2))。

新线程会继承调用线程的浮点环境 (fenv(3))。

新线程的 CPU 时间时钟初始值为 0(参见 pthread_getcpuclockid(3))。

Linux 专有细节

新线程继承调用线程的权能集合(capability sets,参见 capabilities(7))和 CPU 亲和力掩码(CPU affinity mask,参见 sched_setaffinity(2))的副本。

返回值 (RETURN VALUE)

成功时,pthread_create() 返回 0;出错时,它返回一个错误编号(error number),并且 *thread 的内容处于未定义状态。

错误 (ERRORS)

  • EAGAIN:系统资源不足,无法创建另一个线程。
  • EAGAIN:遇到了系统对线程数量施加的限制。可能触发此错误的限制包括:达到了由 setrlimit(2) 设置的实际用户 ID 所能拥有的进程和线程数的软限制 (RLIMIT_NPROC);达到了内核系统级最大进程和线程数限制 /proc/sys/kernel/threads-max(参见 proc(5));或达到了 PID 的最大数量限制 /proc/sys/kernel/pid_max(参见 proc(5))。
  • EINVALattr 中的设置无效。
  • EPERM:没有权限设置 attr 中指定的调度策略和参数。

属性 (ATTRIBUTES)

有关本节中使用的术语解释,请参见 attributes(7)

接口 属性
pthread_create() 线程安全性 (Thread safety) MT-Safe (多线程安全)

标准 (STANDARDS)

POSIX.1-2008.

历史 (HISTORY)

POSIX.1-2001.

注解 (NOTES)

有关 pthread_create() 返回在 *thread 中的线程 ID 的进一步信息,请参见 pthread_self(3)。除非使用了实时调度策略,否则在调用 pthread_create() 之后,接下来哪个线程(是调用者还是新线程)将被执行是不确定的。

线程可以是可连接的 (joinable)分离的 (detached)。如果一个线程是可连接的,那么另一个线程可以调用 pthread_join(3) 来等待该线程终止并获取其退出状态。只有当已终止的可连接线程被连接 (joined) 后,其最后剩下的系统资源才会被释放回系统。当一个分离的线程终止时,其资源会自动释放回系统:无法连接分离的线程来获取其退出状态。将线程设为分离状态对于某些后台守护 (daemon) 线程非常有用,因为应用程序不需要关心它们的退出状态。默认情况下,新线程是在可连接状态下创建的,除非 attr 被设置为在分离状态下创建线程(使用 pthread_attr_setdetachstate(3))。

在 NPTL 线程实现下,如果在程序启动时 RLIMIT_STACK 软资源限制的任何值非 “unlimited”(无限制),那么它将决定新线程的默认栈大小。通过使用 pthread_attr_setstacksize(3),可以在用于创建线程的 attr 参数中显式设置栈大小属性,以获得不同于默认值的栈大小。如果 RLIMIT_STACK 资源限制被设置为 “unlimited”,则会使用特定于架构的值作为栈大小:大多数架构为 2 MB;POWER 和 Sparc-64 架构为 4 MB。

缺陷 (BUGS)

在已废弃的 LinuxThreads 实现中,同一个进程中的每个线程都有不同的进程 ID。这违反了 POSIX 线程规范,也是该实现中许多其他不符合标准问题的根源;参见 pthreads(7)

示例 (EXAMPLES)

下面的程序演示了 pthread_create() 以及 pthreads API 中一些其他函数的使用方法。

在以下运行示例中(在提供 NPTL 线程实现的系统上),栈大小默认为 “stack size” (栈大小) 资源限制所给定的值:

$ ulimit -s
8192            # 栈大小限制为 8 MB (0x800000 字节)
$ ./a.out hola salut servus
Thread 1: top of stack near 0xb7dd03b8; argv_string=hola
Thread 2: top of stack near 0xb75cf3b8; argv_string=salut
Thread 3: top of stack near 0xb6dce3b8; argv_string=servus
Joined with thread 1; returned value was HOLA
Joined with thread 2; returned value was SALUT
Joined with thread 3; returned value was SERVUS

在下一次运行中,程序显式地为创建的线程设置了 1 MB 的栈大小(使用 pthread_attr_setstacksize(3)):

$ ./a.out -s 0x100000 hola salut servus
Thread 1: top of stack near 0xb7d723b8; argv_string=hola
Thread 2: top of stack near 0xb7c713b8; argv_string=salut
Thread 3: top of stack near 0xb7b703b8; argv_string=servus
Joined with thread 1; returned value was HOLA
Joined with thread 2; returned value was SALUT
Joined with thread 3; returned value was SERVUS

程序源码

#include <ctype.h>
#include <err.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

struct thread_info {    /* 用于作为 thread_start() 的参数 */
    pthread_t thread_id;        /* 由 pthread_create() 返回的 ID */
    int       thread_num;       /* 应用程序定义的线程编号 */
    char     *argv_string;      /* 来源于命令行参数 */
};

/* 线程启动函数:显示栈顶附近的地址,
   并返回 argv_string 的大写副本。 */

static void *
thread_start(void *arg)
{
    struct thread_info *tinfo = arg;
    char *uargv;

    printf("Thread %d: top of stack near %p; argv_string=%s\n",
           tinfo->thread_num, (void *) &tinfo, tinfo->argv_string);

    uargv = strdup(tinfo->argv_string);
    if (uargv == NULL)
        err(EXIT_FAILURE, "strdup");

    for (char *p = uargv; *p != '\0'; p++)
        *p = toupper(*p);

    return uargv;
}

int
main(int argc, char *argv[])
{
    int                 s, opt;
    void                *res;
    size_t              num_threads;
    ssize_t             stack_size;
    pthread_attr_t      attr;
    struct thread_info  *tinfo;

    /* "-s" 选项为我们的线程指定栈大小。 */

    stack_size = -1;
    while ((opt = getopt(argc, argv, "s:")) != -1) {
        switch (opt) {
        case 's':
            stack_size = strtoul(optarg, NULL, 0);
            break;

        default:
            fprintf(stderr, "Usage: %s [-s stack-size] arg...\n",
                    argv[0]);
            exit(EXIT_FAILURE);
        }
    }

    num_threads = argc - optind;

    /* 初始化线程创建属性。 */

    s = pthread_attr_init(&attr);
    if (s != 0)
        errc(EXIT_FAILURE, s, "pthread_attr_init");

    if (stack_size > 0) {
        s = pthread_attr_setstacksize(&attr, stack_size);
        if (s != 0)
            errc(EXIT_FAILURE, s, "pthread_attr_setstacksize");
    }

    /* 为 pthread_create() 的参数分配内存。 */

    tinfo = calloc(num_threads, sizeof(*tinfo));
    if (tinfo == NULL)
        err(EXIT_FAILURE, "calloc");

    /* 为每个命令行参数创建一个线程。 */

    for (size_t tnum = 0; tnum < num_threads; tnum++) {
        tinfo[tnum].thread_num = tnum + 1;
        tinfo[tnum].argv_string = argv[optind + tnum];

        /* pthread_create() 调用将线程 ID 存储到对应的 tinfo[] 元素中。 */

        s = pthread_create(&tinfo[tnum].thread_id, &attr,
                           &thread_start, &tinfo[tnum]);
        if (s != 0)
            errc(EXIT_FAILURE, s, "pthread_create");
    }

    /* 销毁线程属性对象,因为它不再需要了。 */

    s = pthread_attr_destroy(&attr);
    if (s != 0)
        errc(EXIT_FAILURE, s, "pthread_attr_destroy");

    /* 现在连接 (join) 每个线程,并显示其返回值。 */

    for (size_t tnum = 0; tnum < num_threads; tnum++) {
        s = pthread_join(tinfo[tnum].thread_id, &res);
        if (s != 0)
            errc(EXIT_FAILURE, s, "pthread_join");

        printf("Joined with thread %d; returned value was %s\n",
               tinfo[tnum].thread_num, (char *) res);
        free(res);      /* 释放由线程分配的内存 */
    }

    free(tinfo);
    exit(EXIT_SUCCESS);
}

参见 (SEE ALSO)

getrlimit(2), pthread_attr_init(3), pthread_cancel(3), pthread_detach(3), pthread_equal(3), pthread_exit(3), pthread_getattr_np(3), pthread_join(3), pthread_self(3), pthread_setattr_default_np(3), pthreads(7)

跋 (COLOPHON)

本页面是 man-pages(Linux 内核与 C 库用户空间接口文档)项目的一部分。关于该项目的信息可以前往 ⟨https://www.kernel.org/doc/man-pages/⟩ 了解。如果您发现本手册页有漏洞或错误,请参阅 ⟨https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/tree/CONTRIBUTING⟩。
此页面是从 man-pages-6.18.tar.gz 压缩包中获取的,该包于 2026-05-24 获取自 ⟨https://mirrors.edge.kernel.org/pub/linux/docs/man-pages/⟩。如果您在此 HTML 版本的页面中发现任何渲染问题,或者您认为有更好、更新的页面源码,又或者您想要对本跋(此部分不属于原始手册页)中的信息提供更正或改进,请发送邮件至 man-pages@man7.org。


Linux man-pages 6.18 | 2026-02-10 | pthread_create(3)
引用了此页面的其他页面:mmap(2), spu_run(2), wait(2), pthread_attr_init(3), pthread_attr_setdetachstate(3), pthread_attr_setguardsize(3), pthread_attr_setinheritsched(3), pthread_attr_setschedparam(3), pthread_attr_setschedpolicy(3), pthread_attr_setscope(3), pthread_attr_setstack(3), pthread_attr_setstackaddr(3), pthread_attr_setstacksize(3), pthread_cancel(3), pthread_detach(3), pthread_equal(3), pthread_exit(3), pthread_getattr_default_np(3), pthread_getattr_np(3), pthread_join(3), pthread_key_create(3), pthread_self(3), pthread_setaffinity_np(3), pthread_setname_np(3), pthread_setschedparam(3), pthread_setschedprio(3), pthread_sigmask(3), pthreads(7)

HTML 渲染由 Michael Kerrisk 于 2026-05-30 创建,《The Linux Programming Interface》的作者。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐