【Linux】线程概念,线程控制。

本文介绍了线程的基本概念,包括线程的创建、退出、等待等关键操作,并提供了具体的代码示例来展示线程如何在Linux环境下运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

线程概念:

线程控制:

创建线程:

线程退出:

线程等待:



线程概念:

操作系统分配资源以进程为基本单位。而线程是进程的组成部分,它代表了一条顺序的执行流,每个进程至少有一个执行流。线程是cpu调度的最小单位,同类的多个线程共享同一块虚拟地址空间和页表。假如有一个程序它由fun1()fun2()fun3()三个函数组成。该程序运行起来后,操作系统为他分配相应的资源,pcb块,虚拟地址空间,页表等如下图所示。

 

这样会按顺序执行 fun1() fun2() fun3(),但是如果想并发执行 这三个函数,提高效率时。可以对每个函数建立一个进程并发执行,同时也要创建每个进程的虚拟地址空间与页表, 这样在程序运行时会对性能造成不小的影响 .。而线程就是在创建出PCB的时候让这些PCB共用同一块虚拟地址空间,页表等资源,但是程序计数器,上下文数据不一样,从而去执行不同的函数,这样就大大提高了性能,如下图所示:

总结:

在linux中没有线程的概念,线程的创建是通过库函数实现的,库函数通过是模拟进程pcb实现的(如上图所示),所以linux下线程又称为轻量级进程。在传统意义上pcb是一个进程控制块,而在linux中pcb只能算一个线程控制块。进程就是多个线程的集合,每个线程是一个执行流,共享进程的大部分资源。

线程之间的独有与共享:

独有:标识符,寄存器,栈,信号屏蔽字, errno,优先级。

共享:虚拟地址空间(代码段/数据段) ,文件描述符表,信号处理的回调函数,用户ID/组ID/工作路径等

线程控制:

 

创建线程:

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

头文件:#include <pthread.h>

在编译时注意加上-lpthread参数,以调用静态链接库。因为pthread并非Linux系统的默认库

 

参数:

thread: 输出型参数,指向线程标识符的指针。

attr: 用来设置现成的属性。

start_routine:函数指针,传入线程运行函数的起始地址。注意函数指针的类型必须是void* (*)(void*) 。既:函数返回值,参数的类型都是 void* 

arg:线程运行函数的参数。

返回值:创建线程成功时,返回0,创建线程失败,返回错误号

练习程序:

#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
void* thr_start(void* ptr){
    while(1){
        printf("i am thread %s \n",(char*)ptr);
        sleep(1);
    }   
    return NULL;
}
int main(){
    char* ptr = "你好";
    pthread_t tid;
    int res = pthread_create(&tid, NULL, thr_start,(void*) ptr);//tid,线程属性设置 函数运行起始地址 函数参数
    if(res != 0){
        printf("线程创建失败");
        return -1;
    }
    while(1){
        printf("i am main thread \n");//主线程的无限次循环
        sleep(1);
    }   
    return 0;//退出进程 而非主线程。
}

 

程序这个程序主要展示线程的创建流程。主线程:创建一个线程,然后运行一个无限循环函数,创建的函数也是是一个无限循环函数。运行结果如下:

 

可以看见两个线程并行运行:此时通过命令(ps -efL | head -n 1 && ps -efL | grep pthread_create)查看进程的运行状态可以查看到两个./pthread_create

 他们的PID都一样是12467,LWP是指轻量级进程id分别是 12467 和 12468。主线程的轻量级进程id和进程id一样。

线程退出:

 

(1)

线程入口函数运行完毕,线程就会自动退出--在线程入口函数中调用return (但是main函数中return,退出的是进程而不是主线程)。

(2)

void pthread_exit(void *retval);

那个线程调用就退出哪个线程。如果是主线程调用,主线程退出。但是主线程退出并不会导致进程退出,只有所有的线程都退出了,进程才会退出。

参数:线程的退出返回值。

(3)

int pthread_cancel(pthread t thread);

根据线程tid,终止一个指定的线程;退出的线程是被动取消的

线程等待:

线程等待:等待一个线程的退出,获取退出线程的返回值,回收线程所占的资源

线程有一个属性,默认创建出来这个属性是joinable,处于这个属性的线程,退出后,需要被其它线程等待获取返回值回收资源。int pthread join(pthread t thread, void *retval); --阻塞等待指定线程退出,获取其返回值

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

thread:要等待退出的线程tid --阻塞函数,线程没有退出则一直等待。

retval:输出型参数,用于返回线程的返回值

线程的返回值是一个void*,是一个一级指针 若要通过一个函数的参数获取一级指针,就需要传入一个一级指针变量的地址进来。

默认情况下,一个线程是必须被等待,若不等待,则会造成资源泄漏

练习程序:

#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
void* thr_start(void* ptr){
    //睡两秒退出线程
    sleep(2);
    printf("这里是创建的线程\n");
    char* ptr = "这是创建线程的返回值";
    pthread_exit((void*)ptr);
}
int main(){
    pthread_t tid; 
    int res = pthread_create(&tid, NULL, thr_start, NULL);
    if(res != 0){
        printf("线程创建失败\n");
        return -1;//进程退出
    }
    char* ptr;
    pthread_join(tid,(void**)&ptr);
    printf("%s\n",(char*)ptr);
return 0;
}

运行结果:

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值