linux线程管理

一、基本概念
    进程中的资源有哪些:代码的指令、只读段、全局段、静态数据段、堆、栈、命令行参数、环境变量表、执行者(线程)。
    什么线程:在进程中负责执行代码的一个单位,它是进程的一部分,一个进程至少要一个线程(主线程),进程也可以有多个线程(创建)。
    进程中的代码的指令、只读段、全局段、静态数据段、堆、命令行参数、环境变量表、文件描述符、信号处理函数等资源对线程来说都是共享,线程之间栈空间是私有的。
    
    线程是进程的一个实体,是操作系统独立调度和分派任务的基本单位。
    
二、POSIX线程
    UNIX和Linux天生骄傲(不支持线程),通过添加额外的线程库可以使用,在编译多线程代码时需要添加 -lpthread,pthread.h。
    
    对线程的操作:
        创建线程
        销毁线程
        分离线程
        联合线程
        查询线程属性
        设置线程属性
        
    对于线程来说最要的是解决脏数据问题(线程同步),对于进程来说是解决通信(IPC)问题。
    
三、创建线程
    int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
    功能:创建线程
    thread:返回值,获取线程id
    attr:返回值,获取线程属性
    start_routine:参数,注册线程的入口函数
    arg:给线程入口函数的参数
    
    1、同一个进程的多个线程都在同一个地址空间内活动,因此相对于进程,线程的系统开销小,任务切换快,它们可以执行相同的代码,也可以执行不同的代码。 
    
    2、线程间的数据交换不需要依赖于类似IPC的特殊通信机制,简单而高效,每个线程拥有自己独立的线程ID、寄存器信息、函数栈、错误码和信号掩码,线程之间存在优先级的差异。 
    
    3、main函数即主线程,main函数返回即主线程结束,主线程结束即进程结束,进程一但结束其所有的线程即结束。

    4、应设法保证在线程过程函数执行期间,其参数所指向的目标持久有效。
    
四、对线程的操作
    1、等待线程
        int pthread_join (pthread_t thread, void** retval);
        功能:等待thread参数所标识的线程结束
        retval:返回值,线程入口函数的返回值
        返回值:成功返回0,失败返回错误码。
        
        线程过程函数将所需返回的内容放在一块内存中,返回该内存的地址,要保证这块内存在函数返回后,即线程结束,以后依然有效;
        若retval参数非NULL,则pthread_join函数将线程过程函数所返回的指针,拷贝到该参数所指向的内存中;
        若线程过程函数所返回的指针指向动态分配的内存,则还需保证在用过该内存之后释放之。
        
    2、获取线程id
        pthread_t pthread_self (void);
        功能:返回当前线程的id,此函数不会执行失败。
    
    3、比较两个线程
        int pthread_equal (pthread_t t1, pthread_t t2);
        功能:比较两个id是否是同一个线程
        返回值:两个id相等,则返回非零,否则返回0。
        某些实现的pthread_t不是unsigned long int类型,可能是结构体类型,无法通过“==”判断其相等性。
        
    4、终止线程
        1) 从线程过程函数中return。
        2) 调用pthread_exit函数。
        void pthread_exit (void* retval);
        retval和线程过程函数的返回值语义相同。
        
    5、线程的执行轨迹
        1) 同步方式(非分离状态): 
        创建线程之后调用pthread_join函数等待其终止,并释放线程资源。
        2) 异步方式(分离状态): 
        无需创建者等待,线程终止后自行释放资源。

        int pthread_detach (pthread_t thread);
        功能:使线程进入分离(DETACHED)状态。
        返回值:成功返回0,失败返回错误码。
        处于分离状态的线程终止后自动释放线程资源,且不能被pthread_join函数等待。

    6、取消线程
        1) 向指定线程发送取消请求
        int pthread_cancel (pthread_t thread);
​        成功返回0,失败返回错误码。
​        注意:只是向线程发出取消请求,并不等待线程终止。

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

        state取值:
               PTHREAD_CANCEL_ENABLE:接受取消请求
               PTHREAD_CANCEL_DISABLE:忽略取消请求。
               
        3) 设置调用线程的可取消类型
        int pthread_setcanceltype (int type, int* oldtype);

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

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

上面是线程的知识点总结,下面将给出几个代码例子:

1、

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

void funcb()
{
	sleep(3);
	char* str = malloc(255);
	sprintf(str,"hello world");
	pthread_exit(str);
}

void * run(void* arg)
{
	//funcb();
	for(int i=0; i<3; i++)
	{
		printf("这是一个子线程%lu\n",pthread_self());
		sleep(1);
	}
}

int main()
{
	pthread_t tid = 0;
	int ret = pthread_create(&tid,NULL,run,NULL);
	if(0 > ret)
	{
		perror("pthread_create");
		return -1;
	}
	pthread_detach(tid);
	char* str = "我等的线程还没有来";
	pthread_join(tid,(void**)&str);
	printf("线程%lu结束,它的遗言是:%s\n",tid,str);
	//free(str);
}

2、

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

typedef struct Hehe
{
	char name[20];
	char sex;
	short age;
	char addr[128];
}Hehe;

int num = 0;
void* pthread_run(void* arg)
{
	Hehe* hehep = arg;
	while(1)
	{
		printf("我是子线程 %d\n",num++);
		printf("%s %c %hd %s\n",hehep->name,hehep->sex,hehep->age,hehep->addr);
		sleep(1);
	}
}

int main()
{
	pthread_t ptid;
	double pi = 3.14;
	Hehe hehe = {"ll",'f',18,"china"};
	int ret = pthread_create(&ptid,NULL,pthread_run,&hehe);
	if(0 > ret)
	{
		perror("pthread_create");
		return -1;
	}

	while(1)
	{
		printf("我是主线程%d\n",num++);
		sleep(1);
	}
}


总结:线程还有很多其他的例子,这里就不列举了,线程是很有用的在构建项目中,往往有很强的功能!所以要好好做掌握!

猜你喜欢

转载自blog.csdn.net/Dachao0707/article/details/81365602