###线程测试代码
#include
#include
#include
#include
#include
void *thd_fn(void *args)
{
int n = *((int *)args);
printf("this is thread:%d\n", n);
while(1)
{
printf("this is thread:%d\n", n);
sleep(1);
}
}
int main(int argc, char *argv[])
{
pthread_attr_t attr;
int ret = pthread_attr_init(&attr);
if(ret != 0)
{
perror("pthread_attr_init_err:");
printf("pthread_attr_init_err ret:%d\n", ret);
exit(1);
}
size_t default_stack_size = 0;
ret = pthread_attr_getstacksize(&attr, &default_stack_size);
if(ret != 0)
{
perror("pthread attr getstatck size err:");
printf("pthread_attr_getstatck_size err. ret:%d\n", ret);
exit(1);
}
printf("the default stack size:%d, %dK\n", default_stack_size, default_stack_size/1024);
size_t stack_size = 64*1024;
//size_t stack_size = 128*1024;
ret = pthread_attr_setstacksize(&attr, stack_size);
if(ret != 0)
{
perror("pthread attr setstatck size");
printf("pthread_attr_setstatcksize err, size :%d(%dK). ret:%d\n",stack_size, stack_size/1024, ret);
exit(1);
}
int i = 0;
for(; i<10; i++)
{
pthread_t pid;
ret = pthread_create(&pid, &attr, thd_fn, (void *)&i);
if(ret != 0 )
{
perror("pthread err:");
printf("ret:%d\n", ret);
}
}
while(1);
return 0;
}
###编译运行
如下所示,默认的线程栈大小为8192K,但将栈大小设置为64K 时,运行出错返回值为 22.
$ gcc pthread_test.c -g -o pthread_test -pthread
$ ./pthread_test
the default stack size:8388608, 8192K
pthread attr setstatck size: Success
pthread_attr_setstatcksize err, size :65536(64K). ret:22
根据这种情况,先查看pthread_attr_setstacksize 说明看看能不能找到一些说明信息,其中对返回出错的一段描述如下的所示。根据其说明是大小设置必须为页大小的倍数,还有一个返回码为EINVAL
时表示栈大小小于最小要求16K。 通过getconf PAGESIZE
可知当前的页大小为16K,而代码里面设置的大小为64K, 符合大小须页大小的倍数这一要求,并且也超过了16K的最小值。事出怪异,必有妖~
$ man pthread_attr_setstacksize
ERRORS
pthread_attr_setstacksize() can fail with the following error:
EINVAL The stack size is less than PTHREAD_STACK_MIN (16384) bytes.
On some systems, pthread_attr_setstacksize() can fail with the error EINVAL if stacksize is not a multiple of the system page size.
# 查看页大小
$ getconf PAGESIZE
16384
接下来只能看返回值22 对应的是什么错误了,还有说明中EINVAL
值是多少。 linux 平台错误码定义在/usr/include/asm/errno.h
文件中。 但grep "EINVAL" asm/errno.h
没见有结果。 查看cat asm/errno.h
发现里面包含了文件 asm-generic/errno-base.h
。执行grep "EINVAL" asm-generic/errno-base.h -rn
查找到了相关定义./asm-generic/errno-base.h:26:#define EINVAL 22 /* Invalid argument */
。
_好消息是这个返回值刚和man
里面的说明一致,但是man
里面说出这个错误是因为栈大小小于 PTHREAD_STACK_MIN (16384)
。莫非man
骗我,不太可能吧。本着怀疑的精神(试试又不会怀孕),推测是这个说明是针对x86
平台的,而我手里的是MIPS64
平台。 那么接下来看看宏PTHREAD_STACK_MIN
的定义。通过grep
大法找到了PTHREAD_STACK_MIN
在此的定义是 131072 即128K
。 呵呵呵呵,只要套路深,铁柱变成针… 改代码把大小设置为128K
之后运行正常。
# 查找线程栈大小的最小值定义
$ cd /usr/include
$ grep "PTHREAD_STACK_MIN" . -rni
./mips64el-linux-gnuabi64/bits/local_lim.h:81:#define PTHREAD_STACK_MIN 131072
./pthread.h:363: minimal size of the block must be PTHREAD_STACK_MIN. */
./pthread.h:374: to be started. This size must never be less than PTHREAD_STACK_MIN
总结:
龙芯(MIPS64)平台,线程栈的大小设置要求: 1. 必须是页大小(16K)的整数倍 2. 线程栈的最小值在此平台的定义为 128K。