线程的发展史,调度策略、适用范围、特点,进程与线程的区别、线程的属性、posix线程库

一、线程介绍

什么是线程:

​ 线程是操作系统能够进行运算执行的最小单位,它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

​ 如果man手册查不到线程的相关函数,安装完整版的gnu手册 sudo apt-get install gliba-doc

线程的发展简史:

​ 60年代,在操作系统中能拥有资源和独立运行的基本单位是进程。

​ 随着计算机技术的发展,进程出现了很多弊端:

​ 一是由于进程是资源拥有者,创建、撤消与切换存在较大的时空开销,因此需要引入轻型进程;

​ 二是由于对称多处理机出现,可以满足多个运行单位,而多个进程并行开销过大。

​ 因此在80年代,出现了能独立运行的基本单位——线程(Threads)。

线程的调度策略:

​ 线程是独立调度和分派的基本单位,有三种不同的调试策略:

​ 1、线程可以为操作系统内核调度的内核线程,如Win32线程;

​ 2、由用户进程自行调度的用户线程,如Linux平台的POSIX Thread;

​ 3、由内核与用户进程进行混合调度,如Windows 7的线程。

多线程适用的范围:

​ 一个进程可以有很多线程,每条线程并行执行不同的任务。
​ 在多核或多CPU,或支持Hyper-threading的CPU上使用多线程程序设计的好处是显而易见,即提高了程序的执行吞吐率。

​ 在单CPU单核的计算机上,使用多线程技术,可以把进程中负责I/O处理、人机交互而常被阻塞的部分与密集计算的部分分开来执行,原因就是线程占用的资源少,被阻塞时不浪费资源。(主要解决阻塞和等待问题)

线程的特点:
轻型实体:

​ 线程中的实体基本上不拥有系统资源,只有一点必不可少的、能保证独立运行的资源。线程的实体包括用于指示被执行指令序列的程序计数器、局部变量、状态参数和返回地址。

​ 线程是动态概念,它的动态特性由线程控制块TCB(Thread Control Block)描述,包括以下信息:

​ 1、线程状态

​ 2、当线程不运行时,被保存的现场资源

​ 3、一组执行堆栈(也是栈)

​ 4、存放每个线程的局部变量主存区(栈)

​ 5、访问同一个进程中的主存和其它资源

独立调度和分派的基本单位:

​ 在多线程OS中,线程是能独立运行的基本单位,因而也是独立调度和分派的基本单位。由于线程很“轻”,故线程的切换非常迅速且开销小(在同一进程中的)。

可并发执行:

​ 在一个进程中的多个线程之间,可以并发执行,甚至允许在一个进程中所有线程都能并发执行;同样,不同进程中的线程也能并发执行,充分利用和发挥了处理机与外围设备并行工作的能力。

共享进程资源:

​ 在同一进程中的各个线程,都可以访问该进程的用户空间,此外,还可以访问进程所拥有的已打开文件、定时器、信号量机构等,线程可以共享该进程所拥有的资源。所以线程之间互相通信不必调用内核。

二、线程与进程的区别

资源:

​ 进程采用虚拟空间+用户态/内核态机制,所以就导致进程与进程之间是互相独立的,各自的资源不可见。

​ 在同一进程中的各个线程都可以共享该进程所拥有的资源。

通信:

​ 由于进程之间是互相独立的,需要使用各种IPC通信机制,保障多个进程协同工作。

​ 同一进程中的各个线程共享该进程所拥有的资源,线程间可以直接读写进程数据段来进行通信,但需要线程同步和互斥手段的辅助,以保证数据的一致性。

调度:

​ 无论系统采用什么样的线程调试策略,线程上下文切换都比进程上下文切换要快得多。

身份:

​ 进程是个资源单位,线程是个执行单位,并且线程是进程的一部分,线程需要进程安身立命,进程也需要线程当牛做马。

三、POSIX线程库

POSIX线程库介绍:

​ POSIX线程(POSIX Threads,常被缩写为pthread)是POSIX的线程标准,定义了创建和操纵线程的一套API。
​ 实现POSIX 线程标准的库常被称作pthread,一般用于Unix-likePOSIX 系统,如Linux、Solaris。但是Microsoft Windows上的实现也存在,例如直接使用Windows API实现的第三方库pthread-w32。

API具体内容:

​ pthread定义了一套C语言的类型、函数与常量,它以pthread.h头文件和一个个接口库libpthread.so,gcc和g++编译器没有默认链接该库,需要程序员使用 -l pthread 参数进行手动链接。

​ pthread API中大致共有100个函数调用,全都以"pthread_"开头,并可以分为四类:

​ 1、线程管理,如创建线程,等待线程,查询线程状态等。

​ 2、互斥锁,有创建、摧毁、锁定、解锁、设置属性等操作

​ 3、条件变量,有创建、摧毁、等待、通知、设置与查询属性等操作

​ 4、使用了互斥锁的线程间的同步管理。

四、创建线程

int pthread_create (pthread_t* restrict thread,
                    const pthread_attr_t* restrict attr,
                    void* (*start_routine) (void*),
                    void* restrict arg);

thread        - 线程ID,输出型参数。我们目前使用的linux系统中 pthread_tunsigned long int
attr          - 线程属性,NULL表示缺省属性,如果没有特殊需要,一般写NULL
start_routine - 线程入口函数指针,参数和返回值的类型都是void*
				启动线程本质上就是调用一个函数,只不过是在一个独立的线程中调用的,函数返回即线程结束
arg           - 传递给线程过程函数的参数
返回值:成功返回0,失败返回错误码。(不会修改全局的错误变量,也就是说无法用perror获取错误原因)
    获取方法:1、errno = 返回值;再perror
    		2strerror(返回值)
 
注意:
	1、restrict: C99引入的编译优化指示符,提高重复解引用同一个指针的效率。
	2、pthread.h头文件中声明的函数,通常以直接返回错误码的方式表示失败,而非以错误码设置errno并返回-13、main函数即主线程(主线程不在main函数中结束,则主线程和子线程没关系),main函数返回即主线程结束,主线程结束即进程结束,进程一但结束其所有的线程即结束。
	3、应设法保证在线程过程函数执行期间,其参数所指向的目标持久有效。
#include <string.h>
#include <unistd.h>
#include <pthread.h>

void* thread_proc (void* arg) 
{
	printf ("%lu线程:%s\n", pthread_self (), (char*)arg);
	return NULL;
}

int main () 
{
	pthread_t tid;
	int error = pthread_create (&tid, NULL, thread_proc,"我是快乐的子线程!");
	if (error) 
	{
		fprintf (stderr, "pthread_create: %s\n", strerror (error));
		return -1;
	}

	printf ("%lu线程:我是主线程,创建了%lu线程。\n", pthread_self (),tid);
	sleep (1);

	return 0;
}

五、线程回收

int pthread_join (pthread_t thread, void** retval);

pthread_t thread:线程id
    
功能:等待thread参数所标识的线程结束,并回收相关资源,如果thread线程没有结束则阻塞
retval:获得线程正常结束时的返回值,是输出型参数,用于获取线程入口函数的返回值
返回值:成功返回0,失败返回错误码
    
从线程过程函数中返回值的方法:
	1、线程过程函数将所需返回的内容放在一块内存中,返回该内存的地址,保证这块内存在函数返回,即线程结束,以后依然有效;(不要返回局部变量的地址)
	2、若retval参数非NULL,则pthread_join函数将线程过程函数所返回的指针,拷贝到该参数所指向的内存中;
	3、若线程过程函数所返回的指针指向text、data、bss内存段的数据,如果指向是heap内存段,则还需保证在用过该内存之后释放之。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

#define PAI 3.14159

void* thread_area (void* arg) 
{
	double r = *(double*)arg;
	/*
	static double s;
	s = PAI * r * r;
	return &s;
	*/
	double* s = malloc (sizeof (double));
	*s = PAI * r * r;
	return s;
}

int main () 
{
	printf ("r = ");
	double r;
	scanf ("%lf", &r);

	pthread_t tid;
	int error = pthread_create (&tid, NULL, thread_area, &r);
	if (error) 
	{
		fprintf (stderr, "pthread_create: %s\n", strerror (error));
		return -1;
	}

	double* s;
	if ((error = pthread_join (tid, (void**)&s)) != 0) 
	{
		fprintf (stderr, "pthread_join: %s\n", strerror (error));
		return -1;
	}

	printf ("s = %g\n", *s);
	free (s);

	return 0;
}

六、区分主、子线程

pthread_t pthread_self (void);
成功返回调用线程的ID,不会失败。

int pthread_equal (pthread_t t1, pthread_t t2);
功能:若参数t1和t2所标识的线程ID相等,则返回非零,否则返回0。

注意:某些实现的pthread_t不是unsigned long int类型,可能是结构体类型,无法通过“==”判断其相等性。
#include <stdio.h>
#include <string.h>
#include <pthread.h>

pthread_t g_main;

void* ismain (void* arg) 
{
  //if (pthread_self () == g_main)
	if (pthread_equal (pthread_self (), g_main))
		printf ("我是主线程!\n");
	else
		printf ("我不是主线程!\n");
	return NULL;
}

int main () 
{
	g_main = pthread_self ();

	ismain (NULL);

	pthread_t tid;
	int error = pthread_create (&tid, NULL, ismain, NULL);
	if (error) 
	{
		fprintf (stderr, "pthread_create: %s\n", strerror (error));
		return -1;
	}

	if ((error = pthread_join (tid, NULL)) != 0) 
	{
		fprintf (stderr, "pthread_join: %s\n", strerror (error));
		return -1;
	}

	return 0;
}

七、终止线程

方法1:从线程入口函数中return。

方法2:调用pthread_exit函数。

void pthread_exit (void* retval);
retval - 和线程过程函数的返回值语义相同。

注意:在任何线程中调用exit函数都将终止整个进程。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

#define PAI 3.14159

void* thread_area (void* arg) 
{
	double r = *(double*)arg;
	double* s = malloc (sizeof (double));
	//exit (0);
	*s = PAI * r * r;
	pthread_exit (s); // <==> return s;
	*s = 2 * PAI * r;
	return s;
}

int main () 
{
	printf ("r = ");
	double r;
	scanf ("%lf", &r);

	pthread_t tid;
	int error = pthread_create (&tid, NULL, thread_area, &r);
	if (error) 
	{
		fprintf (stderr, "pthread_create: %s\n", strerror (error));
		return -1;
	}

	double* s;
	if ((error = pthread_join (tid, (void**)&s)) != 0) 
	{
		fprintf (stderr, "pthread_join: %s\n", strerror (error));
		return -1;
	}

	printf ("s = %g\n", *s);
	free (s);

	return 0;
}

八、线程分离

同步方式(非分离状态):创建线程之后主线程调用pthread_join函数等待其终止,并释放线程资源。

异步方式(分离状态):无需创建者等待,线程终止后自行释放资源。

int pthread_detach (pthread_t thread);
功能:使thread参数所标识的线程进入分离(DETACHED)状态。
返回值:成功返回0,失败返回错误码。
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

void* thread_proc (void* arg) 
{
	for (int i = 0; i < 200; i++) 
    {
		putchar ('-');
		usleep (50000);
	}
	return NULL;
}

int main () 
{
	setbuf (stdout, NULL);

	pthread_t tid;
	int error = pthread_create (&tid, NULL, thread_proc, NULL);
	if (error) 
	{
		fprintf (stderr, "pthread_create: %s\n", strerror (error));
		return -1;
	}

	if ((error = pthread_detach (tid)) != 0) 
	{
		fprintf (stderr, "pthread_detach: %s\n", strerror (error));
		return -1;
	}
	/*
	if ((error = pthread_join (tid, NULL)) != 0) 
	{
		fprintf (stderr, "pthread_join: %s\n", strerror (error));
		return -1;
	}
	*/
	for (int i = 0; i < 200; i++) 
	{
		putchar ('+');
		usleep (100000);
	}

	printf ("\n");

	return 0;
}

九、取消线程

向发送取消请求:
int pthread_cancel (pthread_t thread);

成功返回0,失败返回错误码。

注意:该函数只是向线程发出取消请求,并不等待线程终止。

缺省情况下,线程在收到取消请求以后,并不会立即终止,而是仍继续运行,直到其达到某个取消点。
在取消点处,线程检查其自身是否已被取消了,并做出相应动作。
当线程调用一些特定函数时,取消点会出现。
设置可取消状态:
int pthread_setcancelstate (int state,int* oldstate);
成功返回0,并通过oldstate参数输出原可取消状态(若非NULL),失败返回错误码。

state取值:
   PTHREAD_CANCEL_ENABLE  - 接受取消请求(缺省)。
   PTHREAD_CANCEL_DISABLE - 忽略取消请求。
设置可取消类型:
int pthread_setcanceltype (int type, int* oldtype);

成功返回0,并通过oldtype参数输出原可取消类型
(若非NULL),失败返回错误码。

type取值:
   PTHREAD_CANCEL_DEFERRED     - 延迟取消(缺省)。
      被取消线程在接收到取消请求之后并不立即响应,
       而是一直等到执行了特定的函数(取消点)之后再响应该请求。
   PTHREAD_CANCEL_ASYNCHRONOUS - 异步取消。
      被取消线程可以在任意时间取消,不是非得遇到取消点才能被取消。
       但是操作系统并不能保证这一点。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

void elapse (void) 
{
	size_t i;
	for (i = 0; i < 800000000; ++i);
}

void* thread_proc (void* arg) 
{
	/*
	int error = pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL);
	if (error) 
	{
		fprintf (stderr, "pthread_setcancelstate: %s\n", strerror (error));
		exit (EXIT_FAILURE);
	}
	*//*
	int error = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
	if (error) 
	{
		fprintf (stderr, "pthread_setcanceltype: %s\n", strerror (error));
		exit (EXIT_FAILURE);
	}
	*/
	for (;;) 
	{
		printf ("线程:子在川上曰,逝者如斯夫。\n");
		elapse ();
	}

	return NULL;
}

int main () 
{
	setbuf (stdout, NULL);
	printf ("按<回车>取消线程...\n");

	pthread_t tid;
	int error = pthread_create (&tid, NULL, thread_proc, NULL);
	if (error) 
	{
		fprintf (stderr, "pthread_create: %s\n", strerror (error));
		return -1;
	}

	getchar ();

	if ((error = pthread_cancel (tid)) != 0) 
	{
		fprintf (stderr, "pthread_cancel: %s\n", strerror (error));
		exit (EXIT_FAILURE);
	}

	printf ("已发送取消请求,等待线程终止...\n");

	if ((error = pthread_join (tid, NULL)) != 0) 
	{
		fprintf (stderr, "pthread_join: %s\n", strerror (error));
		return -1;
	}

	printf ("线程已终止。\n");
	return 0;
}

十、线程属性

int pthread_create (pthread_t* restrict thread,
                    const pthread_attr_t* restrict attr,
                    void* (*start_routine) (void*),
                    void* restrict arg);
//创建线程函数的第二个参数即为线程属性,传空指针表示使用缺省属性。

typedef struct {
    // 分离状态
    int detachstate;
       // PTHREAD_CREATE_DETACHED - 分离线程。
       // PTHREAD_CREATE_JOINABLE(缺省) - 可汇合线程。

    // 竞争范围
    int scope;
       // PTHREAD_SCOPE_SYSTEM - 在系统范围内竞争资源。
       // PTHREAD_SCOPE_PROCESS(Linux不支持) - 在进程范围内竞争资源。
    

    // 继承特性
    int inheritsched;
       // PTHREAD_INHERIT_SCHED(缺省) - 调度属性自创建者线程继承。
       // PTHREAD_EXPLICIT_SCHED - 调度属性由后面两个成员确定。
    

    // 调度策略
    nt schedpolicy;
        // SCHED_FIFO - 先进先出策略。
            // 没有时间片。
            // 一个FIFO线程会持续运行,直到阻塞或有高优先级线程就绪。
            // 当FIFO线程阻塞时,系统将其移出就绪队列,待其恢复时再加到同优先级就绪队列的末尾。
            // 当FIFO线程被高优先级线程抢占时,它在就绪队列中的位置不变。
            // 因此一旦高优先级线程终止或阻塞,被抢占的FIFO线程将会立即继续运行。
        // SCHED_RR - 轮转策略。
            // 给每个RR线程分配一个时间片,一但RR线程的时间片耗尽,系统即将移到就绪队列的末尾。
            // SCHED_OTHER(缺省) - 普通策略。
            // 静态优先级为0。任何就绪的FIFO线程或RR线程,都会抢占此类线程。    

    // 调度参数
    struct sched_param schedparam;
        // struct sched_param {
        //     int sched_priority; /* 静态优先级 */
        // };
    

    // 栈尾警戒区大小(字节)  缺省一页(4096字节)。
    size_t guardsize;

    // 栈地址
    void* stackaddr;

    // 栈大小(字节)
    size_t stacksize;
} pthread_attr_t;

不要手动读写该结构体,而应调用pthread_attr_set/get函数设置/获取具体属性项。
设置线程属性:
初始化线程属性结构体:
int pthread_attr_init (pthread_attr_t* attr);
设置具体线程属性项:
int pthread_attr_setdetachstate (pthread_attr_t* attr,int detachstate);
int pthread_attr_setscope (pthread_attr_t* attr,int scope);
int pthread_attr_setinheritsched (pthread_attr_t* attr,int inheritsched);
int pthread_attr_setschedpolicy (pthread_attr_t* attr,int policy);
int pthread_attr_setschedparam (pthread_attr_t* attr,const struct sched_param* param);
int pthread_attr_setguardsize (pthread_attr_t* attr,size_t guardsize);
int pthread_attr_setstackaddr (pthread_attr_t* attr,void* stackaddr);
int pthread_attr_setstacksize (pthread_attr_t* attr,size_t stacksize);
int pthread_attr_setstack (pthread_attr_t* attr,void* stackaddr, size_t stacksize);
以设置好的线程属性结构体为参数创建线程:
int pthread_create (pthread_t* restrict thread,
                    const pthread_attr_t* testrict attr,
                    void* (*start_routine) (void*),
                    void* restrict arg);
销毁线程属性结构体:
int pthread_attr_destroy (pthread_attr_t* attr);
获取线程属性:
获取线程属性结构体:
int pthread_getattr_np (pthread_t thread,pthread_attr_t* attr);
获取具体线程属性项:
int pthread_attr_getdetachstate (pthread_attr_t* attr,int* detachstate);
int pthread_attr_getscope (pthread_attr_t* attr,int* scope);
int pthread_attr_getinheritsched (pthread_attr_t* attr,int* inheritsched);
int pthread_attr_getschedpolicy (pthread_attr_t* attr,int* policy);
int pthread_attr_getschedparam (pthread_attr_t* attr,struct sched_param* param);
int pthread_attr_getguardsize (pthread_attr_t* attr,size_t* guardsize);
int pthread_attr_getstackaddr (pthread_attr_t* attr,void** stackaddr);
int pthread_attr_getstacksize (pthread_attr_t* attr,size_t* stacksize);
int pthread_attr_getstack (pthread_attr_t* attr,void** stackaddr, size_t* stacksize);
以上所有函数成功返回0,失败返回错误码。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define __USE_GNU
#include <pthread.h>

int printattrs (pthread_attr_t* attr) 
{
	printf("------- 线程属性 -------\n");

	int detachstate;
	int error = pthread_attr_getdetachstate (attr, &detachstate);
	if (error) 
	{
		fprintf (stderr, "pthread_attr_getdetachstate: %s\n",strerror (error));
		return -1;
	}
	printf("分离状态:  %s\n",
		(detachstate == PTHREAD_CREATE_DETACHED) ? "分离线程" :
		(detachstate == PTHREAD_CREATE_JOINABLE) ? "可汇合线程" :
		"未知");

	int scope;
	if ((error = pthread_attr_getscope (attr, &scope)) != 0) 
	{
		fprintf (stderr, "pthread_attr_getscope: %s\n",
			strerror (error));
		return -1;
	}
	printf ("竞争范围:  %s\n",
		(scope == PTHREAD_SCOPE_SYSTEM)  ? "系统级竞争" :
		(scope == PTHREAD_SCOPE_PROCESS) ? "进程级竞争" : "未知");

	int inheritsched;
	if ((error = pthread_attr_getinheritsched (attr,
		&inheritsched)) != 0) 
	{
		fprintf (stderr, "pthread_attr_getinheritsched: %s\n",
			strerror (error));
		return -1;
	}
	printf ("继承特性:  %s\n",
		(inheritsched == PTHREAD_INHERIT_SCHED)  ? "继承调用属性" :
		(inheritsched == PTHREAD_EXPLICIT_SCHED) ? "显式调用属性" :
		"未知");

	int schedpolicy;
	if ((error = pthread_attr_getschedpolicy(attr,&schedpolicy)) != 0) 
	{
		fprintf (stderr, "pthread_attr_getschedpolicy: %s\n",strerror (error));
		return -1;
	}
	printf ("调度策略:  %s\n",
		(schedpolicy == SCHED_OTHER) ? "普通" :
		(schedpolicy == SCHED_FIFO)  ? "先进先出" :
		(schedpolicy == SCHED_RR)    ? "轮转" : "未知");

	struct sched_param schedparam;
	if ((error = pthread_attr_getschedparam (attr, &schedparam)) != 0) 
	{
		fprintf (stderr, "pthread_attr_getschedparam: %s\n",strerror (error));
		return -1;
	}
	printf ("调度优先级:%d\n", schedparam.sched_priority);

	size_t guardsize;
	if ((error = pthread_attr_getguardsize(attr, &guardsize)) != 0) 
	{
		fprintf (stderr, "pthread_attr_getguardsize: %s\n",strerror (error));
		return -1;
	}
	printf ("栈尾警戒区:%u字节\n", guardsize);
	/*
	void* stackaddr;
	if ((error = pthread_attr_getstackaddr (attr, &stackaddr)) != 0) 
	{
		fprintf (stderr, "pthread_attr_getstackaddr: %s\n",strerror (error));
		return -1;
	}
	printf ("栈地址:    %p\n", stackaddr);

	size_t stacksize;
	if ((error = pthread_attr_getstacksize (attr, &stacksize)) != 0) 
	{
		fprintf (stderr, "pthread_attr_getstacksize: %s\n",strerror (error));
		return -1;
	}
	printf ("栈大小:    %u字节\n", stacksize);
	*/
	void* stackaddr;
	size_t stacksize;
	if ((error = pthread_attr_getstack (attr, &stackaddr,&stacksize)) != 0) 
	{
		fprintf (stderr, "pthread_attr_getstack: %s\n",strerror (error));
		return -1;
	}
	printf ("栈地址:    %p\n", stackaddr);
	printf ("栈大小:    %u字节\n", stacksize);

	printf("------------------------\n");

	return 0;
}

void* thread_proc (void* arg) 
{
	pthread_attr_t attr;
	int error = pthread_getattr_np (pthread_self (), &attr);
	if (error) 
	{
		fprintf (stderr, "pthread_getattr_np: %s\n", strerror (error));
		exit (EXIT_FAILURE);
	}

	if (printattrs (&attr) < 0)
		exit (EXIT_FAILURE);

	exit (EXIT_SUCCESS);

	return NULL;
}

int main (int argc, char* argv[]) 
{
	int error;
	pthread_attr_t attr, *pattr = NULL;

	if (argc > 1) 
	{
		if (strcmp (argv[1], "-s")) 
		{
			fprintf (stderr, "用法:%s [-s]\n", argv[0]);
			return -1;
		}

		if ((error = pthread_attr_init (&attr)) != 0) 
		{
			fprintf (stderr, "pthread_attr_init: %s\n",strerror (error));
			return -1;
		}

		if ((error = pthread_attr_setdetachstate (&attr,PTHREAD_CREATE_DETACHED)) != 0) 
		{
			fprintf (stderr, "pthread_attr_setdetachstate: %s\n",strerror (error));
			return -1;
		}

		if ((error = pthread_attr_setinheritsched (&attr,PTHREAD_EXPLICIT_SCHED)) != 0) 
		{
			fprintf (stderr, "pthread_attr_setinheritsched: %s\n",strerror (error));
			return -1;
		}

		if ((error = pthread_attr_setstacksize (&attr, 4096*10)) != 0) 
		{
			fprintf (stderr, "pthread_attr_setstack: %s\n",strerror (error));
			return -1;
		}

		pattr = &attr;
	}

	pthread_t tid;
	if ((error = pthread_create (&tid, pattr, thread_proc,NULL)) != 0) 
	{
		fprintf (stderr, "pthread_create: %s\n", strerror (error));
		return -1;
	}

	if (pattr)
	{
		if ((error = pthread_attr_destroy (pattr)) != 0) 
		{
			fprintf (stderr, "pthread_attr_destroy: %s\n",strerror (error));
			return -1;
		}
	}

	pause ();
	return 0;
}
te: %s\n",strerror (error));
			return -1;
		}

		if ((error = pthread_attr_setinheritsched (&attr,PTHREAD_EXPLICIT_SCHED)) != 0) 
		{
			fprintf (stderr, "pthread_attr_setinheritsched: %s\n",strerror (error));
			return -1;
		}

		if ((error = pthread_attr_setstacksize (&attr, 4096*10)) != 0) 
		{
			fprintf (stderr, "pthread_attr_setstack: %s\n",strerror (error));
			return -1;
		}

		pattr = &attr;
	}

	pthread_t tid;
	if ((error = pthread_create (&tid, pattr, thread_proc,NULL)) != 0) 
	{
		fprintf (stderr, "pthread_create: %s\n", strerror (error));
		return -1;
	}

	if (pattr)
	{
		if ((error = pthread_attr_destroy (pattr)) != 0) 
		{
			fprintf (stderr, "pthread_attr_destroy: %s\n",strerror (error));
			return -1;
		}
	}

	pause ();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值