侧边栏壁纸
博主头像
noerror

虚灵不寐,众理具而万事出。

  • 累计撰写 238 篇文章
  • 累计创建 9 个标签
  • 累计收到 2 条评论
标签搜索

目 录CONTENT

文章目录

pthread_getattr_np函数用法详解

noerror
2022-10-04 / 0 评论 / 0 点赞 / 42 阅读 / 1,566 字 / 正在检测是否收录...

pthread_getattr_np函数用法详解

pthread_getattr_np函数简介

  • 头文件包含
#include <pthread.h>
  • 函数定义
int pthread_getattr_np(pthread_t  thread , pthread_attr_t * attr );
  • 编译链接选项
-pthread

pthread_getattr_np函数常见使用错误

  • 链接错误
    undefined reference to `pthread_getattr_np'
    解决办法:添加链接选项
-pthread
  • 编译错误
    warning: implicit declaration of function ‘pthread_getattr_np’ [-Wimplicit-function-declaration]
    解决办法:包含头文件
#include <pthread.h>

pthread_getattr_np函数详细描述

pthread_getattr_np ()函数初始化attr引用的thread attributes对象,以便它包含描述运行的线程thread 的实际属性值
返回的属性值可能不同于attr对象中传递的相应属性值,该对象用于使用pthread_create (3)创建线程,特别是以下属性可能不同:

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

此外,如果用于创建线程的thread attributes对象中没有设置stack address属性,则返回的thread attributes对象将报告实现为该线程选择的实际堆栈地址。
当不再需要pthread_getattr_np ()返回的thread attributes对象时,应该使用pthread_attr_destroy (3)销毁该对象

pthread_getattr_np函数返回值

成功时,此函数返回0;出错时,它返回一个非零错误号。

pthread_getattr_np函数错误码

  • ENOMEM 内存不足。

此外,如果thread引用主线程,那么pthread_getattr_np ()可能会因为来自各种底层调用的错误而失败:如果/proc/self/maps不能打开,则为fopen (3);如果不支持RLIMIT_STACK资源限制,则为getrlimit (2)。

pthread_getattr_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

在最后一次运行中,程序手动为线程分配堆栈。在这种情况下,将忽略guard size属性。

" ./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) \e
       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          = %zu bytes\en", 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("\en");
   printf("%sStack size          = %#zx (%zu) bytes\en",
           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:\en");
   display_thread_attributes(pthread_self(), "\et");

   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]\en", pname);
   fprintf(stderr, "\et\et\-a means program should allocate stack\en");
   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;
   size_t 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 \(aqa\(aq:   allocate_stack = 1;                     break;
       case \(aqg\(aq:   guard_size = strtoul(optarg, NULL, 0);  break;
       case \(aqs\(aq:   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\en");

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

   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\en\en", 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:\en");
       display_stack_related_attributes(attrp, "\et");
       printf("\en");
   }

   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() */
}
0

评论区