linux下线程有关的概念

 1.线程的概念
        线程依赖于进程而存在,线程运行所需的系统资源全部都是进程给它的
        线程和进程都是为了实现多任务的并发执行
     主线程:创建线程的那个主函数,叫做主线程
     子线程:创建出来的线程,叫做子线程

   2.linux提供线程有关的接口函数
        (1)创建子线程
              #include <pthread.h>
              int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
                        参数:thread --》存放线程ID号
                              attr --》存放线程属性,单独讨论,暂时不用理会
                              void *(*start_routine) (void *) --》函数指针,线程的任务函数(你创建线程需要完成的任务就靠它来实现)
                              arg --》传递给第三个参数的
                              

              Compile and link with -pthread.  //使用多线程编译的时候需要链接线程库
         (2)线程的退出
              void pthread_exit(void *retval);
                         参数:retval --》保存线程退出的信息,void *表明可以返回任何变量的地址
            线程的回收
              int pthread_join(pthread_t thread, void **retval); 晕针
                         参数:thread --》线程的ID号
                               retval --》二级指针,存放线程退出时候返回的信息
              pthread_join会阻塞主函数,等待子线程退出,如果你的子线程一直不退出,该函数会一直阻塞
         (3)线程的取消 --》干掉线程
              int pthread_cancel(pthread_t thread);
                         参数:thread --》线程的ID号
            设置线程的取消状态
                   有两种状态:可以取消和不可以取消
                   默认情况下线程是可以取消的
                   int pthread_setcancelstate(int state, int *oldstate);
                             参数: state --》PTHREAD_CANCEL_ENABLE  能取消 
                                              PTHREAD_CANCEL_DISABLE 不能取消
                                    oldstate --》备份线程原本的取消状态
            设置线程的取消类型
                   前提条件是线程是能够被取消的
                   取消类型有两种:立即取消和延时取消
                   立即取消: 调用pthread_cancel函数成功,子线程立马挂掉
                   延时取消: 调用pthread_cancel函数成功,子线程不会立马退出,会继续往后执行,直到遇到取消点函数才结束
                   取消点函数:man  7  pthreads 查看所有的取消点函数 
                   int pthread_setcanceltype(int type, int *oldtype);  
                             参数:type --》PTHREAD_CANCEL_DEFERRED      延时取消
                                            PTHREAD_CANCEL_ASYNCHRONOUS  立即取消 
                                   oldtype --》备份线程原本的取消类型
          (4)线程取消时候要调用执行的例程函数
                   push()和pop()必须成对使用
                   原理和作用: 但一个线程被取消的时候,push的第一个参数指向的函数会被自动调用
                   void pthread_cleanup_push(void (*routine)(void *), void *arg); 
                            参数:void (*routine)(void *) --》线程被取消的时候,需要执行的例程函数
                                  arg --》传递给routine的参数
                   void pthread_cleanup_pop(int execute);
                            参数:execute --》  0  出栈,但不执行routine指向的函数
                                              非0  出栈,执行routine指向的函数
              总结:如果你不想线程被干掉(取消)
                         方法一:pthread_setcancelstate()把线程设置成不可以被取消
                         方法二:push和pop配合,但线程被取消的时候,去执行push第一个参数指向的函数,接着完成其它任务

 线程的创建

#include "myhead.h"
//自定义函数来表示线程的任务函数
void *fun(void *arg)
{
	//代表的就是子线程的代码
	while(1)
	{
		printf("我是子线程,我帮你杀毒!\n");
		sleep(1);
	}
}
int main() //主线程
{
	pthread_t id;
	//创建子线程--》帮助我杀毒
	pthread_create(&id,NULL,fun,NULL);
	
	//我自己--》清除垃圾
	while(1)
	{
		printf("我自己清除垃圾!\n");
		sleep(1);
	} 
}

线程的退出与回收错误写法

#include "myhead.h"


//线程的任务函数
void *fun(void *arg)
{
	int a=666; //局部变量--》栈空间--》函数结束的时候会自动释放它地址
	printf("线程已经开始运行了\n");
	
	//结束线程
	pthread_exit(&a); //表示线程退出的时候,留下一个整数的地址给主函数(有问题,a的地址函数fun结束的时候被释放了)
}

int main()
{
	//二级指针--》降级成一级指针
	void *buf;
	
	pthread_t id;
	//创建一个线程
	pthread_create(&id,NULL,fun,NULL);

	//回收子线程
	pthread_join(id,&buf);
	printf("我成功回收到了子线程,子线程留下来信息是:%d\n",*((int *)buf));
}

线程的回收与退出正确写法

#include "myhead.h"


//线程的任务函数
void *fun(void *arg)
{
	int *a=malloc(sizeof(int)); //堆空间--》函数结束的时候不会自动释放它地址
	*a=666;
	printf("线程已经开始运行了\n");
	
	//结束线程
	pthread_exit(a); //表示线程退出的时候,留下一个地址给主函数(没有有问题,堆空间没有释放)
}

int main()
{
	//二级指针--》降级成一级指针
	void *buf;
	
	pthread_t id;
	//创建一个线程
	pthread_create(&id,NULL,fun,NULL);

	//回收子线程
	pthread_join(id,&buf);
	printf("我成功回收到了子线程,子线程留下来信息是:%d\n",*((int *)buf));
}

线程的退出与回收不留下任何信息

#include "myhead.h"


//线程的任务函数
void *fun(void *arg)
{
	printf("线程已经开始运行了\n");
	
	//结束线程
	pthread_exit(NULL); //表示线程退出的时候,不留下任何一片云彩
}

int main()
{

	pthread_t id;
	//创建一个线程
	pthread_create(&id,NULL,fun,NULL);

	//回收子线程
	pthread_join(id,NULL);
}

留下字符串

#include "myhead.h"


//线程的任务函数
void *fun(void *arg)
{
	printf("线程已经开始运行了\n");
	
	//结束线程
	pthread_exit("我退出了"); //表示线程退出的时候,留下一个字符串给主函数
}

int main()
{
	//二级指针--》降级成一级指针
	void *buf;
	
	pthread_t id;
	//创建一个线程
	pthread_create(&id,NULL,fun,NULL);

	//回收子线程
	pthread_join(id,&buf);
	printf("我成功回收到了子线程,子线程留下来信息是:%s\n",(char *)buf);
}

线程的取消

#include "myhead.h"


//线程的任务函数
void *fun(void *arg)
{
	while(1)
	{
		printf("子线程正在运行!\n");
		sleep(1);
	}
}

int main()
{
	pthread_t id;
	//创建一个线程
	pthread_create(&id,NULL,fun,NULL);
	
	//延时5秒后,取消刚才创建的那个线程
	sleep(5);
	pthread_cancel(id);

	//回收子线程
	pthread_join(id,NULL);
}

线程设置取消类型

#include "myhead.h"


//线程的任务函数
void *fun(void *arg)
{
	//设置子线程立即取消
	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
	while(1)
	{
		printf("子线程正在运行!\n");
		sleep(1);
	}
}

int main()
{
	pthread_t id;
	
	//创建一个线程
	pthread_create(&id,NULL,fun,NULL);
	//延时5秒后,取消刚才创建的那个线程
	sleep(5);
	pthread_cancel(id);

	//回收子线程
	pthread_join(id,NULL);
}
#include "myhead.h"


//线程的任务函数
void *fun(void *arg)
{
	//设置当前子线程不可以被取消
	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
	while(1)
	{
		printf("子线程正在运行!\n");
		sleep(1);
	}
}

int main()
{
	pthread_t id;
	
	//创建一个线程
	pthread_create(&id,NULL,fun,NULL);
	//延时5秒后,取消刚才创建的那个线程
	sleep(5);
	pthread_cancel(id);

	//回收子线程
	pthread_join(id,NULL);
}

理解线程创建最后一个参数的使用

#include "myhead.h"

struct student
{
	char name[20];
	int age;
};

struct uuu
{
	int a;
	float b;
	char c[20];
	struct student stu;
};
//线程的任务函数
void *fun(void *arg)
{
	//printf("线程已经开始运行了,主函数传递过来的参数是:%d\n",*((int *)arg));
	//printf("线程已经开始运行了,主函数传递过来的参数是:%f\n",*((float *)arg));
	//printf("线程已经开始运行了,主函数传递过来的参数是:%s\n",(char *)arg);
	//struct student *p=(struct student *)arg;
	//printf("线程已经开始运行了,主函数传递过来的参数是:%s    %d\n",p->name,p->age);
	
	//上面两句话压缩成一句话
	//printf("线程已经开始运行了,主函数传递过来的参数是:%s    %d\n",((struct student *)arg)->name,((struct student *)arg)->age);

	
	struct uuu *q=(struct uuu *)arg;
	printf("传递的信息:%d   %f   %s   %s   %d\n",q->a,q->b,q->c,q->stu.name,q->stu.age);
}

int main()
{
	int a=999;
	float b=98.7;
	char c[20]="hello";
	struct student stu={"张三",18};
	
	struct uuu u;
	u.a=8996;
	u.b=45.6;
	strcpy(u.c,"gec");
	strcpy(u.stu.name,"李四");
	u.stu.age=19;
	
	pthread_t id;
	//创建一个线程
	//pthread_create(&id,NULL,fun,&a);
	//pthread_create(&id,NULL,fun,&b);
	//pthread_create(&id,NULL,fun,c);
	//pthread_create(&id,NULL,fun,&stu);
	pthread_create(&id,NULL,fun,&u);
	while(1); //防止主线程退出,导致子线程挂掉了
}

push和pop的使用

#include "myhead.h"

void endfun(void *arg)
{
	printf("当线程被取消的时候,该函数会被调用!\n");
}

//线程的任务函数
void *fun(void *arg)
{
	pthread_cleanup_push(endfun,NULL);
	while(1)
	{
		printf("子线程正在运行!\n");
		sleep(1);
	}
	pthread_cleanup_pop(0);
}

int main()
{
	pthread_t id;
	//创建一个线程
	pthread_create(&id,NULL,fun,NULL);
	
	//延时5秒后,取消刚才创建的那个线程
	sleep(5);
	pthread_cancel(id);

	//回收子线程
	pthread_join(id,NULL);
}

pop参数设置0和非0的区别

#include "myhead.h"

void endfun(void *arg)
{
	printf("当线程被取消的时候,该函数会被调用!\n");
}

//线程的任务函数
void *fun(void *arg)
{
	int i;
	pthread_cleanup_push(endfun,NULL);
	for(i=0; i<10; i++)
	{
		printf("子线程正在运行!\n");
		sleep(1);
	}
	//pthread_cleanup_pop(0);  //出栈,但不执行endfun()
	pthread_cleanup_pop(12);   //出栈,执行endfun()
}

int main()
{
	pthread_t id;
	//创建一个线程
	pthread_create(&id,NULL,fun,NULL);
	
	//回收子线程
	pthread_join(id,NULL);
}

prctl(PR_SET_NAME, (unsigned long)"xx");

    prctl(PR_GET_NAME, name);

给当前线程取名字

#include <stdio.h>
#include <pthread.h>
#include <sys/prctl.h>
#include <stdlib.h>
#include <unistd.h>

void* tmain(void* arg) {
    char name[32];
    prctl(PR_SET_NAME, (unsigned long)"xx");
    prctl(PR_GET_NAME, name);
    printf("%s\n", name);

    while (1) {
        prctl(PR_GET_NAME, name);
        printf("%s\n", name);
        usleep(100000);
    }
}

int main(void) {
    pthread_t tid;
    pthread_create(&tid, NULL, tmain, NULL);
    pthread_join(tid, NULL);

    return 0;
}

 ps -L -p pid

查看线程的名字

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hqb_newfarmer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值