当前位置: 首页 > news >正文

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 问题

最近公司里遇到一个线程栈大小的问题&#xff0c;借此机会刚好学习一下这个线程栈大小相关的函数。如果公司里用的还是比较老的代码的话&#xff0c;都是用的 pthread 库支持线程的&#xff0c;而不是 c11 里的线程类。主要有两个相关函数&#xff1a;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&#xff0c;可以说它受ReactHook 启发而来&#xff1b;它我们编写逻辑更灵活&#xff0c;便于提取公共逻辑&#xff0c;代码的复用率得到了提高&#xff0c;也不用再使用 mixin 担心命名冲突的问题。 ref 与 reactive…...

小程序day01

简介: 小程序项目的基本结构 页面的组成部分 一个页面对应一个文件夹&#xff0c;所有有关的内容都放在一起。 JSON配置文件 2.app.json文件 3.project.config.json文件 4.sitemap.json文件 5.页面的.json配置文件 6. 新建小程序页面 7.修改项目首页 小程序代码构成 小程序的宿…...

redis主要支持的数据类型有哪些?—— 筑梦之路

Redis支持的主要数据类型&#xff1a; 1、字符串&#xff08;String&#xff09;&#xff1a;字符串是最简单的数据结构&#xff0c;可以存储文本或二进制数据。常用操作&#xff1a;设置值、获取值、追加、自增自减等。 2、列表&#xff08;List&#xff09;&#xff1a;列表是…...

解决国际阿里云服务器挂载云盘的问题!!

跟着云计算技术的开展&#xff0c;越来越多的企业和个人挑选运用云服务器。然而&#xff0c;在运用过程中&#xff0c;可能会遇到一些问题&#xff0c;比如云服务器无法挂载云盘。这篇文章将详细说明如何处理这个问题。 一、云服务器无法挂载云盘的原因 云服务器无法挂载云盘可…...

基于吉萨金字塔建造算法的无人机航迹规划-附代码

基于吉萨金字塔建造算法的无人机航迹规划 文章目录 基于吉萨金字塔建造算法的无人机航迹规划1.吉萨金字塔建造搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用吉萨金字塔建造算法…...

高频SQL50题(基础版)-1

文章目录 主要内容一.SQL练习题1.1757-可回收且抵制的产品代码如下&#xff08;示例&#xff09;: 2.584-寻找用户推荐人代码如下&#xff08;示例&#xff09;: 3.595-大的国家代码如下&#xff08;示例&#xff09;: 4.1148-文章浏览代码如下&#xff08;示例&#xff09;: 5…...

RecyclerView自定义LayoutManager从0到1实践

此前大部分涉及到 RecyclerView 页面的 LayoutManager基本上用系统提供的 LinearLayoutManager 、GridLayoutManager 就能解决&#xff0c;但在一些特殊场景上还是需要我们自定义 LayoutManager。之前基本上没有自己写过&#xff0c;在网上看各种源码各种文章&#xff0c;刚开始…...

【虹科干货】5个关于微服务的误解

你认为微服务架构能为你带来什么&#xff1f;难道微服务真的是一劳永逸的吗&#xff1f;又或者&#xff0c;难道微服务的威力并不如传闻所言&#xff1f;微服务架构应当如何设计才能真正彰显它作为一种解决方案的好处呢&#xff1f; 文章速览&#xff1a; 误解一&#xff1a;…...

利用卷影拷贝服务攻击域控五大绝招

点击星标&#xff0c;即时接收最新推文 在微软Active Directory&#xff08;活动目录&#xff09;中&#xff0c;所有的数据都被保存在ntds.dit中&#xff0c; NTDS.DIT是一个二进制文件&#xff0c; 它存在于域控制器中的 %SystemRoot%\ntds\NTDS.DIT。ntds.dit包括但不限于Us…...

web3 在React dapp中全局管理web3当前登录用户/智能合约等信息

上文 Web3 React项目Dapp获取智能合约对象我们在自己的前端dapp项目中链接获取到了 自己的智能合约 我们继续 我们还是先启动ganache环境 终端输入 ganache -d然后发布一下我们的智能合约 打开我们的合约项目 终端输入 truffle migrate --reset这样 我们的智能合约就部署到区…...

Golang硬件控制:将软件力量扩展到物理世界

引言 在过去的几十年中&#xff0c;计算机科学和软件工程领域取得了巨大的发展和进步。现在&#xff0c;我们可以编写各种强大的软件应用程序来解决各种问题。然而&#xff0c;软件并不仅限于在计算机上运行&#xff0c;它也可以扩展到物理世界中。这就是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、主要功能&#xff1a;网站信息发布功能组件、文章数据转移、内容管理word导入发布、一键排版、统一互动、网站管理、权限分配管理 2、跨浏览器的后台管理界面&#xff0c;支持IE\FIREFOX\CHROME\SAFARI\OPERA及其他第三方浏览器&#xff1b; 3、系统…...

前度开发面试题

面试题总结 vue页面跳转会经过两个钩子函数beforeEach、afterEach 组见守卫 beforeRouteEnter前置组见守卫 *beforeRouteUpdate更新之前 watch和computed区别 数据没有改变&#xff0c;则 computed 不会重新计算&#xff09;。若没改变&#xff0c;计算属性会立即返回之前缓…...

如何保证缓存中都是热点数据?

确保缓存中保留热点数据是关键&#xff0c;因为热点数据通常是最常被访问的数据&#xff0c;提高了缓存的命中率和整体性能。以下是一些策略和方法&#xff0c;能够帮助你维护缓存中的热点数据&#xff1a; 缓存策略&#xff1a; 缓存预热&#xff1a; 在系统启动时或负载较低的…...

什么是Webpack?它的主要功能是什么?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…...

基于深度学习的人脸性别年龄识别 - 图像识别 opencv 计算机竞赛

文章目录 0 前言1 课题描述2 实现效果3 算法实现原理3.1 数据集3.2 深度学习识别算法3.3 特征提取主干网络3.4 总体实现流程 4 具体实现4.1 预训练数据格式4.2 部分实现代码 5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 毕业设计…...

深度剖析:导致AI项目失败的五大核心因素与系统化解决方案

AI项目失败率高企,根源往往不在算法,而在系统性的工程、组织与价值错配。本文将深度剖析五大核心因素,并提供可落地的解决方案。同时,结合CAIE注册人工智能工程师认证的能力框架,说明系统化学习如何帮助从业者规避这些陷阱。 一、价值错配:解决了一个“完美”的非问题 现…...

飞书API权限避坑大全:从‘无权限’到成功发送消息的完整流程

飞书API权限配置实战指南&#xff1a;从零到消息发送的完整避坑手册 第一次调用飞书API时&#xff0c;看到控制台抛出"无权限"错误的那种挫败感&#xff0c;我至今记忆犹新。那是一个周五的深夜&#xff0c;我按照官方文档逐字逐句配置&#xff0c;却在最简单的发送…...

当模数只有50万:从‘球与盒子’问题聊聊竞赛中那些‘不寻常模数’的坑与技巧

当模数只有50万&#xff1a;竞赛中非常规模数的解题艺术与陷阱规避 在算法竞赛的数学题中&#xff0c;模数通常被默认为一个背景设定——比如常见的1e97这样的大质数。但当我们遇到一个"不按常理出牌"的模数时&#xff0c;比如题目中的500009&#xff0c;它往往暗示着…...

告别BDC!用BAPI_ACC_DOCUMENT_POST+SAP增强搞定资产、票据等特殊总账凭证

告别BDC&#xff01;用BAPI_ACC_DOCUMENT_POSTSAP增强搞定资产、票据等特殊总账凭证 在SAP财务模块的日常开发中&#xff0c;处理资产购置、票据贴现等特殊总账业务时&#xff0c;很多开发者都会遇到一个经典难题&#xff1a;标准BAPI无法直接支持带有特别总账标识&#xff08;…...

别再瞎调了!NRF52832蓝牙发射功率实战指南:从-40dBm到+4dBm,手把手教你平衡距离与功耗

NRF52832蓝牙发射功率调优实战&#xff1a;从理论到场景化配置的艺术 在物联网设备开发中&#xff0c;蓝牙低功耗(BLE)技术的应用越来越广泛&#xff0c;而NRF52832作为Nordic Semiconductor的明星芯片&#xff0c;其灵活的发射功率调节功能常常被开发者忽视或误用。很多工程师…...

【仅限本周开放】:AGI蛋白质折叠预测工程化部署指南(Docker+Kubernetes+GPU量化推理全流程,含NVIDIA Triton部署模板)

第一章&#xff1a;AGI的蛋白质折叠预测能力 2026奇点智能技术大会(https://ml-summit.org) 通用人工智能&#xff08;AGI&#xff09;系统在蛋白质结构建模领域已展现出超越传统专用AI模型的能力&#xff0c;其核心突破在于将多尺度物理约束、进化序列共变信息与三维几何生成…...

如何快速部署EspoCRM:免费开源CRM系统的完整安装指南

如何快速部署EspoCRM&#xff1a;免费开源CRM系统的完整安装指南 【免费下载链接】espocrm EspoCRM – Open Source CRM Application 项目地址: https://gitcode.com/GitHub_Trending/es/espocrm EspoCRM是一款功能强大的免费开源客户关系管理系统&#xff0c;专为帮助企…...

保姆级教程:用Unity把原神角色变成你的专属桌宠(附完整C#脚本)

Unity实战&#xff1a;打造高互动性原神风格桌宠全流程指南 从零开始构建你的虚拟伙伴 在数字生活日益丰富的今天&#xff0c;个性化桌面伴侣已成为许多用户表达自我风格的方式。想象一下&#xff0c;当你工作疲惫时&#xff0c;桌面上可爱的游戏角色会对你眨眼&#xff1b;当你…...

共享内存数据残留怎么办?深入理解shmget/shmctl的生命周期管理与清理实战

共享内存数据残留怎么办&#xff1f;深入理解shmget/shmctl的生命周期管理与清理实战 在Linux系统编程中&#xff0c;共享内存是进程间通信(IPC)最高效的方式之一&#xff0c;但它的生命周期管理却常常让开发者感到困惑。你是否遇到过这样的情况&#xff1a;测试程序明明已经退…...

融合注意力与多尺度:CBAM_ASPP模块在语义分割中的实践与性能分析

1. 从多尺度到注意力&#xff1a;为什么需要CBAM_ASPP&#xff1f; 语义分割任务的核心挑战在于如何同时捕捉场景中的全局上下文信息和局部细节特征。传统ASPP模块通过多组不同膨胀率的空洞卷积并行处理输入特征&#xff0c;确实能够覆盖不同尺度的感受野。但我在实际项目中发现…...