Linux 第三十三章

🐶博主主页:@ᰔᩚ. 一怀明月ꦿ 

❤️‍🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C++,linux

🔥座右铭:“不要等到什么都没有了,才下定决心去做”

🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀

目录

线程

线程控制 

pthread_create创建线程

pthread_self

pthread_join

Pthread_exit

pthread_detach

pthread_cancel

系统库调用问题

线程的局部存储


线程

重谈一次地址空间-虚拟到物理的过程

文件系统IO的基本单位大小:4kb

内存以4GB为例,就有1048576个页框(4kb)

struct page

{

    int flag;//用于表示该页的状态和属性

    //描述一个page的使用情况

    //页框的属性

}

为了对所有的页框进行管理,所以需要一个struct page pages[1048576]的数组

线程划分页表的本质:划分地址空间

Int a=100

根据a的虚拟地址,找到a的物理地址,a是一个整形变量,偏移量就位4

在进程视角:虚拟地址本身就是资源!

线程共享进程数据,但也拥有自己的一部分数据:

线程ID
一组寄存器(每个线程有自己的独立上下文数据)
栈
errno
信号屏蔽字
调度优先级

线程控制 

pthread_create创建线程

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                   void *(*start_routine) (void *), void *arg);
这个函数的参数包括:

* thread:指向 pthread_t 类型的指针,用于存储新创建线程的标识符。
* attr:指向 pthread_attr_t 类型的指针,用于设置新线程的属性,通常可以设为 NULL 表示使用默认属性。
* start_routine:指向一个函数的指针,该函数定义了新线程要执行的任务。它的签名为 void* func(void*)。
* arg:传递给 start_routine 函数的参数。//对象/结构体

linux下有没有真正的线程?

没有。只有轻量级进程的概念,所以linux os只会提供轻量级进程创建的系统调用,不会直接提供线程创建接口

所以需要一个库pthread,这个库不属于c/c++,这个库是操作系统自带的,编译时链接我们的库

function<void()> 是 C++11 中引入的函数对象,它可以用来表示一个没有参数且没有返回值的函数。在 C++ 中,函数对象是可调用的实体,类似于函数指针,但具有更大的灵活性和功能。

事例

#include <iostream>
#include <pthread.h>
#include <string>
#include <unistd.h>
#include <functional>
#include <time.h>
#include <vector>

using namespace std;

const int threadnum = 5;
using func_t = function<void()>;

class threaddata
{
public:
threaddata(const string &name, const uint64_t &time, func_t f)

: threadname(name), createtime(time), func(f)

{
}


public:
string threadname;

uint64_t createtime;

func_t func;

};


void print()

{
cout << "我是线程执行的大任务的一部分" << endl;

}


// 新线程
void *ThreadRountine(void *args)

{
threaddata *td = static_cast<threaddata *>(args); // 安全强转threaddata*类型

while (true)

{
cout << "new thread"

<< " thread name:" << td->threadname << " thread time:" << td->createtime << endl;

td->func();
sleep(1);


//测试一个线程异常,整个进程就结束了
// int a=10;
// if(td->threadname=="thread-4")
// {
// cout<<"触发异常"<<endl;
// a/=0;
// }
}
}


// 如何给新线程传参,如何创建多线程呢
// 获取返回值


// 主线程
int main()

{
vector<pthread_t> pthreads;

for (int i = 0; i < threadnum; i++)

{
char pthreadname[64];

snprintf(pthreadname, sizeof(pthreadname), "%s-%lu", "thread", i);

pthread_t tid;

threaddata *td = new threaddata(pthreadname, (uint64_t)time(nullptr), print);

pthread_create(&tid, nullptr, ThreadRountine, td);

pthreads.push_back(tid);
sleep(1);
}


while (true)

{
cout << "main thread" << endl;

sleep(3);
}
return 0;

}

pthread_self

在Linux中,pthread_self 函数用于获取当前线程的线程ID(pthread_t)。

它的声明如下:

#include <pthread.h>
 pthread_t pthread_self(void);

调用 pthread_self 函数将返回当前线程的线程ID,即 pthread_t 类型的值。线程ID 是一个唯一标识符,用于区分不同的线程。通常情况下,你可以将线程ID存储在变量中以供后续使用。

线程终止

1. 新线程函数return。这种方法对主线程不适用,从main函数return相当于调用exit。

2. 线程可以调用pthread_exit终止自己。

3. 一个线程可以调用pthread_cancel终止同一进程中的另一个线程。

线程默认要被等待

1.线程退出,没有等待,会导致类似进程的僵尸问题

2.线程退出时,主线程如何获取新线程的返回值!

pthread_join

pthread_join 是 POSIX 线程库中的函数,用于等待指定的线程结束执行。它会阻塞当前线程,直到指定的线程完成为止。

int pthread_join(pthread_t thread, void **retval);
* thread:要等待的线程的线程 ID。
* retval:指向指针的指针,用于接收被等待线程的返回值(如果有)。

事例

#include <stdio.h>
#include <pthread.h>
void* threadFunction(void* arg) {
    printf("Inside the new thread\n");
    return (void*)42;
}
int main() {
    pthread_t thread;
    pthread_create(&thread, NULL, threadFunction, NULL); // 创建一个新线程
    // 等待新线程结束
    void* result;
    pthread_join(thread, &result);
    printf("New thread returned: %ld\n", (long)result);
    return 0;
}
在这个示例中,我们创建了一个新线程,并在主线程中调用 
pthread_join 来等待新线程结束。pthread_join 函数会将主线程阻塞直到新线程执行结束,
并且可以获取新线程的返回值。

需要注意的是,pthread_join 函数会阻塞当前线程,直到指定的线程结束。因此,在实际使用中,需要确保调用 pthread_join 的线程不是主要的执行线程,否则可能会导致整个程序被阻塞。

Pthread_exit

pthread_exit函数用于终止调用它的线程。当线程调用pthread_exit时,它会立即退出,而不会影响其他线程的执行。线程在退出时可以返回一个指向线程退出状态的指针。

例:

pthread_exit((void*)"thread_1 done");

如果线程退出出现异常呢?

如果线程出现异常,整个进程都会崩溃,所以没必要获取线程退出信号

线程的返回值,不一定返回的都是字符串,还可以是对象

线程没有非阻塞等待,线程等待很极端,要么一直等,要么不等

线程默认是:线程模式joinable的(是可以被等待的)

线程是可以被设置为分离状态的

在线程设置为分离状态后,该线程结束时系统会自动释放其所占用的资源,而不需要其他线程调用pthread_join来回收资源

pthread_detach

使用 pthread_detach 函数可以避免出现僵尸线程,提高系统效率。要使用 pthread_detach 函数,首先需要创建线程,并在创建后立即使用 pthread_detach 函数将线程设置为分离状态。

主线程可以调用pthread_detach分离新线程

新线程也可以调用pthread_detach分离自己

pthread_cancel

线程取消

Pthread_cancel(tid);

线程如果是分离的,是可以被取消的,但是不可以被等待

如果线程是被取消的,线程返回的值是-1,

全部都不是系统直接提供的接口,而是原生线程库pthread(默认是os自带的)提供的接口

linux中的线程被叫作用户级线程

系统库调用问题

线程要有独立属性

1)硬件上下文

2)栈:

新线程的栈,在库维护

默认地址空间中的栈,由主线程使用

clone 是一个系统调用,用于创建一个新的进程或线程。与 fork 系统调用不同的是,clone 允许创建的新进程或线程与父进程或线程共享某些资源,如内存空间、文件描述符等,从而实现更灵活的进程/线程管理。

clone 的原型如下:

int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...);

其中参数含义如下:

* fn:指向新进程/线程执行的函数指针

* child_stack:指向新进程/线程栈的指针

* flags:用于指定创建新进程/线程的标志

* arg:传递给新进程/线程执行函数的参数

clone 的常用标志包括:

* CLONE_VM:共享内存空间

* CLONE_FS:共享文件系统信息

* CLONE_FILES:共享文件描述符

* CLONE_SIGHAND:共享信号处理器

线程库不仅要管理每个线程tcb,还要提供一些方法(pthread_create/pthread_join,pthread_cancel/pthread_self)

线程的局部存储

在 C/C++ 中,__thread 是一种线程局部存储(Thread-Local Storage,TLS)的实现方式,用于声明线程私有变量。在使用 __thread 关键字声明的变量中,每个线程都会有自己独立的变量副本,不同线程之间互不影响。

__thread int g_val=100;//线程的局部存储

g_val 被声明为一个 __thread 变量,其初始值为 100。这意味着每个线程都会有一个名为 g_val 的变量,且其初始值为 100。不同线程中对 g_val 的操作都是互相独立的,一个线程修改 g_val 的值不会影响到其他线程中 g_val 的值。

线程可以进行fork?线程可以进行exec*程序替换吗?

可以fork,就是整个进程创建了一个子进程

程序替换之后,整个进程会被替换,所以建议,线程直接程序替换

  🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸   

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/629919.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

rocketmq的存储和检索

messageId是rocketmq自动生成的。

JSP+SQL学生成绩管理系统

Java版本&#xff1a;1.8 数据库&#xff1a;MySQL 框架&#xff1a;Spring Spring MVC MyBatis 服务器&#xff1a;Tomcat 前端解析框架&#xff1a;Thymeleaf 开发工具&#xff1a;Idea 2017 版本管理工具&#xff1a;Maven 版本控制工具&#xff1a;GitHub 经过对系统的需…

国际化日期(inti)

我们可以使用国际化API自动的格式化数字或者日期&#xff0c;并且格式化日期或数字的时候是按照各个国家的习惯来进行格式化的&#xff0c;非常的简单&#xff1b; const now new Date(); labelDate.textContent new Intl.DateTimeFormat(zh-CN).format(now);比如说这是按照…

link.click()时浏览器报错The file at ‘data:image/png;base64,iVBORw

代码如下&#xff1a; const dataURL canvas.toDataURL({format: "png",width: 400,height: 400, });const link document.createElement("a"); link.download new Date().getTime();link.href dataURL; document.body.appendChild(link); link.click…

【考研数学】准备开强化,更「张宇」还是「武忠祥」?

数一125学长前来回答&#xff0c;选择哪位老师的课程&#xff0c;这通常取决于你的个人偏好和学习风格&#xff01; 张宇老师和武忠祥老师都是非常有经验的数学老师&#xff0c;他们的教学方法各有特点。 张宇老师的教学风格通常被认为是通俗易懂&#xff0c;善于将复杂的概念…

x264 帧类型代价计算原理:slicetype_mb_cost 函数分析

slicetype_mb_cost 函数 函数功能 计算每个宏块 MB 的代价 cost。函数参数分析 x264_t *h:全局编码结构体x264_mb_analysis_t *a:宏块分析结构体x264_frame_t **frames:系列帧数据结构体int p0:帧序号之一,一般指向靠前帧int p1:帧序号之一,一般指向靠后帧int b:帧标志…

《系统架构设计师教程(第2版)》第4章-信息安全技术基础知识-02-信息加密技术

文章目录 1. 信息加密技术1.1 数据加密1.2 对称密钥加密算法1&#xff09;数据加密标准&#xff08;DES)2&#xff09;三重DES&#xff08;Triple-DES&#xff09;3&#xff09;国际数据加密算法&#xff08;IDEA&#xff09;4&#xff09;高级加密标准&#xff08;AES&#xf…

【C -> Cpp】由C迈向Cpp (6):静态、友元和内部类

标题&#xff1a;【C -&#xff1e; Cpp】由C迈向Cpp &#xff08;6&#xff09;&#xff1a;静态、友元和内部类 水墨不写bug &#xff08;图片来源于网络&#xff09; 目录 &#xff08;一&#xff09;静态成员 &#xff08;二&#xff09;友元 &#xff08;三&#xff09…

Zynq UltraScale+ RFSoC 配置存储器器件

Zynq UltraScale RFSoC 配置存储器器件 下表所示闪存器件支持通过 Vivado 软件对 Zynq UltraScale RFSoC 器件执行擦除、空白检查、编程和验证等配置操 作。 本附录中的表格所列赛灵思系列非易失性存储器将不断保持更新 &#xff0c; 并支持通过 Vivado 软件对其中所列…

扭亏为盈的赛力斯,真正进入稳态了吗?

“72小时内大定破1万台”。5月15日&#xff0c;问界新M5开启全国大规模交付&#xff0c;从当前取得的成绩来看&#xff0c;赛力斯的“富贵”似乎还将延续。 其实&#xff0c;此前基于问界新M7等车型的爆火&#xff0c;赛力斯已经找到了创收轨道。财报显示&#xff0c;2024年一…

无代码无国界:我们正在走向软件安全的狂野西部吗?

我们使用的几乎所有东西都是基于代码构建的&#xff0c;从汽车到智能冰箱再到门铃。在企业中&#xff0c;无数的应用程序保持设备、工作流程和操作的运行。因此&#xff0c;当早期的无代码开发平台于 2010 年推出时&#xff0c;承诺为公民开发人员提供更易于访问的应用程序开发…

用友GRP-U8 bx_dj_check.jsp SQL注入漏洞复现(XVE-2024-10537)

0x01 免责声明 请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;作者不为此承担任何责任。工具来自网络&#xff0c;安全性自测&#xff0c;如有侵权请联系删…

【2024华为HCIP831 | 高级网络工程师之路】刷题日记(18)

个人名片&#xff1a;&#x1faaa; &#x1f43c;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢AI编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&a…

动态手势识别(VGG11)

学校的大作业要做一个视频图像处理相关的&#xff0c;就做了动态手势识别 VGG代码 import torch import torch.nn as nnclass VGG_11_3D(nn.Module):def __init__(self, num_classes, pretrainedFalse):super(VGG_11_3D, self).__init__()self.conv1 nn.Conv3d(3, 64, kernel…

labelimg删除用不到的标签(yolo格式)以及 下载使用

问题&#xff1a;当我们标注完成新的类别后后直接删除classes.txt中不需要的类别之后再次打开labelimg会闪退&#xff0c;如何删除不需要的标签并且能够正确运行呢&#xff1f;&#xff08;yolo格式&#xff09; 原因&#xff1a;当我们打开labelimg进行标注的时候&#xff0c…

JumpServer堡垒机简单式部署与管理(v3.10.8) 上

目录 一. 环境准备 1.1 关闭防火墙 1.2 永久关闭SEliunx 1.3 重启虚拟机让seliunx文件生效 1.4 配置阿里源镜像 二. 安装部署 2.1 上传压缩包到虚拟机&#xff08;v3.10.8&#xff09; 2.2 解压 2.3 一键安装部署 2.4 安装完成界面 2.5 启动 2.6 浏览器访问IP 2.7 使…

“图生视频”技术创新:剪贴画秒变动画生成的实验验证与分析

在最近的研究进展中&#xff0c;AniClipart系统的问世标志着文本到视频生成技术的一个重要里程碑。这一系统由香港城市大学和莫纳什大学的研究者们共同开发&#xff0c;旨在解决将静态剪贴画图像根据文本提示自动转换成动画序列的挑战。传统的动画制作流程繁琐且耗时&#xff0…

基于物联网的教室人数检测系统-设计说明书

设计摘要&#xff1a; 本设计基于物联网技术&#xff0c;实现了一个教室人数检测系统。系统利用STM32单片机作为中控&#xff0c;通过红外对管检测人员进出教室&#xff0c;并实时统计应到人数和实到人数&#xff0c;同时使用OLED显示屏显示相关信息。系统还通过温湿度传感器检…

掌握Linux常用命令,扫平面试需求障碍

cd 切换目录。 > cd ../ #切换到父级目录 > cd /tmp # 切换到/tmp目录 > cd ~ # 切换到当前用户的家目录 ls命令 查看文件与目录的命令&#xff0c;list 的缩写。 > ls -l #列出长数据串&#xff0c;包含文件的属性与权限数据等 > ls -a #列出隐藏…

script标签以及defer和async属性

1. <script>标签 将JavaScript代码嵌入到HTML中主要方式是使用<script>元素。 使用<script>的方式有两种&#xff1a; &#xff08;1&#xff09;直接在网页中嵌入JavaScript代码&#xff1a; <script>function sayHi() {console.log("Hi"…