PTHREAD_CREATE - Linux手册页

时间:2019-08-20 18:01:02  来源:igfitidea点击:

Linux程序员手册 第3部分
更新日期: 2020-06-09

名称

pthread_create-创建一个新线程

语法

#include <pthread.h>

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

编译并链接-pthread。

说明

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存储在线程指向的缓冲区中;此标识符用于在后续对其他pthreads函数的调用中引用线程。

新线程继承了创建线程的信号掩码(pthread_sigmask(3))的副本。新线程的未决信号集为空(sigpending(2))。新线程不会继承创建线程的备用信号堆栈(sigaltstack(2))。

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

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

Linux-specific details

新线程继承了调用线程的功能集(请参阅功能(7))和CPU亲和力掩码(请参阅sched_setaffinity(2))的副本。

返回值

成功时,pthread_create()返回0;否则,返回0。如果出错,则返回错误号,并且* thread的内容未定义。

错误说明

EAGAIN
资源不足,无法创建另一个线程。
EAGAIN
遇到了系统施加的线程数限制。有许多限制可能触发此错误:已达到RLIMIT_NPROC软资源限制(通过setrlimit(2)设置),该限制限制了实际用户ID的进程和线程数;达到了内核在系统范围内对进程和线程数的限制,即/ proc / sys / kernel / threads-max(请参见proc(5));或已达到PID的最大数量/ proc / sys / kernel / pid_max(请参阅proc(5))。
EINVAL
attr中的设置无效。
EPERM无权设置attr中指定的调度策略和参数。

属性

有关本节中使用的术语的说明,请参见attribute(7)。

InterfaceAttributeValue
pthread_create()Thread safetyMT-Safe

遵循规范

POSIX.1-2001,POSIX.1-2008。

备注

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

线程可以是可连接的也可以是分离的。如果一个线程是可连接的,则另一个线程可以调用pthread_join(3)等待该线程终止并获取其退出状态。仅当终止的可连接线程已被连接时,其最后资源才释放回系统。当分离的线程终止时,其资源将自动释放回系统:不可能与线程联接以获得其退出状态。使线程分离对于某些类型的守护程序线程非常有用,这些守护程序线程的退出状态是应用程序不需要关心的。默认情况下,除非将attr设置为以分离状态创建线程(使用pthread_attr_setdetachstate(3)),否则将以可连接状态创建新线程。

在NPTL线程实现下,如果程序启动时的RLIMIT_STACK软资源限制具有" unlimited"以外的任何其他值,则它将确定新线程的默认堆栈大小。使用pthread_attr_setstacksize(3),可以在用于创建线程的attr参数中显式设置堆栈大小属性,以获取默认值以外的堆栈大小。如果RLIMIT_STACK资源限制设置为" unlimited",则每个体系结构值将用于堆栈大小。这是一些体系结构的价值:

体系结构默认堆栈大小 i3862兆字节 IA-6432 MB PowerPC4 MB S / 3902兆字节 Sparc-322 MB Sparc-644兆字节 x86_642 MB

BUGS

在过时的LinuxThreads实现中,一个进程中的每个线程都有一个不同的进程ID。这违反了POSIX线程规范,并且是许多其他不符合该标准的原因。参见pthreads(7)。

示例

下面的程序演示了pthread_create()的用法以及pthreads API中的许多其他功能。

在以下运行中,在提供NPTL线程实现的系统上,堆栈大小默认为"堆栈大小"资源限制所给定的值:

$ ulimit -s
8192            # The stack size limit is 8 MB (0x800000 bytes)
$ ./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

Program source

#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>

#define handle_error_en(en, msg) \
        do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)

#define handle_error(msg) \
        do { perror(msg); exit(EXIT_FAILURE); } while (0)

struct thread_info {    /* Used as argument to thread_start() */
    pthread_t thread_id;        /* ID returned by pthread_create() */
    int       thread_num;       /* Application-defined thread # */
    char     *argv_string;      /* From command-line argument */
};

/* Thread start function: display address near top of our stack,
   and return upper-cased copy of argv_string */

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

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

    uargv = strdup(tinfo->argv_string);
    if (uargv == NULL)
        handle_error("strdup");

    for (p = uargv; *p != aq##代码##aq; p++)
        *p = toupper(*p);

    return uargv;
}

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

    /* The "-s" option specifies a stack size for our threads */

    stack_size = -1;
    while ((opt = getopt(argc, argv, "s:")) != -1) {
        switch (opt) {
        case aqsaq:
            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;

    /* Initialize thread creation attributes */

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

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

    /* Allocate memory for pthread_create() arguments */

    tinfo = calloc(num_threads, sizeof(struct thread_info));
    if (tinfo == NULL)
        handle_error("calloc");

    /* Create one thread for each command-line argument */

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

        /* The pthread_create() call stores the thread ID into
           corresponding element of tinfo[] */

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

    /* Destroy the thread attributes object, since it is no
       longer needed */

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

    /* Now join with each thread, and display its returned value */

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

        printf("Joined with thread %d; returned value was %s\n",
                tinfo[tnum].thread_num, (char *) res);
        free(res);      /* Free memory allocated by thread */
    }

    free(tinfo);
    exit(EXIT_SUCCESS);
}

出版信息

这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/