半亩花草 发表于 2024-6-28 06:25:49

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

一、线程的概念

        对于进程来说,进程创建时间和空间成本较高,由于进程是承担分配体系资源的根本实体,以是线程的出现就成为了一定。Linux线程与进程非常相似,Linux设计者在设计之初以为如果再为线程设计数据结构和调度算法就会使整个体系变得十分复杂。地址空间和地址空间上的假造地址,本质就是一种资源,以是线程就在进程的底子上让差别的线程看到进程地址空间上的代码区中的差别代码,并让差别线程去实行差别的代码,如许同样也实现了线程的功能。差别的线程在同一个进程地址空间中运行,共享相同的内存和其他资源。以是说线程是进程内部的一个实行分支,线程也是CPU调度的根本单元。
        每个线程都有一个与之关联的task_struct结构体,该结构体包罗了线程的状态信息、调度信息、资源使用情况等。CPU在实行调度的时间,根本就不消区分进程和线程,反正你们都有task_struct结构体,都是实行流。Linux中全部的可调度实行流都叫做轻量级进程。
二、详谈页表以及假造地址到物理地址之间的转化

        磁盘中的数据块和内存中的数据块都是4kb大小。为了管理内存中每一块4kb大小的内存块,操作体系内核中会有描述该内存块的结构体,4GB的内存大小中就有1048576个内存块,再利用数组就能将整个内存管理起来,对于内存的管理就变成了对于数组的增删查改。以是,操作体系进行内存管理的根本单元就是4kb。
        再谈页表,其实页表并不是只有一块数据结构,而是分为了页目次,页表。一个假造地址有32位,32位中的前10位用来表现处于页目次中的哪一个位置,页目次中最多可以存放https://latex.csdn.net/eq?2%5E%7B%5E%7B10%7D%7D个页表的首地址,第11到20位用来表现处于页表的哪一个页表项,一个页表中最多也有https://latex.csdn.net/eq?2%5E%7B%5E%7B10%7D%7D个页表项,一个页表项就对应内存中的一个4kb大小的数据块。末了12位用来确定数据块中的字节,https://latex.csdn.net/eq?2%5E%7B%5E%7B12%7D%7D刚好就是4kb,恰恰可以确定是哪一个字节,以是后12位也叫做页内偏移。
https://img-blog.csdnimg.cn/direct/56e0a45be32d4f40a7bec11e1c697c99.png
https://img-blog.csdnimg.cn/direct/b13152b2374d4965b6f98f28b36cd48e.png
        如果再在页表项中加入访问权限审查,有没有被使用过等等标志位,就能对用户操作进行一些审查以及拦截,来包管内存访问的安全性。
        针对页表的这一种分页存储的模式,我们所写的函数编译完就是一块一块的假造地址,根据函数名就可以找到函数入口地址,各个函数就分配得到了差别的假造地址,也就是得到了差别的页表区域。同样的,我们只要给差别的线程分配差别的页表区域,就可以让差别的线程能够访问到页表的差别子集,进一步的,就可以让差别的线程访问到差别的代码,从而实现多线程技术。   
三、创建线程的小例子

https://img-blog.csdnimg.cn/direct/acb7beb2224444f4b695a8498f409723.png
   thread:这是一个指向pthread_t类型的指针,用于获取新创建线程的线程ID。在调用pthread_create后,这个指针会被设置为新线程的ID。

attr:这是一个指向pthread_attr_t类型的指针,用于设置线程的属性,如栈大小、优先级等。如果这个参数为NULL,那么线程将使用默认的属性。通常情况下,如果你不需要设置特别的线程属性,可以通报NULL。
 
start_routine:这是一个函数指针,指向线程开始实行时要调用的函数。这个函数通常被称为线程的“入口点”或“启动例程”。

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

#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

myThread:testThread.cc
        g++ -o $@ $^ -std=c++11 -lpthread
.PHONY:clean
clean:
        rm -f myThread 可以看到两个线程就同时跑起来了: 
https://img-blog.csdnimg.cn/direct/077faba3e7a344fcb14717ec75a53f9f.png

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 【Linux】线程的内核级理解&&详谈页表以及假造地址到物理地址之间的转化