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,就是整个进程创建了一个子进程

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大模型学习笔记九:模型微调

文章目录 一、什么时候需要Fine-Tuning二、用Hugging Face根据电影评论输出来对电影进行情感分类1)安装依赖2)操作流程3)名字解释4)代码导入库和加载模型、加载数据库、加载tokenlizer5)其他相关公共变量赋值(随机种子、标签集评价、标签转token_Id)6)处理数据集:转成…

Altium Designer封装库和元器件符号库下载与导入教程(SnapEDA 、Ultra Librarian、Alldatasheetcn)

1.AD封装库和元器件符号库下载网址 以下是一些全球热门的Altium Designer封装库和元器件符号库下载网址推荐&#xff1a; Altium Content Vault (现称为Altium Manufacturer Part Search)&#xff1a;这是Altium官方提供的元器件库&#xff0c;可以直接在Altium Designer中使用…

免费体验GPT-4o这5大功能,非常好用!

这几天&#xff0c;OpenAI发布了新的GPT版本&#xff0c;GPT-4o&#xff0c;比GPT4更加智能也更快。 据说&#xff0c;GPT-4o在文本、推理和编码智能方面实现了GPT-4 Turbo级别的性能&#xff0c;在多语言、文本、音频和视觉功能方面甚至超过了市面上所有同类产品。 有几个亮点…

数据结构复习指导之图的存储及基本操作

文章目录 图的存储及基本操作 考纲内容 复习提示 1.邻接矩阵法 2.邻接表法 3.十字链表 4.邻接多重表 5.图的基本操作 图的存储及基本操作 图的存储必须要完整、准确地反映顶点集和边集的信息。根据不同图的结构和算法&#xff0c;采用不同的存储方式将对程序的效率产生…

Python进度条工具——tqdm

原文链接&#xff1a;http://www.juzicode.com/python-note-tqdm 在安装Python库文件的时候我们经常可以看到这种进度条&#xff1a; 其实Python库中就自带了现成的工具库——tqdm。 tqdm读起来比较拗口&#xff0c;它是从“进程”的阿拉伯语taqaddum简化而来。 安装tqdm 使用…

C++二叉搜索树搜索二叉树二叉排序树

C二叉搜索树 1. 二叉搜索树的概念 二叉搜索树&#xff08;BST,Binary Search Tree)&#xff0c;也称为二叉排序树或二叉查找树。它与一般二叉树的区别在于&#xff1a;每个结点必须满足“左孩子大于自己&#xff0c;右孩子小于自己”的规则。在这种规则的约束下&#xff0c;二…

ADS Momentum 仿真设置

1、选择Momenttum Microwave。 2、Layout不需要操作。 3、Partitioning 不需要操作。 4、没有叠层的话需要新建叠层&#xff0c;过孔可以在叠层中右键添加。 5、注意确认端口的Gnd Layer。 6、设置仿真频率。 7、Output Plan。 8、Option。 最后运行仿真&#xff0c;等待结果即…

算法学习(7)-树

目录 开启“树”之旅 二叉树 堆--优先队列 并查集 开启“树”之旅 是不是很像一棵倒挂的树&#xff1f;也就是说它是根朝上&#xff0c; 而叶子朝下的。不像&#xff1f;哈哈&#xff0c;来看看下面的图你就会觉得像啦。 你可能会间&#xff1a; 树和图有什么区别&#xff…

代码生成工具1 ——项目简介和基础开发

1 项目简介 需要提前在数据库建好表&#xff0c;然后执行代码生成工具&#xff0c;会生成简单的Java文件&#xff0c;避免重复编写增删改查代码。类似的工具网上有很多&#xff0c;本人开发这个工具属于自娱自乐。这个专栏会记录开发的过程。 2 项目搭建 数据库使用MySQL &…

APP没有上架就开通了APP支付,微信商户的这个操作绝了

在当今的移动支付时代&#xff0c;APP支付已成为商家与消费者之间的重要桥梁。然而&#xff0c;对于一些尚未上架的应用来说&#xff0c;如何快速开通APP支付功能一直是个难题。最近&#xff0c;微信商户平台的一项新操作&#xff0c;为这类商家带来了福音---APP没有上架&#…

财富增长新途径:副业赚钱方法全攻略

探寻财富之路&#xff1a;多元化赚钱途径解析 在追求财富的道路上&#xff0c;每个人都在以自己的方式前行。然而&#xff0c;正如古人所云&#xff1a;“君子爱财&#xff0c;取之有道。”今天&#xff0c;我将为您揭示一些新颖且实用的赚钱途径&#xff0c;希望能为您的财富…

Blender雕刻建模_衰减

衰减 从中心点向外的强度衰减。 其中 中心点&#xff1a;即笔刷选中的顶点 半径&#xff1a;即笔刷的半径 衰减范围 从中心点向外的一个球形空间&#xff08;不仅是看见的2D球&#xff0c;而是一个3D球形的空间&#xff09; 为了避免误操作有如下几种方法&#xff1a; -Al…

Unity射击游戏开发教程:(13)如何在Unity中播放音效

在本文中,我将向大家展示一些为游戏添加声音的不同方法。 我们为游戏添加声音的第一种方法是播放背景音乐。在此,我们将创建游戏对象(“音频管理器”)并创建一个子游戏对象(“背景音乐”)。该子游戏对象将是播放音乐的对象,因此需要向其添加音频源组件。如果没有音频源组…

【LInux】<基础IO> 文件操作 | 文件描述符 | 重定向

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在学习c和算法 ✈️专栏&#xff1a;Linux &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指点一二 如果文章对…

springboot004网页时装购物系统

springboot004网页时装购物系统 亲测完美运行带论文&#xff1a;获取源码&#xff0c;私信评论或者v:niliuapp 运行视频 包含的文件列表&#xff08;含论文&#xff09; 数据库脚本&#xff1a;db.sql其他文件&#xff1a;ppt.pptx论文/文档&#xff1a;开题报告.docx论文&…

独立服务器和云服务器哪个好?

在当今数字时代&#xff0c;网站托管是任何在线业务成功的关键要素之一。但是&#xff0c;当谈到选择正确的托管解决方案时&#xff0c;很容易陷入独立服务器与云服务器之间的抉择。两者都有各自的优势和限制&#xff0c;因此在决定哪种类型的托管适合您的业务之前&#xff0c;…

【线性系统理论】笔记二

状态转移矩阵-性质 特殊的矩阵指数函数 A求矩阵指数函数计算 方法1&#xff1a;特征值互异 方法2&#xff1a;特征值重根 方法3&#xff1a;反拉氏变换 方法4&#xff1a; 凯莱-哈密顿求e 特征值互异&#xff1a; 特征值相同 状态转移矩阵e求A 零输入响应 零状态响应 状态…

第189题|幂级数的展开的常规方法(二)|武忠祥老师每日一题

解题思路&#xff1a;将函数展开成幂级数有两种方法&#xff1a;一种是直接法&#xff08;这种一般比较麻烦&#xff09;&#xff0c;一种是拆解成现有展开式展开&#xff08;这种的特征一般是能因式分解&#xff09;。 第一步&#xff1a; 这里看到 ln(1-x-2x^2) 将里面的式…

AI大模型日报#0515:Google I/O大会、 Ilya官宣离职、腾讯混元文生图大模型开源

导读&#xff1a;欢迎阅读《AI大模型日报》&#xff0c;内容基于Python爬虫和LLM自动生成。目前采用“文心一言”&#xff08;ERNIE 4.0&#xff09;、“零一万物”&#xff08;Yi-34B&#xff09;生成了今日要点以及每条资讯的摘要。 《AI大模型日报》今日要点&#xff1a;谷歌…

高考志愿系统-模拟填报模块分析

1.获取所有志愿列表 接口: http://localhost:81/dev-api/college_entrance/aspiration/list 默认传参pageNum1&pageSize10&#xff0c; 请求方法: GET 接口内方法同样首先设置分页信息&#xff0c;然后修改查询出的所有志愿信息列表中的学生id属性 2.详细志愿查看 接口…