Linux多线程详解(2)
5.线程的更多细节
5.1线程栈
线程栈大小是固定的,也就是ulimit -a 显示的值
在创建线程的时候,可以通过pthread_attr_t来初始化线程的属性,包括线程的栈布局信息,如栈起始地址stackaddr,栈大小stacksize。 具体需要通过方法
函数原型:
int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, size_t stacksize);
参数说明:
attr:线程属性指针
stackaddr:设置栈的起始地址
返回值:0代表成功,或返回大于0的错误码 // 注:stackaddr 指向为该线程开辟的空间,该空间可以使用malloc或者mmap来开辟,而不能来自进程的栈区。开辟的stackaddr所指向的动态空间需要自己负责释放。
当然也可将线程栈的空间管理交给系统,如果想只改变系统默认的栈大小8MB,可以通过
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize); // 注:stacksize最小值为16384,单位为字节 |
由上面的API接口,可以得到,线程栈的stacksize是保存在pthread_attr_t中的,可以通过人为的指定,也可以通过在创建线程的时候读取系统的配置文件来初始化stacksize,当初始化完栈的起始地址,和大小后,便可以通过
int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize); |
来初始化线程栈末尾之后用以避免栈溢出的缓冲区的大小,如果应用程序溢出到此缓冲区中,这个错误可能会导致 SIGSEGV 信号被发送给该线程, 从而造成段错误,缓冲区默认设置为PAGESIZE个字节。因为线程的mm->start_stack和所属进程相同,所以线程栈的起始地址并没有存放在task_struct中,应该只是使用attr中的stackaddr,来初始化task_struct->thread-> sp(sp指向struct pt_regs对象,该结构体用于保存用户进程或者线程的寄存器现场)。
总结:线程栈的空间开辟在所属进程的堆区,线程与其所属的进程共享进程的用户空间,所以线程栈之间可以互访。线程栈的起始地址和大小存放在pthread_attr_t 中,栈的大小并不是用来判断栈是否越界,而是用来初始化避免栈溢出的缓冲区的大小(或者说安全间隙的大小)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App