【Linux】线程的内核级理解&&详谈页表以及虚拟地址到物理地址之间的转化

一、线程的概念

对于进程来说, 进程创建时间和空间成本较高,因为进程是承担分配系统资源的基本实体所以线程的出现就成为了必然。Linux线程与进程非常相似,Linux设计者在设计之初觉得如果再为线程设计数据结构和调度算法就会使整个系统变得十分复杂。 地址空间和地址空间上的虚拟地址,本质就是一种资源,所以线程就在进程的基础上让不同的线程看到进程地址空间上的代码区中的不同代码,并让不同线程去执行不同的代码,这样同样也实现了线程的功能不同的线程在同一个进程地址空间中运行,共享相同的内存和其他资源。所以说 线程是进程内部的一个执行分支,线程也是CPU调度的基本单位

每个线程都有一个与之关联的task_struct结构体,该结构体包含了线程的状态信息、调度信息、资源使用情况等。CPU在执行调度的时候,根本就不用区分进程和线程,反正你们都有task_struct结构体,都是执行流。 Linux中所有的可调度执行流都叫做轻量级进程

二、详谈页表以及虚拟地址到物理地址之间的转化

磁盘中的数据块和内存中的数据块都是4kb大小。为了管理内存中每一块4kb大小的内存块,操作系统内核中会有描述该内存块的结构体,4GB的内存大小中就有1048576个内存块,再利用数组就能将整个内存管理起来,对于内存的管理就变成了对于数组的增删查改。所以, 操作系统进行内存管理的基本单位就是4kb

再谈页表,其实页表并不是只有一块数据结构,而是分为了页目录,页表。一个虚拟地址有32位,32位中的前10位用来表示处于页目录中的哪一个位置,页目录中最多可以存放个页表的首地址,第11到20位用来表示处于页表的哪一个页表项,一个页表中最多也有个页表项, 一个页表项就对应内存中的一个4kb大小的数据块**。最后12位用来确定数据块中的字节,刚好就是4kb,正好可以确定是哪一个字节,所以后12位也叫做** 页内偏移

如果再在页表项中加入访问权限审查,有没有被使用过等等标志位,就能对用户操作进行一些审查以及拦截,来保证内存访问的安全性。

针对页表的这一种分页存储的模式,我们所写的函数编译完就是一块一块的虚拟地址,根据函数名就可以找到函数入口地址,各个函数就分配得到了不同的虚拟地址,也就是得到了不同的页表区域。同样的,我们只要给不同的线程分配不同的页表区域,就可以让不同的线程能够访问到页表的不同子集,进一步的,就可以让不同的线程访问到不同的代码,从而实现多线程技术。

三、创建线程的小例子

thread:这是一个指向pthread_t类型的指针,用于获取新创建线程的线程ID。在调用pthread_create后,这个指针会被设置为新线程的ID。

attr:这是一个指向pthread_attr_t类型的指针,用于设置线程的属性,如栈大小、优先级等。如果这个参数为NULL,那么线程将使用默认的属性。通常情况下,如果你不需要设置特殊的线程属性,可以传递NULL。

start_routine:这是一个函数指针,指向线程开始执行时要调用的函数。这个函数通常被称为线程的"入口点"或"启动例程"。

arg:用于向线程的启动例程传递参数。你可以通过这个参数向线程传递任何类型的数据。如果你的启动例程不需要任何参数,可以传递NULL。

3.1、主函数

cpp 复制代码
#include <iostream>
#include <unistd.h>
#include <pthread.h>
using namespace std;

void* newthread(void*)
{
    while (true)
    {
        cout << 22222222 << endl;
        sleep(1);
    }
    
}

int main()
{
    pthread_t pthread;
    pthread_create(&pthread, nullptr, newthread, nullptr);
    while(true)
    {
        cout << 11111111 << endl;
        sleep(1);
    }
    return 0;
}

3.2、makefile

cpp 复制代码
myThread:testThread.cc
	g++ -o $@ $^ -std=c++11 -lpthread
.PHONY:clean
clean:
	rm -f myThread

可以看到两个线程就同时跑起来了:

相关推荐
小张成长计划..1 小时前
【Linux】10:冯·诺依曼体系结构和操作系统
linux·运维·服务器
喜欢的名字被抢了2 小时前
Python实战:SQLAlchemy ORM与FastAPI项目集成
开发语言·python·sql·教程·fastapi
遨游DATA4 小时前
Spring Boot 启动失败排查:如何区分多 Bean 冲突与清理阶段异常
java·spring boot·后端
IT_陈寒4 小时前
Java线程池这个坑我算是踩明白了
前端·人工智能·后端
掉头发的王富贵4 小时前
我来入职新公司两个月了,为什么只写了100行代码?
后端·ai编程
从零开始的代码生活_4 小时前
C++ 内存管理:从内存分区到 new/delete 底层原理
开发语言·c++·后端
悦儿遥遥雨14 小时前
PXE + Kickstart 无人值守批量部署系统
linux·javascript·nginx
31535669135 小时前
Superpowers:GPT-5.6 时代下的流程毒瘤
前端·后端
wabs6665 小时前
关于单调栈【力扣739.每日温度的思考】
java·开发语言
AOwhisky5 小时前
Python 学习笔记(第三期)——流程控制核心知识点自测与详解
开发语言·笔记·python·学习·云原生·运维开发·流程控制