linux linux内核线程栈溢出默认栈多大

Linux开发之线程栈属性
转自:/ymy124/archive//2354742.ht
线程的栈是线程的私有数据,这部分内容是不共享的。在一个进程内有多个线程,这些线程都有自己的栈,但是又都要挤在进程的虚拟地址空间内。线程之间的栈内存必须保证彼此不冲突线程才能正确地运行。因此,虽然大多数情况下,由系统为用户设置和线程的栈内存,但有些时候还是需要用户亲自对线程进行设置。
线程基本属性中和线程栈有关的属性有三个,分别是线程栈的大小、线程栈的最低地址和线程栈末尾警戒区的大小。
系统默认为一个新建的线程提供PAGESIZE个字节的栈空间,但是很多时候需要更改此值。有时候该线程栈可能会不够用,例如,线程体函数是一个多层递归函数,该函数的特点就是需要多层嵌套栈来保存执行过程,因此,该函数可能会造成现有的栈尺寸缩小。另一中情况刚刚相反,用户进程空间的大小是固定的。如果进程内的线程太多,那么就会造成进程的虚拟地址空间不够用,这个时候减小每一个线程的栈的大小是一个必须采取的措施。
Linux下使用pthread_attr_getstacksize函数得到栈大小属性值,pthread_attr_setstack函数设置该属性,其函数原型如下:
int pthread_attr_getstacksize(const pthtead_attr_t *restrict
attr,void **restrict stackaddr,size_t *restrict stacksize)
int pthread_attr_setstacksize(const
pthread_attr_t& *attr,void *stackaddr,size_t
*stacksize)
#include&&&
#include&&&
#include&&&
#include&&&
void*&thread()&&
&&pthread_attr_t&&&
&&size_t&size&=&0;&&
&&printf("default&size:%d\n",&size);&&
&&pthread_attr_getstacksize(&pattr,&&size);&&
&&printf("current&thread&stack&size:%d\n",&size);&&
&&return&(void*)0;&&
int&main()&&
&&pthread_t&&&
&&pthread_create(&ptd,&NULL,&thread,&NULL);&&
&&pthread_join(ptd,&NULL);&&
&&printf("main&thread&quit!\n");&&
线程是提高代码响应和性能的有效手段,它类似于进程。与进程一样,线程由系统内核按时间片进行管理。在单处理系统中,系统内核使用时间片来模拟线程的并发执行。同一进程中的线程共享如下内容。
1,全局变量
3,打开的文件描述符
4,当前工作目录
5,用户及用户组ID
但每个线程有自己独立的线程ID、堆栈、errno变量、优先级
常见的线程相关的函数
1,pthread_create:创建一个进程
2,pthread_join:挂起当前线程直到所等待的线程结束
3,pthread_detach:线程分为“可联合的‘或”可分离的“。可联合的线程终止后,系统将保留其线程ID和退出状态,知道另一个线程调用pthread_jion函数。该函数将一个线程设置为“可分离”的。
4,pthread_self:返回当前线程ID
5,pthead_cancle:用于终止指定线程的执行。
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。下次自动登录
现在的位置:
& 综合 & 正文
linux线程-sysconf系统变量
了解系统的线程资源限制是使得应用恰当地管理它们的关键。前面已经讨论了利用系统资源的示例。当设置线程的栈大小时,最小值为PTHREAD_MIN_STACK。栈大小不应当低于由pthread_attr_getstacksize( )返回的默认栈大小的最小值。每个进程的最大线程数决定了能够为每个进程创建的worker线程的上限。函数sysconf( )用于返回可配置系统限制或选项的当前值。系统中定义了同线程、进程和信号量相关的多个变量和常量。在表6-8中,列出了部分变量和常量。
名字值(Name Value)
_SC_THREADS
_POSIX_THREADS
_SC_THREAD_ATTR_STACKADDR
_POSIX_THREAD_ATTR_STACKADDR
支持线程栈地址属性
_SC_THREAD_ATTR_STACKSIZE
_POSIX_THREAD_ATTR_STACKSIZE
支持线程栈大小属性
_SC_THREAD_STACK_MIN
PTHREAD_STACK_MIN
线程栈存储区的最小大小,以字节为单位
_SC_THREAD_THREADS_MAX
PTHREAD_THREADS_MAX
每个进程的最大线程数
_SC_THREAD_KEYS_MAX
PTHREAD_KEYS_MAX
每个进程关键字的最大数目
_SC_THREAD_PRIO_INHERIT
_POSIX_THREAD_PRIO_INHERIT
支持优先级继承选项
_SC_THREAD_PRIO
_POSIX_THREAD_PRIO_
支持线程优先级选项
_SC_THREAD_PRIORITY_SCHEDULING
_POSIX_THREAD_PRIORITY_SCHEDULING
支持线程优先级调度选项
_SC_THREAD_PROCESS_SHARED
_POSIX_THREAD_PROCESS_SHARED
支持进程共享同步
_SC_THREAD_SAFE_FUNCTIONS
_POSIX_THREAD_SAFE_FUNCTIONS
支持线程安全函数
_SC_THREAD_DESTRUCTOR_ITERATIONS
_PTHREAD_THREAD_DESTRUCTOR_ITERATIONS
决定在线程退出时尝试销毁线程特定数据的尝试次数
_SC_CHILD_MAX
每个UID允许的最大进程数目
_SC_PRIORITY_SCHEDULING
_POSIX_PRIORITY_SCHEDULING
支持进程调度
_SC_REALTIME_SIGNALS
_POSIX_REALTIME_SIGNALS
支持实时信号
_SC_XOPEN_REALTIME_THREADS
_XOPEN_REALTIME_THREADS
支持X/Open POSIX实时线程特性组
_SC_STREAM_MAX
决定进程能够打开的流的数目
_SC_SEMAPHORES
_POSIX_SEMAPHORES
支持信号量
_SC_SEM_NSEMS_MAX
SEM_NSEMS_MAX
决定线程能够拥有的信号量的最大数目
_SC_SEM_VALUE_MAX
SEM_VALUE_MAX
决定信号量的最大值
_SC_SHARED_MEMORY_OBJECTS
_POSIX_SHARED_MEMORY_OBJECTS
支持共享内存对象
下面是调用sysconf( )的示例:
if(PTHREAD_STACK_MIN == (sysconf(_SC_THREAD_STACK_MIN))){
参考网址:
&&&&推荐文章:
【上篇】【下篇】linux下查看某个进程的线程栈
pstack &pid&
它只是个wrapper shell script,原理,利用的是gdb的功能
相当于执行如下命令:
shell$ gdb
gdb& attach pid
gdb&&thread apply all bt
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。关于Linux线程的线程栈以及TLS_Linux编程_Linux公社-Linux系统门户网站
你好,游客
关于Linux线程的线程栈以及TLS
来源:Linux社区&
作者:dog250
说明:a.本文描述Linux NPTL的线程栈简要实现以及线程本地存储的原理,实验环境中Linux内核版本为2.6.32,glibc版本是2.12.1,Linux发行版为,硬件平台为x86的32位系统。b.对于Linux NPTL线程,有很多话题。本文挑选了原则上是每线程私有的地址空间来讨论,分别是线程栈和TLS。原则山私有并不是真的私有,因为大家都知道线程的特点就是共享地址空间,原则私有空间就是一般而言通过正常手段其它线程不会触及这些空间的数据。
一.线程栈虽然Linux将线程和进程不加区分的统一到了task_struct,但是对待其地址空间的stack还是有些区别的。对于Linux进程或者说主线程,其stack是在fork的时候生成的,实际上就是复制了父亲的stack空间地址,然后写时拷贝(cow)以及动态增长,这可从sys_fork调用do_fork的参数中看出来:
int&sys_fork(struct&pt_regs&*regs)&&
&&&&return&do_fork(SIGCHLD,&regs-&sp,&regs,&0,&NULL,&NULL);&&
}&&何谓动态增长呢?可以看到子进程初始的size为0,然后由于复制了父亲的sp以及稍后在dup_mm中复制的所有vma,因此子进程stack的flags仍然包含:
#define&VM_STACK_FLAGS&&&&(VM_GROWSDOWN&|&VM_STACK_DEFAULT_FLAGS&|&VM_ACCOUNT)&&这就说针对带有这个flags的vma(stack也在一个vma中!)可以动态增加其大小了,这可从do_page_fault中看到:
if&(likely(vma-&vm_start&&=&address))&&
&&&&goto&good_&&
if&(unlikely(!(vma-&vm_flags&&&VM_GROWSDOWN)))&{&&
&&&&bad_area(regs,&error_code,&address);&&
}&&很清晰。& && && 然而对于主线程生成的子线程而言,其stack将不再是这样的了,而是事先固定下来的,使用mmap系统调用,它不带有VM_STACK_FLAGS&& &标记(估计以后的内核会支持!)。这个可以从glibc的nptl/allocatestack.c中的allocate_stack函数中看到:
mem&=&mmap&(NULL,&size,&prot,&&
&&&&&&&&MAP_PRIVATE&|&MAP_ANONYMOUS&|&MAP_STACK,&-1,&0);&&此调用中的size参数的获取很是复杂,你可以手工传入stack的大小,也可以使用默认的,一般而言就是默认的。这些都不重要,重要的是,这种stack不能动态增长,一旦用尽就没了,这是和生成进程的fork不同的地方。在glibc中通过mmap得到了stack之后,底层将调用sys_clone系统调用:
int&sys_clone(struct&pt_regs&*regs)&&
&&&&unsigned&long&clone_&&
&&&&unsigned&long&&&
&&&&int&__user&*parent_tidptr,&*child_&&
&&&&clone_flags&=&regs-&&&
&&&&//获取了mmap得到的线程的stack指针&&
&&&&newsp&=&regs-&&&
&&&&parent_tidptr&=&(int&__user&*)regs-&&&
&&&&child_tidptr&=&(int&__user&*)regs-&&&
&&&&if&(!newsp)&&
&&&&&&&&newsp&=&regs-&&&
&&&&return&do_fork(clone_flags,&newsp,&regs,&0,&parent_tidptr,&child_tidptr);&&
}&&因此,对于子线程的stack,它其实是在进程的地址空间中map出来的一块内存区域,原则上是线程私有的,但是同一个进程的所有线程生成的时候浅拷贝生成者的task_struct的很多字段,其中包括所有的vma,如果愿意,其它线程也还是可以访问到的,于是一定要注意。
相关资讯 & & &
& (12/17/:12)
& (06/21/:37)
& (01/18/:33)
& (11/20/:23)
& (06/21/:31)
图片资讯 & & &
   同意评论声明
   发表
尊重网上道德,遵守中华人民共和国的各项有关法律法规
承担一切因您的行为而直接或间接导致的民事或刑事法律责任
本站管理人员有权保留或删除其管辖留言中的任意内容
本站有权在网站内转载或引用您的评论
参与本评论即表明您已经阅读并接受上述条款

我要回帖

更多关于 linux内核线程堆栈 的文章

 

随机推荐