PTHREAD_GETATTR_NP - Linux手册页

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

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

名称

pthread_getattr_np-获取已创建线程的属性

语法

#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include <pthread.h>

int pthread_getattr_np(pthread_t thread, pthread_attr_t *attr);

Compile and link with -pthread.

说明

pthread_getattr_np()函数初始化attr引用的线程属性对象,以便它包含描述正在运行的线程的实际属性值。

返回的属性值可能与在使用pthread_create(3)创建线程的attr对象中传递的相应属性值不同。特别是,以下属性可能有所不同:

*
分离状态,因为可连接线程在创建后可能已经脱离了自身;
*
堆栈大小,实现可将其对齐到合适的边界。
*
和保护大小,如果应用程序正在分配自己的堆栈,则实现可以向上舍入为页面大小的倍数,或者忽略(即视为0)。

此外,如果未在用于创建线程的线程属性对象中设置堆栈地址属性,则返回的线程属性对象将报告实现为该线程选择的实际堆栈地址。

当不再需要pthread_getattr_np()返回的线程属性对象时,应使用pthread_attr_destroy(3)销毁该对象。

返回值

成功时,此函数返回0;否则,返回0。如果出错,则返回非零错误号。

错误说明

ENOMEM
内存不足。

另外,如果线程引用了主线程,则pthread_getattr_np()可能由于各种基础调用的错误而失败:fopen(3),如果无法打开/ proc / self / maps;则fopen(3)。和getrlimit(2)(如果不支持RLIMIT_STACK资源限制)。

版本

从2.2.3版开始,此功能在glibc中可用。

属性

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

InterfaceAttributeValue
pthread_getattr_np()Thread safetyMT-Safe

遵循规范

此函数是非标准的GNU扩展;因此名称中的后缀" _np"(不可移植)。

示例

下面的程序演示了pthread_getattr_np()的用法。该程序创建一个线程,然后使用pthread_getattr_np()检索并显示其保护大小,堆栈地址和堆栈大小属性。创建线程时,可以使用命令行参数将这些属性设置为默认值以外的值。下面的shell会话演示了该程序的用法。

在x86-32系统上的第一次运行中,使用默认属性创建线程:

$ ulimit -s      # No stack limit ==> default stack size is 2 MB
unlimited
$ ./a.out
Attributes of created thread:
        Guard size          = 4096 bytes
        Stack address       = 0x40196000 (EOS = 0x40397000)
        Stack size          = 0x201000 (2101248) bytes

在下面的运行中,我们看到如果指定了防护大小,则将其舍入为系统页面大小的下一个倍数(x86-32上为4096字节):

$ ./a.out -g 4097
Thread attributes object after initializations:
        Guard size          = 4097 bytes
        Stack address       = (nil)
        Stack size          = 0x0 (0) bytes

Attributes of created thread:
        Guard size          = 8192 bytes
        Stack address       = 0x40196000 (EOS = 0x40397000)
        Stack size          = 0x201000 (2101248) bytes

在上一次运行中,程序为线程手动分配堆栈。在这种情况下,保护大小属性将被忽略。

$ ./a.out -g 4096 -s 0x8000 -a
Allocated thread stack at 0x804d000

Thread attributes object after initializations:
        Guard size          = 4096 bytes
        Stack address       = 0x804d000 (EOS = 0x8055000)
        Stack size          = 0x8000 (32768) bytes

Attributes of created thread:
        Guard size          = 0 bytes
        Stack address       = 0x804d000 (EOS = 0x8055000)
        Stack size          = 0x8000 (32768) bytes

Program source

#define _GNU_SOURCE     /* To get pthread_getattr_np() declaration */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

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

static void
display_stack_related_attributes(pthread_attr_t *attr, char *prefix)
{
    int s;
    size_t stack_size, guard_size;
    void *stack_addr;

    s = pthread_attr_getguardsize(attr, &guard_size);
    if (s != 0)
        handle_error_en(s, "pthread_attr_getguardsize");
    printf("%sGuard size          = %d bytes\n", prefix, guard_size);

    s = pthread_attr_getstack(attr, &stack_addr, &stack_size);
    if (s != 0)
        handle_error_en(s, "pthread_attr_getstack");
    printf("%sStack address       = %p", prefix, stack_addr);
    if (stack_size > 0)
        printf(" (EOS = %p)", (char *) stack_addr + stack_size);
    printf("\n");
    printf("%sStack size          = 0x%x (%d) bytes\n",
            prefix, stack_size, stack_size);
}

static void
display_thread_attributes(pthread_t thread, char *prefix)
{
    int s;
    pthread_attr_t attr;

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

    display_stack_related_attributes(&attr, prefix);

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

static void *           /* Start function for thread we create */
thread_start(void *arg)
{
    printf("Attributes of created thread:\n");
    display_thread_attributes(pthread_self(), "\t");

    exit(EXIT_SUCCESS);         /* Terminate all threads */
}

static void
usage(char *pname, char *msg)
{
    if (msg != NULL)
        fputs(msg, stderr);
    fprintf(stderr, "Usage: %s [-s stack-size [-a]]"
            " [-g guard-size]\n", pname);
    fprintf(stderr, "\t\t-a means program should allocate stack\n");
    exit(EXIT_FAILURE);
}

static pthread_attr_t *   /* Get thread attributes from command line */
get_thread_attributes_from_cl(int argc, char *argv[],
                              pthread_attr_t *attrp)
{
    int s, opt, allocate_stack;
    long stack_size, guard_size;
            void *stack_addr;
    pthread_attr_t *ret_attrp = NULL;   /* Set to attrp if we initialize
                                           a thread attributes object */
    allocate_stack = 0;
    stack_size = -1;
    guard_size = -1;

    while ((opt = getopt(argc, argv, "ag:s:")) != -1) {
        switch (opt) {
        case aqaaq:   allocate_stack = 1;                     break;
        case aqgaq:   guard_size = strtoul(optarg, NULL, 0);  break;
        case aqsaq:   stack_size = strtoul(optarg, NULL, 0);  break;
        default:    usage(argv[0], NULL);
        }
    }

    if (allocate_stack && stack_size == -1)
        usage(argv[0], "Specifying -a without -s makes no sense\n");

    if (argc > optind)
        usage(argv[0], "Extraneous command-line arguments\n");

    if (stack_size >= 0 || guard_size > 0) {
        ret_attrp = attrp;

        s = pthread_attr_init(attrp);
        if (s != 0)
            handle_error_en(s, "pthread_attr_init");
    }

    if (stack_size >= 0) {
        if (!allocate_stack) {
            s = pthread_attr_setstacksize(attrp, stack_size);
            if (s != 0)
                handle_error_en(s, "pthread_attr_setstacksize");
        } else {
            s = posix_memalign(&stack_addr, sysconf(_SC_PAGESIZE),
                               stack_size);
            if (s != 0)
                handle_error_en(s, "posix_memalign");
            printf("Allocated thread stack at %p\n\n", stack_addr);

            s = pthread_attr_setstack(attrp, stack_addr, stack_size);
            if (s != 0)
                handle_error_en(s, "pthread_attr_setstacksize");
        }
    }

    if (guard_size >= 0) {
        s = pthread_attr_setguardsize(attrp, guard_size);
        if (s != 0)
            handle_error_en(s, "pthread_attr_setstacksize");
    }

    return ret_attrp;
}

int
main(int argc, char *argv[])
{
    int s;
    pthread_t thr;
    pthread_attr_t attr;
    pthread_attr_t *attrp = NULL;    /* Set to &attr if we initialize
                                        a thread attributes object */

    attrp = get_thread_attributes_from_cl(argc, argv, &attr);

    if (attrp != NULL) {
        printf("Thread attributes object after initializations:\n");
        display_stack_related_attributes(attrp, "\t");
        printf("\n");
    }

    s = pthread_create(&thr, attrp, &thread_start, NULL);
    if (s != 0)
        handle_error_en(s, "pthread_create");

    if (attrp != NULL) {
        s = pthread_attr_destroy(attrp);
        if (s != 0)
            handle_error_en(s, "pthread_attr_destroy");
    }

    pause();    /* Terminates when other thread calls exit() */
}

另外参见

pthread_attr_getaffinity_np(3),pthread_attr_getdetachstate(3),pthread_attr_getguardsize(3),pthread_attr_getinheritsched(3),pthread_attr_getschedparam(3),pthread_attr_getschedpolicycy(3),pthread_attr_getr(get)() pthread_attr_init(3),pthread_create(3),pthreads(7)

出版信息

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