波奇学Linux:线程

2024-03-10 04:12
文章标签 linux 线程 波奇学

本文主要是介绍波奇学Linux:线程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

线程的概念

进程的一个执行分支,线程执行粒度,要比进程要细

进程的一个执行分支:线程是在进程内部执行,任何执行流都要执行,都要有资源,地址空间是进程的资源窗口,线程共享进程的地址空间。

cpu只关心执行流,对于cpu进程和线程都看作执行流。

线程是操作系统调度的基本单位

进程:内核数据结构(task_struct)+代码和数据->进程是分配操作系统资源的实体(每个线程都分配一点进程的一点资源),操作以进程为单位分配资源,但是以往进程只有一个执行流。

linux没用真正意义的线程,而是用进程模拟线程:指的是用进程的内核数据结构模拟线程,如PCB来管理线程。

线程<=执行流<=进程。

Linux中的执行流,轻量级进程

虚拟地址是如何转换为物理地址

 以32为例

32位地址会转换为10+10+12

页表结构

其中12位刚好对应2^2*2^10=4kb, 4KB刚好是物理内存数据交换的最小单位,因此无论怎么偏移会在一个最小的物理内存上。

二级页表不一定全部存在,但进程一定有页目录

当访问的二级页表不存在等情况,可以看成缺页中断

读取地址时,带类型就是为了能知道连续读取多少个字节

cr2寄存器:引起缺页中断的虚拟地址

线程分配资源就是本质分配地址空间范围

对代码地址划分,实现把不同的代码划分给不同的线程

线程比进程更加轻量化

a.创建和释放更加轻量化

b.切换更加轻量化

cpu含有一个硬件cache,缓存的热数据(高频访问的数据),切换线程的时候只用切换,不要改变cache内容,而进程切换需要重新缓存内容。

线程是有主次的,可以识别出不同的线程,并且可以识别出线程和进程

线程优缺点

线程缺点

因为大部分的数据共享的,一个线程出问题会影响其他线程或者整个进程。

线程独有数据和共享数据

一组寄存器:线程的上下文

栈:保证执行流不错乱

线程共享

代码示范

pthread线程库,在应用层,轻量级进程接口进行封装,为用户直接提供线程的接口

phread_create

thread:输出型参数

attr:线程属性,一般为nulltr

start_routine:函数指针 线程执行的入口函数 返回值为void* 参数是void*

arg:输入型参数,新线程回调线程函数的时候,需要参数,函数start_routine函数的参数

ps -aL :查看机器的轻量级的进程

LWP相当于轻量级进程的pid,当PID等于LWP,即为进程或者叫主线程

可以通过kill -9 pid/LWP 发送指令 当线程被kill了,整个进程也被kill掉

#include<pthread.h>
#include<iostream>
#include<unistd.h>
using namespace std;
//可以被多个执行流调用 函数被重入
void show(const string& name)
{cout<<name<<"say#"<<"hello thread"<<endl;
}void *threadToutine(void* args)
{while(true){cout<<"new thread,pid"<<getpid()<<endl;show("[new thread]");sleep(1);}
}
int main()
{pthread_t tid;pthread_create(&tid,nullptr,threadToutine,nullptr);//不是系统调用while(true){cout<<"main threadd,pid: "<<getpid()<<endl;show("[new thread]");sleep(1);}
}

tid是一个很大的数字

线程的等待:当线程结束时,必须在主线程等待,否则进行僵尸态

成功返回0,失败返回-1

线程入口函数start_route 的返回值是void*,我们通过void**输出型参数获得返回值

终止线程不用exit() ,终止线程用return或者pthread_exit();

pthread_exit(void*(100));

取消进程

pthread_cancel(tid);

当线程被取消了,退出返回值激素PTHREAD_CANCELED是宏,值是(void*)-1

线程函数传递类对象

class Request
{
public:Request(int start,int end, const string& threadname):start_(start),end_(end),threadname_(threadname){}
public:int start_;int end_;string threadname_;
};
class Response
{
public:Response(int result , int exitcode):result_(result),exitcode_(exitcode){}
public:int result_;int exitcode_;
};void* sumCount(void* args)
{//把void* args强转成Request*Request*rq=static_cast<Request*>(args);Response *rsp=new Response(0,0);for(int i=rq->start_;i<rq->end_;i++){cout<<rq->threadname_<<" is runing, calling... "<<i<<endl;rsp->result_+=i;usleep(10000);}delete rq;return rsp;
}
int main()
{pthread_t tid;//rq是线程指针Request *rq=new Request(1,100,"thread one");pthread_create(&tid,nullptr,sumCount,rq);void*ret;pthread_join(tid,&ret);// void* ret强转成Response*Response *rsp=static_cast<Response*>(ret);cout<<"rsp->result :"<<rsp->result_<<", exitcode: "<< rsp->exitcode_<<endl;return 0;
}

C++的原生数据库

void threadrun()
{while(true){cout<<"I am thread for C++"<<endl;sleep(1);}
}
int main()
{thread t1(threadrun);t1.join();return 0;
}

线程pid

被线程库封装,创建线程函数的底层

在底层os把线程看成执行流,和进程无异。为了方便用户管理和组织线程,在用户级别有线程控制块,相当于PCB的一种,只不过是在用户层的,PCB是在内核中

std::string toHex(pthread_t tid)
{char hex[64];snprintf(hex,sizeof(hex),"%p",tid);return hex;
}
void* threadRoutine(void* args)
{while(true){cout<<"thread id: "<<toHex(pthread_self())<<endl;sleep(1);}
}
int main()
{pthread_t tid;pthread_create(&tid,nullptr,threadRoutine,(void*)"thread 1");cout<<"main thread create thead done"<<endl;pthread_join(tid,nullptr);return 0;
}

进程地址空间

每一个线程的库级别的pcb起始地址叫做线程pid

线程栈:压栈时的临时变量

除了主线程,所有其他线程的独立栈,都在共享区,具体来讲时在pthread,tid指向的用户tcb当中

这篇关于波奇学Linux:线程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/793001

相关文章

防止Linux rm命令误操作的多场景防护方案与实践

《防止Linuxrm命令误操作的多场景防护方案与实践》在Linux系统中,rm命令是删除文件和目录的高效工具,但一旦误操作,如执行rm-rf/或rm-rf/*,极易导致系统数据灾难,本文针对不同场景... 目录引言理解 rm 命令及误操作风险rm 命令基础常见误操作案例防护方案使用 rm编程 别名及安全删除

Linux下MySQL数据库定时备份脚本与Crontab配置教学

《Linux下MySQL数据库定时备份脚本与Crontab配置教学》在生产环境中,数据库是核心资产之一,定期备份数据库可以有效防止意外数据丢失,本文将分享一份MySQL定时备份脚本,并讲解如何通过cr... 目录备份脚本详解脚本功能说明授权与可执行权限使用 Crontab 定时执行编辑 Crontab添加定

使用docker搭建嵌入式Linux开发环境

《使用docker搭建嵌入式Linux开发环境》本文主要介绍了使用docker搭建嵌入式Linux开发环境,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录1、前言2、安装docker3、编写容器管理脚本4、创建容器1、前言在日常开发全志、rk等不同

Java中如何正确的停掉线程

《Java中如何正确的停掉线程》Java通过interrupt()通知线程停止而非强制,确保线程自主处理中断,避免数据损坏,线程池的shutdown()等待任务完成,shutdownNow()强制中断... 目录为什么不强制停止为什么 Java 不提供强制停止线程的能力呢?如何用interrupt停止线程s

linux系统上安装JDK8全过程

《linux系统上安装JDK8全过程》文章介绍安装JDK的必要性及Linux下JDK8的安装步骤,包括卸载旧版本、下载解压、配置环境变量等,强调开发需JDK,运行可选JRE,现JDK已集成JRE... 目录为什么要安装jdk?1.查看linux系统是否有自带的jdk:2.下载jdk压缩包2.解压3.配置环境

Linux搭建ftp服务器的步骤

《Linux搭建ftp服务器的步骤》本文给大家分享Linux搭建ftp服务器的步骤,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录ftp搭建1:下载vsftpd工具2:下载客户端工具3:进入配置文件目录vsftpd.conf配置文件4:

python 线程池顺序执行的方法实现

《python线程池顺序执行的方法实现》在Python中,线程池默认是并发执行任务的,但若需要实现任务的顺序执行,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋... 目录方案一:强制单线程(伪顺序执行)方案二:按提交顺序获取结果方案三:任务间依赖控制方案四:队列顺序消

Linux实现查看某一端口是否开放

《Linux实现查看某一端口是否开放》文章介绍了三种检查端口6379是否开放的方法:通过lsof查看进程占用,用netstat区分TCP/UDP监听状态,以及用telnet测试远程连接可达性... 目录1、使用lsof 命令来查看端口是否开放2、使用netstat 命令来查看端口是否开放3、使用telnet

Linux系统管理与进程任务管理方式

《Linux系统管理与进程任务管理方式》本文系统讲解Linux管理核心技能,涵盖引导流程、服务控制(Systemd与GRUB2)、进程管理(前台/后台运行、工具使用)、计划任务(at/cron)及常用... 目录引言一、linux系统引导过程与服务控制1.1 系统引导的五个关键阶段1.2 GRUB2的进化优

Linux查询服务器 IP 地址的命令详解

《Linux查询服务器IP地址的命令详解》在服务器管理和网络运维中,快速准确地获取服务器的IP地址是一项基本但至关重要的技能,下面我们来看看Linux中查询服务器IP的相关命令使用吧... 目录一、hostname 命令:简单高效的 IP 查询工具命令详解实际应用技巧注意事项二、ip 命令:新一代网络配置全