pthread_attr_getstacksize 问题
最近公司里遇到一个线程栈大小的问题,借此机会刚好学习一下这个线程栈大小相关的函数。如果公司里用的还是比较老的代码的话,都是用的 pthread 库支持线程的,而不是 c++11 里的线程类。主要有两个相关函数: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, see<https://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;
}
![]()
相关文章:
pthread_attr_getstacksize 问题
最近公司里遇到一个线程栈大小的问题,借此机会刚好学习一下这个线程栈大小相关的函数。如果公司里用的还是比较老的代码的话,都是用的 pthread 库支持线程的,而不是 c11 里的线程类。主要有两个相关函数:pthread_attr_setstacksiz…...
anaconda常见语法
anaconda常见语法 一、镜像 1.添加镜像channel conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/2.删除镜像channel conda config --remove channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/3.展示目前已有的镜像…...
reactive与ref VCA
简介 Vue3 最大的一个变动应该就是推出了 CompositionAPI,可以说它受ReactHook 启发而来;它我们编写逻辑更灵活,便于提取公共逻辑,代码的复用率得到了提高,也不用再使用 mixin 担心命名冲突的问题。 ref 与 reactive…...
小程序day01
简介: 小程序项目的基本结构 页面的组成部分 一个页面对应一个文件夹,所有有关的内容都放在一起。 JSON配置文件 2.app.json文件 3.project.config.json文件 4.sitemap.json文件 5.页面的.json配置文件 6. 新建小程序页面 7.修改项目首页 小程序代码构成 小程序的宿…...
redis主要支持的数据类型有哪些?—— 筑梦之路
Redis支持的主要数据类型: 1、字符串(String):字符串是最简单的数据结构,可以存储文本或二进制数据。常用操作:设置值、获取值、追加、自增自减等。 2、列表(List):列表是…...
解决国际阿里云服务器挂载云盘的问题!!
跟着云计算技术的开展,越来越多的企业和个人挑选运用云服务器。然而,在运用过程中,可能会遇到一些问题,比如云服务器无法挂载云盘。这篇文章将详细说明如何处理这个问题。 一、云服务器无法挂载云盘的原因 云服务器无法挂载云盘可…...
基于吉萨金字塔建造算法的无人机航迹规划-附代码
基于吉萨金字塔建造算法的无人机航迹规划 文章目录 基于吉萨金字塔建造算法的无人机航迹规划1.吉萨金字塔建造搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要:本文主要介绍利用吉萨金字塔建造算法…...
高频SQL50题(基础版)-1
文章目录 主要内容一.SQL练习题1.1757-可回收且抵制的产品代码如下(示例): 2.584-寻找用户推荐人代码如下(示例): 3.595-大的国家代码如下(示例): 4.1148-文章浏览代码如下(示例): 5…...
RecyclerView自定义LayoutManager从0到1实践
此前大部分涉及到 RecyclerView 页面的 LayoutManager基本上用系统提供的 LinearLayoutManager 、GridLayoutManager 就能解决,但在一些特殊场景上还是需要我们自定义 LayoutManager。之前基本上没有自己写过,在网上看各种源码各种文章,刚开始…...
【虹科干货】5个关于微服务的误解
你认为微服务架构能为你带来什么?难道微服务真的是一劳永逸的吗?又或者,难道微服务的威力并不如传闻所言?微服务架构应当如何设计才能真正彰显它作为一种解决方案的好处呢? 文章速览: 误解一:…...
利用卷影拷贝服务攻击域控五大绝招
点击星标,即时接收最新推文 在微软Active Directory(活动目录)中,所有的数据都被保存在ntds.dit中, NTDS.DIT是一个二进制文件, 它存在于域控制器中的 %SystemRoot%\ntds\NTDS.DIT。ntds.dit包括但不限于Us…...
web3 在React dapp中全局管理web3当前登录用户/智能合约等信息
上文 Web3 React项目Dapp获取智能合约对象我们在自己的前端dapp项目中链接获取到了 自己的智能合约 我们继续 我们还是先启动ganache环境 终端输入 ganache -d然后发布一下我们的智能合约 打开我们的合约项目 终端输入 truffle migrate --reset这样 我们的智能合约就部署到区…...
Golang硬件控制:将软件力量扩展到物理世界
引言 在过去的几十年中,计算机科学和软件工程领域取得了巨大的发展和进步。现在,我们可以编写各种强大的软件应用程序来解决各种问题。然而,软件并不仅限于在计算机上运行,它也可以扩展到物理世界中。这就是Golang的魅力所在。Go…...
Docker 查看Image镜像的Dockerfile方法
1、创建测试镜像 Dockerfile: FROM centos LABEL maintainer"NGINX Docker Maintainers docker-maintnginx.com" RUN yum install -y nginx RUN echo "Nginx Web: CMD defining default arguments for an ENTRYPOINT" > /usr/share/nginx/html/index.…...
el-dialog中嵌套iframe之后拿不到iframe的id 的解决办法
在vueelement项目中想用到el-dialog弹窗加iframe嵌套外部页面的方法,但是这时候要获取iframe里面的ID 但是这时候怎么也获取不到 <el-dialog ref"middleFlag" v-if"middleFlag" width"1100px" height1200px title"文章管理" :visib…...
汇总公安局网站建设想法,QPQ盐浴氮化处理
功能描述 网站管理平台 1、主要功能:网站信息发布功能组件、文章数据转移、内容管理word导入发布、一键排版、统一互动、网站管理、权限分配管理 2、跨浏览器的后台管理界面,支持IE\FIREFOX\CHROME\SAFARI\OPERA及其他第三方浏览器; 3、系统…...
前度开发面试题
面试题总结 vue页面跳转会经过两个钩子函数beforeEach、afterEach 组见守卫 beforeRouteEnter前置组见守卫 *beforeRouteUpdate更新之前 watch和computed区别 数据没有改变,则 computed 不会重新计算)。若没改变,计算属性会立即返回之前缓…...
如何保证缓存中都是热点数据?
确保缓存中保留热点数据是关键,因为热点数据通常是最常被访问的数据,提高了缓存的命中率和整体性能。以下是一些策略和方法,能够帮助你维护缓存中的热点数据: 缓存策略: 缓存预热: 在系统启动时或负载较低的…...
什么是Webpack?它的主要功能是什么?
聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…...
基于深度学习的人脸性别年龄识别 - 图像识别 opencv 计算机竞赛
文章目录 0 前言1 课题描述2 实现效果3 算法实现原理3.1 数据集3.2 深度学习识别算法3.3 特征提取主干网络3.4 总体实现流程 4 具体实现4.1 预训练数据格式4.2 部分实现代码 5 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 毕业设计…...
逆向实战:手把手带你用Node.js复现某音a_bogus算法核心步骤(含完整代码)
深入解析Node.js实现a_bogus算法的核心逻辑与实战应用 在当今Web开发与数据采集领域,理解平台加密机制已成为开发者必备技能。a_bogus作为某平台核心加密参数,其生成过程融合了多种加密技术。本文将彻底拆解这一算法,从底层位运算到高层架构&…...
【GD32】TIMER基本定时器实战:从时钟树解析到精准微秒延时实现
1. 认识GD32基本定时器:你的精准时间管家 第一次接触GD32的定时器时,我完全被那些专业术语吓到了——APB总线、预分频、自动重装载值...直到有一次做传感器数据采集项目,因为延时不准导致数据错位,才真正明白定时器的重要性。简单…...
Navicat数据库自动备份实战:如何设置夜间定时任务避免业务中断
Navicat数据库自动备份实战:如何设置夜间定时任务避免业务中断 深夜的办公室只剩下服务器指示灯在黑暗中闪烁,数据库管理员小李终于可以松一口气——公司的核心业务数据正在Navicat的自动备份任务中安全流转。对于现代企业而言,数据库就像数字…...
保护公司核心测试资产:CANoe CAPL脚本的3种加密方法与硬件绑定实战指南
保护公司核心测试资产:CANoe CAPL脚本的3种加密方法与硬件绑定实战指南 在汽车电子测试领域,CAPL脚本往往承载着企业多年积累的测试逻辑和专有技术。我曾亲眼见证一家供应商因测试脚本泄露导致竞品在三个月内复现其全部测试用例,直接造成数百…...
[CentOS 7实战] 从零部署高可用TeamSpeak语音服务器
1. 环境准备与基础配置 在CentOS 7上部署TeamSpeak服务器前,需要做好充分的环境准备。我建议使用至少2核4G配置的云服务器,实测这个配置可以稳定支持50人同时在线的语音通信。如果是大型游戏社区使用,建议选择4核8G以上的配置。 首先需要检查…...
免费开源远程桌面控制终极指南:如何用BilldDesk替代ToDesk和向日葵
免费开源远程桌面控制终极指南:如何用BilldDesk替代ToDesk和向日葵 【免费下载链接】billd-desk 基于Vue3 WebRTC Nodejs Flutter搭建的远程桌面控制、游戏串流 项目地址: https://gitcode.com/gh_mirrors/bi/billd-desk 你是否厌倦了远程控制软件的各种限…...
I2C、SPI、CAN、PCIe:从“身份识别”到“对话方式”的四大总线深度解析
1. 四大总线的"身份证":如何唯一标识设备 想象一下你走进一个挤满人的会议室,想要找张三谈事情。这时候你需要两种信息:第一,如何从人群中识别出张三(唯一标识);第二,用什…...
从RESTful API设计实战出发:深度解析@RequestMapping的6个属性与4个参数注解的搭配艺术
RESTful API设计实战:RequestMapping属性与参数注解的深度组合艺术 在微服务架构盛行的今天,设计一套规范、易维护的Web API接口已成为后端开发者的核心技能。Spring MVC框架中的RequestMapping注解及其配套参数注解,就像乐高积木一样&#…...
Claude Design 登场,设计工具分化,Figma“Sketch 时刻”将至?
关于 Claude Design 的思考与感悟 2026 年 4 月 18 日,山姆亨利戈尔德试用了 Claude Design,并对局势发展有了一些想法。随着产品团队规模扩大,设计需在工程组织中证明自身价值,促使设计向系统化发展。Figma 发明了组件、样式、变…...
Minecraft世界管理终极指南:如何用MCA Selector快速清理和优化你的存档 [特殊字符]
Minecraft世界管理终极指南:如何用MCA Selector快速清理和优化你的存档 🎮 【免费下载链接】mcaselector A tool to select chunks from Minecraft worlds for deletion or export. 项目地址: https://gitcode.com/gh_mirrors/mc/mcaselector MCA…...
