网站主页流动图片怎么做,深圳市深企在线技术开发有限公司,商标查询官网,好看的移动端网页最近公司里遇到一个线程栈大小的问题#xff0c;借此机会刚好学习一下这个线程栈大小相关的函数。如果公司里用的还是比较老的代码的话#xff0c;都是用的 pthread 库支持线程的#xff0c;而不是 c11 里的线程类。主要有两个相关函数#xff1a;pthread_attr_setstacksiz… 最近公司里遇到一个线程栈大小的问题借此机会刚好学习一下这个线程栈大小相关的函数。如果公司里用的还是比较老的代码的话都是用的 pthread 库支持线程的而不是 c11 里的线程类。主要有两个相关函数pthread_attr_setstacksize() 和 pthread_attr_getstacksize()。 下面看一下简单的例子
#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)static void *thread_start(void *arg)
{ size_t stack_size 0;pthread_attr_t attr;int ret pthread_attr_init(attr);if(ret ! 0){handle_error_en(ret, pthread_attr_init);}ret pthread_attr_getstacksize(attr, stack_size);if (ret ! 0){handle_error_en(ret, pthread_attr_setstacksize);}printf(stack_size %lu\n, stack_size);return 0;
}int main(int argc, char *argv[])
{int s, tnum, opt, num_threads;pthread_t thread_id;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 s:stack_size strtoul(optarg, NULL, 0);break;default:fprintf(stderr, Usage: %s [-s stack-size] arg...\n, argv[0]);exit(EXIT_FAILURE);}}/* 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);}}printf(set stack size %lu\n, stack_size);s pthread_create(thread_id, attr, thread_start, thread_id);if (s ! 0){handle_error_en(s, pthread_create);}/* Destroy the thread attributes object, since it is nolonger needed */s pthread_attr_destroy(attr);if (s ! 0){handle_error_en(s, pthread_attr_destroy);}s pthread_join(thread_id, res);if (s ! 0){handle_error_en(s, pthread_join);}exit(EXIT_SUCCESS);
} 代码里设置了 512 Kb 大小的线程栈而用 pthread_attr_getstacksize获取到的却是 8MB。为什么呢其实这个 8388608 是系统默认的线程栈大小可以用 ulimit -a 查看相关信息 找到 pthread_attr_getstacksize 的源码看一下大概就知道它为什么是这个返回值了
/* Copyright (C) 2002-2022 Free Software Foundation, Inc.This file is part of the GNU C Library.The GNU C Library is free software; you can redistribute it and/ormodify it under the terms of the GNU Lesser General PublicLicense as published by the Free Software Foundation; eitherversion 2.1 of the License, or (at your option) any later version.The GNU C Library is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNULesser General Public License for more details.You should have received a copy of the GNU Lesser General PublicLicense along with the GNU C Library; if not, seehttps://www.gnu.org/licenses/. */
#include pthreadP.h
#include shlib-compat.h
int
__pthread_attr_getstacksize (const pthread_attr_t *attr, size_t *stacksize)
{struct pthread_attr *iattr;iattr (struct pthread_attr *) attr;size_t size iattr-stacksize;/* If the user has not set a stack size we return what the systemwill use as the default. */if (size 0){lll_lock (__default_pthread_attr_lock, LLL_PRIVATE);size __default_pthread_attr.internal.stacksize;lll_unlock (__default_pthread_attr_lock, LLL_PRIVATE);}*stacksize size;return 0;
}
versioned_symbol (libc, __pthread_attr_getstacksize,pthread_attr_getstacksize, GLIBC_2_34);
#if OTHER_SHLIB_COMPAT (libpthread, GLIBC_2_1, GLIBC_2_34)
compat_symbol (libpthread, __pthread_attr_getstacksize,pthread_attr_getstacksize, GLIBC_2_1);
#endif 可以看到如果是用户没有设置栈大小的话就会返回系统默认值即 8MB。但上面的代码中已经调用 pthread_attr_setstacksize() 设置栈大小了为什么还会返回默认值呢仔细看 pthread_attr_getstacksize 的实现它返回的栈大小其实是从入参 attr 里取的 stacksize 值所以回到我们的代码中我们是用 pthread_attr_init(attr) 来初始化 attr 的所以返回的也就是这个初始化后 attr 里的 stacksize 值。可以看看 pthread_attr_init 的源码
#include errno.h
#include string.h
#include unistd.h
#include pthreadP.h
#include shlib-compat.h
struct pthread_attr *__attr_list;
int __attr_list_lock LLL_LOCK_INITIALIZER;
int
__pthread_attr_init (pthread_attr_t *attr)
{struct pthread_attr *iattr;ASSERT_TYPE_SIZE (pthread_attr_t, __SIZEOF_PTHREAD_ATTR_T);ASSERT_PTHREAD_INTERNAL_SIZE (pthread_attr_t, struct pthread_attr);/* Many elements are initialized to zero so let us do it all atonce. This also takes care of clearing the bytes which are notinternally used. */memset (attr, \0, __SIZEOF_PTHREAD_ATTR_T);iattr (struct pthread_attr *) attr;/* Default guard size specified by the standard. */iattr-guardsize __getpagesize ();return 0;
}
libc_hidden_def (__pthread_attr_init)
versioned_symbol (libc, __pthread_attr_init, pthread_attr_init, GLIBC_2_1);
#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_1)
int
__pthread_attr_init_2_0 (pthread_attr_t *attr)
{/* This code is specific to the old LinuxThread code which has a toosmall pthread_attr_t definition. The struct looked likethis: */struct old_attr{int detachstate;int schedpolicy;struct sched_param schedparam;int inheritsched;int scope;};struct pthread_attr *iattr;/* Many elements are initialized to zero so let us do it all atonce. This also takes care of clearing the bytes which are notinternally used. */memset (attr, \0, sizeof (struct old_attr));iattr (struct pthread_attr *) attr;iattr-flags | ATTR_FLAG_OLDATTR;/* We cannot enqueue the attribute because that member is not in theold attribute structure. */return 0;
}
compat_symbol (libc, __pthread_attr_init_2_0, pthread_attr_init, GLIBC_2_0);
#endif
就是把入参 attr 给 memset 了一下所以在 pthead_attr_getstacksize() 里size iattr-stacksize是为 0 的所以 pthead_attr_getstacksize 取到的就是默认的栈大小。那要真正取到当前线程的 stacksize 怎么操作呢使用 pthread_getattr_np() 这个函数取指定线程的 attr如
static void *thread_start(void *arg)
{ size_t stack_size 0;pthread_attr_t attr;int ret pthread_getattr_np(pthread_self(), attr);if(ret ! 0){handle_error_en(ret, pthread_attr_init);}ret pthread_attr_getstacksize(attr, stack_size);if (ret ! 0){handle_error_en(ret, pthread_attr_setstacksize);}printf(current thread stack_size %lu\n, stack_size);return 0;
}