linux之线程的高级属性

一次性初始化:
用途:  有些事需要且只能执行一次(比如互斥量初始化)。通常当初始化应用程序时,可以比较容易地将其放在main函数中。但当你写一个库函数时,就不能在main里面初始化了,你可以用静态初始化,但使用一次初始(pthread_once_t)会比较容易些。
用法: 

//首先要定义一个pthread_once_t变量,这个变量要用宏PTHREAD_ONCE_INIT初始化。
//然后创建一个与控制变量相关的初始化函数

    pthread_once_t once_control = PTHREAD_ONCE_INIT;
    void init_routine( )
    {
         //需要初始化的内容
         ......
    }

//最后,在任何时刻调用pthread_once函数。
//在多线程编程环境下,init_routine()函数仅执行一次,究竟在哪个线程中执行是不定的,由内核调度来决定。
int pthread_once(pthread_once_t *once_control, void (*init_routine)(void));

线程的属性:

线程的属性类型:pthread_attr_t

属性名称 描述
detachstate   线程的分离状态
guardsize 线程栈末尾的警戒区域大小(字节数)
stacksize 线程栈的最低地址
stacksize 线程栈的大小(字节数)

 1、线程属性初始化
     int pthread_attr_init(pthread_attr_t *attr);
 2、线程属性销毁
     int pthread_attr_destroy(pthread_attr_t *attr);

线程的分离属性:

1、分离属性的概念
        分离一个正在运行的线程并不影响它,仅仅是通知当前系统该线程结束时,其所属的资源可以回收。一个没有被分离的线程在终止时会保留它的虚拟内存,包括他们的堆栈和其他系统资源,有时这种线程被称为“僵尸线程”。创建线程时默认是非分离的
        如果线程具有分离属性,线程终止时会被立刻回收,回收将释放掉所有在线程终止时未释放的系统资源和进程资源。包括保存线程返回值的内存空间、堆栈、保存寄存器的内存空间等

2、分离属性的使用方法
        如果在创建线程的时候就知道不需要了解线程的终止状态,那么可以修改pthread_attr_t结构体的detachstate属性,让线程以分离状态启动。    

//设置线程分离属性的步骤
//1、定义线程属性变量
      pthread_attr_t   attr 
// 2、初始化attr
    pthread_attr_init(&attr)
//3、设置线程的分离状态属性
//线程的分离属性有两种合法值:PTHREAD_CREATE_DETACHED分离的 PTHREAD_CREATE_JOINABLE 非分离的,可连接的        
    int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
//4、创建线程
    int pthread_create(&tid, &attr, thread_fun,  NULL)

获得线程的分离状态属性

  int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate);

线程的栈属性:

1、线程的栈大小
        对于进程来说,虚拟地址空间的大小是固定的,进程中只有一个栈,因此它的大小通常不是问题。但对线程来说,同样的虚拟地址被所有的线程共享。如果应用程序使用了太多的线程,致使线程栈累计超过可用的虚拟地址空间,这个时候就需要减少线程默认的栈大小。另外,如果线程分配了大量的自动变量或者线程的栈帧太深,那么这个时候需要的栈要比默认的大。因此就需要修改线程栈的属性来适应具体程序的需要。

>检查系统是否支持线程栈属性
 1)在编译阶段使用    _POSIX_THREAD_ATTR_STACKADDR 和 _POSIX_THREAD_ATTR_STACKSIZE符号
来检查系统是否支持线程栈属性,这些宏定义在/usr/include/bits/posix_opt.h 
 2)在运行阶段把 _SC_THREAD_ATTR_STACKADD和 _SC_THREAD_THREAD_ATTR_STACKSIZE
传递给sysconf函数检查系统对线程栈属性的支持。

如果用完了虚拟地址空间,可以使用malloc或者mmap来为其他栈分配空间,并修改栈的位置。
    >修改栈属性
         int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, size_t   stacksize);
    >获取栈属性
         int pthread_attr_getstack(pthread_attr_t *attr, void **stackaddr, size_t * stacksize);

也可以单独获取或者修改栈的大小,而不去修改栈的地址。栈大小设置,不能小于PTHREAD_STACK_MIN(需要头文件limit.h)
     >修改栈大小
         int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
     >获取栈大小
         int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize);

2、栈尾警戒区
        线程属性guardsize控制着线程栈末尾以后用以避免栈溢出的扩展内存的大小,这个属性默认是PAGESIZE个字节。你可以把它设为0,这样就不会提供警戒缓冲区。同样的,如果你修改了stackaddr,系统会认为你自己要管理栈,警戒缓冲区会无效

        1)、设置guardsize
                int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);
        2)、获取guardsize
                 int pthread_attr_getguardsize(pthread_attr_t *attr, size_t *guardsize);

实例:

#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<limits.h>
pthread_attr_t attr;
void *thread_1(void * arg)
{
	long signed int  stacksize;
#ifdef _POSIX_THREAD_ATTR_STACKSIZE
	pthread_attr_getstacksize(&attr,&stacksize);
	printf("thread1:  default stacksize is %ld\n",stacksize);

	pthread_attr_setstacksize(&attr,100000);
	pthread_attr_getstacksize(&attr,&stacksize);
	printf("thread1: personic stacksize is %ld\n",stacksize);
	
	pthread_attr_setstacksize(&attr,PTHREAD_STACK_MIN);
	pthread_attr_getstacksize(&attr,&stacksize);
	printf("thread1:  minimum stacksize is %ld\n",stacksize);
#endif
	printf("I am thread1\n");
	return (void *)1;
}

void *thread_2(void * arg)
{
	printf("I am thread2\n");
	return (void *)2;
}

int main(int argc,char *argv[])
{
	pthread_t tid1,tid2;
	int err1,err2;
	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
//#ifdef _POSIX_THREAD_ATTR_STACKSIZE
//	pthread_attr_setstacksize(&attr,PTHREAD_STACK_MIN);
//#endif
	err1 = pthread_create(&tid1,&attr, thread_1,NULL);
	err2 = pthread_create(&tid2,NULL, thread_2,NULL);
	if(err1||err2)
	{
		printf("create thread fail\n");
		return -1;
	}
	printf("thread1 return value is %d\n",pthread_join(tid1,NULL));
	printf("thread2 return value is %d\n",pthread_join(tid2,NULL));
	pthread_attr_destroy(&attr);
	return 0;
}
运行结果:
binge@binge-HP-Compaq:~/my_share/pthread$ ./a.out
thread1 return value is 22
thread1:  default stacksize is 8388608
thread1: personic stacksize is 100000
thread1:  minimum stacksize is 16384
I am thread1
I am thread2
thread2 return value is 0

猜你喜欢

转载自blog.csdn.net/weixin_42039602/article/details/83113137