栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

线程学习一(线程概念、创建、终止、收尸,栈的清理)

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

线程学习一(线程概念、创建、终止、收尸,栈的清理)

1、线程概念:

线程就是一个正在运行的函数
一个进程里面至少会有一个线程
多个线程的内存是共享的
posix线程是一套标准,不是实现
openmp线程也是一种标准

线程标识:pthread_t(类型不清楚,但是在Linux下是整形数)
相关函数介绍:
pthread_equal():
pthread_equal - compare thread IDs

	#include 

   	int pthread_equal(pthread_t t1, pthread_t t2);

  	Compile and link with -pthread.(编译或者链接的时候要加上-pthread)

写到makefile文件中
CFLAGS+=-pthread
LDFLAGS+=-pthread

pthread_self():(相当于进程中的get_pid)
pthread_self - obtain ID of the calling thread(获取当前线程的id

   	#include 

   	pthread_t pthread_self(void);

   	Compile and link with -pthread.

小的点:
ps axm(Linux可以看到进程的详细信息,可以看到–标识,就是线程)
ps ax -L(以Linux的形式查看进程和线程的关系)
Linux下以线程消耗进程号
会话是容器,承载进程组
进程组是容器,承载进程
进程是容器,承载线程
都有一种容器的概念
建议:不要把线程和信号大范围的混用

2、线程的创建

pthread_create():
pthread_create - create a new thread

	#include 
	
  	 int pthread_create(pthread_t *thread, const pthread_attr_t *attr(NULL表示默认),
                      void *(*start_routine) (void *)(函数,就是创建出的线程函数), void *arg)(函数的参数,若想传多个参数就使用结构体);
   	Compile and link with -pthread.

返回值
On success, pthread_create() returns 0; on error, it returns an error
number, and the contents of *thread are undefined.(只能用strerror来报错
例子:

#include 
#include 
#include 

static void *func(void *p)
{

        puts("Thread is working!");
        return NULL;
}


int main()
{

        pthread_t tid;
        int err;

        puts("Beigin!");

        err=pthread_create(&tid,NULL,func,NULL);
        if(err)
        {
                fprintf(stderr,"pthread_create():%sn",strerror(err));
                exit(1);
        }
        puts("End!");
        exit(0);
}

运行结果:
Beigin!
End!
看不到线程运行的原因:线程的调度取决于调度器的调度策略,在虚拟机里面不能多核运行线程来不及调度,进程就结束。(在不同的主机上运行结果不同)

线程终止
3种方式: 1)线程从启动例程返回,返回值就是线程的退出码。
		  2)线程被同一进程中的其他的线程取消
		  3)线程调用调用pthread_exit()函数(相当于进程阶段的exit()函数)

pthread_exit():
pthread_exit - terminate calling thread

 #include 

 	  void pthread_exit(void *retval);

   	Compile and link with -pthread.

例子:

static void *func(void *p)
{

        puts("Thread is working!");
        pthread_exit(NULL);//线程栈的清理用到

}
线程收尸

pthread_join();(相当于进程中的wait())
pthread_join - join with a terminated thread

#include 

 	  int pthread_join(pthread_t thread, void **retval);
第二项若是空,就表示只收尸,不关注状态
若是想把收尸的状态来加以查看的话,给一个void*类型变量的地址(一级指针的地址)
   	Compile and link with -pthread.

例子:
将上面的main函数中增加pthread_join()函数的使用

int main()
{

        pthread_t tid;
        int err;

        puts("Beigin!");

        err=pthread_create(&tid,NULL,func,NULL);
        if(err)
        {
                fprintf(stderr,"pthread_create():%sn",strerror(err));
                exit(1);
        }
        pthread_join(tid,NULL);
        puts("End!");
        exit(0);
}

运行结果:(这个结果是一定的)
一定要等到线程运行完,才可以收尸,所以一定会运行线程。
Beigin!
Thread is working!
End!

栈的清理
pthread_cleanup_push():
pthread_cleanup_pop():(和钩子函数很像,或者可以想象栈的压和出)

pthread_cleanup_push():
pthread_cleanup_pop():
pthread_cleanup_push, pthread_cleanup_pop - push and pop thread cancel‐
lation clean-up handlers

#include 

   	void pthread_cleanup_push(void (*routine)(void *),
  	                           void *arg);
   	void pthread_cleanup_pop(int execute);
pop函数的参数若为真,说明函数要被调用,反之不被调用
   	Compile and link with -pthread.

例子:

#include 
#include 
#include 

static void cleanup_func(void *p)
{
        puts(p);
}

static void *func(void *p)
{

        puts("Thread is working!");
        pthread_cleanup_push(cleanup_func,"cleanup:1");
        pthread_cleanup_push(cleanup_func,"cleanup:2");
        pthread_cleanup_push(cleanup_func,"cleanup:3");

        puts("push over");
	pthread_cleanup_pop(1);
       	pthread_cleanup_pop(1);
         	pthread_cleanup_pop(1);
      	pthread_exit(NULL);
}

int main
{
        pthread_t tid;
        int err;

        puts("Beign");

        err=pthread_create(&tid,NULL,func,NULL);
        if(err)
        {
                 fprintf(stderr,"pthread_create():%sn",strerror(err));
                 exit(1);
        }
        pthread_join(tid,NULL);
        puts("End");
        exit(0);

}

运行结果:
Beign
Thread is working!
push over
cleanup:3
cleanup:2
cleanup:1
End

注意:push和pop一定是成对出现的,这两个不是函数,而是宏,可以用gcc .c文件 -E来验证,若是少了pop预处理的结果就会
少一个大括号匹配。若pop的参数为0,则表示只弹栈,而不去调用。比如上面的程序,若只有第一个pop参数是1,则结果只会
包含cleanup:3。pop可以放在任何的位置。若是放在pthread_exit后面,执行的时候,由于看不到后面的参数,默认都为1.

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/868709.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号