初识 Linux线程

再学习完Linux进程后,本期,我们来讲解Linux线程

1.为什么需要线程

在之前学习进程前,我们写的所有代码几乎都是单个执行流的,也就是说我们的代码只有一条路走.

在学习进程后,我们可以通过fork进行进程创建,给进程分配任务进行多执行流执行任务,问题来了

那我们为什么还需要线程呢

1.线程是什么,线程的特性(在Linux下)

1.相对于进程与进程之间,一个进程下的线程与线程之间都是共享该进程的大部分地址空 间,也就共 享了大部分进程数据

2.一切进程至少 都有一个执行线程

3.线程在进程内部运行 ,本质是在进程地址空间内运行

4.在Linux系统中,在CPU眼中,看到的都是进程 ,PCB都要比传统的进程更加轻量化

5.透过进程虚拟地址空间,线程之间可以看到进程的大部分资源,将进程资源合理分配给每个执行流,就形成了线程执行流

1.对比windows

在Linux下,单叫线程可能并不准确,我们更愿意称之为轻量级进程,相对于Windows而言,Linux的线程就优雅许多

**Windows:**对于线程的管理是单独额外管理,明确的区分线程和进程,对线程也就单独组织,进程中再用指针指向组织线程的地址.

Linux:线程之间共享进程地址空间,在一个程序里的一个执行路线就叫做线程(thread)。更准确的定义是:线程是"一个进程内部的控制序列",也就是轻量级进程,而轻量级进程之间会共享进程地址空间

所以也就相当于Linux中是没有线程的,只存在轻量级进程,线程只是用户级的说法

2.线程(轻量级进程) 轻量在什么地方

由于在Linux下线程为成为轻量级进程更为恰当,下文我就直接称为轻量级进程了

首先,对于cpu来说,它看到的都是进程,轻量级进程也就是一个**更加轻量化的task_struct,**他们和进程并无巨大差别,轻量级进程会轻量在以下地方

  1. 进程地址空间: 轻量级进程与其所属进程共享相同的地址空间。这意味着它们可以访问相同的内存区域,包括代码段、数据段等。

  2. 内核数据结构: 轻量级进程在内核中通常表示为与父进程相同的数据结构,只是某些字段可能会有所不同,例如栈指针、指令指针等。

  3. 文件描述符: 轻量级进程与其父进程共享相同的文件描述符表。这意味着它们可以访问相同的文件、管道、套接字等。

  4. 进程控制块(PCB): 轻量级进程的 PCB 通常与父进程的 PCB 共享很多信息,例如进程 ID、进程状态等。

需要注意的是,每一个轻量级进程都会有自己的独立栈(用户栈) ,这样轻量级进程之间即使调用函数也不会互相干扰.

3.线程间切换

由于在Linux中线程之间是共享进程地址空间 的,而在cpu中,有一块cache缓存 ,然后cpu中的寄存器 会从cache缓存拿数据,它会缓存进程的上下文代码数据 ,大概一般都会有几十 KB 到几 MB左右(还挺大的),所以再进行线程切换的时候,线程不需要 再重新让cache缓存重新加载新的代码数据,这样就不需要冷加载,线程间切换效率也会大大提升

Linux下线程的相关函数

1.pthread_t

创建一个线程单独的线程tid

2. pthread_create

功能:创建一个线程

参数

thread:返回线程ID

attr:设置线程的属性,attr为NULL表示使用默认属性

start_routine:是个函数地址,线程启动后要执行的函数

arg:传给线程启动函数的参数

返回值:成功返回0;失败返回错误码

3.pthread_join

功能:用于等待一个线程结束

参数:

thread:线程ID

retval:拿到线程退出码(这里是二级指针哦)

4.pthread_exit

功能:用于线程自己退出

参数

retval:retval不要指向一个局部变量。

返回值:无返回值,跟进程一样,线程结束的时候无法返回到它的调用者(自身)

使用示例:

cpp 复制代码
#include <iostream>
#include <unistd.h>
#include <pthread.h>
using namespace std;
void *func1(void *args)
{
    string threadname = (char *)args;
    cout << threadname << endl;
    int cnt = 5;
    while (cnt--)
    {
        sleep(1);
        cout <<"I'm thread pid::"<< getpid() << endl;
    }
    // return (void*)123;
    pthread_exit((void *)123); // 线程退出
}

int main()
{
    pthread_t tid;
    pthread_create(&tid, nullptr, func1, (void *)"pthread1");

    int cnt = 10;
    while (cnt--)
    {
        cout <<"I'm main pid::"<< getpid() << endl;
        sleep(1);
    }
    // 主线程
    void *ret = nullptr; // 拿到线程退出码
    int n = pthread_join(tid, &ret);
    std::cout << "main thread quit, n=" << n << " main thread get a ret: " << (long long)ret << std::endl; // void*8个字节
    return 0;
}
相关推荐
EricWang1358几秒前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端
我是谁??2 分钟前
C/C++使用AddressSanitizer检测内存错误
c语言·c++
成都古河云25 分钟前
智慧场馆:安全、节能与智能化管理的未来
大数据·运维·人工智能·安全·智慧城市
算法与编程之美27 分钟前
文件的写入与读取
linux·运维·服务器
发霉的闲鱼36 分钟前
MFC 重写了listControl类(类名为A),并把双击事件的处理函数定义在A中,主窗口如何接收表格是否被双击
c++·mfc
小c君tt39 分钟前
MFC中Excel的导入以及使用步骤
c++·excel·mfc
xianwu5431 小时前
反向代理模块
linux·开发语言·网络·git
xiaoxiao涛1 小时前
协程6 --- HOOK
c++·协程
Amelio_Ming1 小时前
Permissions 0755 for ‘/etc/ssh/ssh_host_rsa_key‘ are too open.问题解决
linux·运维·ssh
心灵彼岸-诗和远方1 小时前
Devops业务价值流:软件研发最佳实践
运维·产品经理·devops