pthread_create(3) Linux 手册页
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))。 - EINVAL:
attr中的设置无效。 - 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》的作者。
更多推荐



所有评论(0)