当前位置: 首页 > news >正文

LINUX 入门 4

LINUX 入门 4

day6 7 20240429 20240504 耗时:240min

课程链接地址

第4章 LINUX环境编程——实现线程池

C基础

  1. 第3节

    1. #define里面的行不能乱空行,要换行就打\

    2. typedef 是 C 和 C++ 中的一个关键字,用于为已有的数据类型定义一个新的名字。通过 typedef 可以为数据类型起一个更直观或者更易于理解的名字,也可以用来简化复杂的数据类型声明。例如:

      unsigned long long int ULLONG; // 为 unsigned long long int 定义了一个新名字 ULLONG
      
    3. static void *nThreadPoolCallback(void *arg){ }

      nThreadPoolCallback 函数声明为 static 可能是为了将其作用域限制在当前文件内部,避免其它文件中的函数同名冲突,而不是全局作用域的函数。这样做有助于提高代码的可维护性和可读性,因为这个函数只能在当前文件内部被访问和调用,不会被其它文件意外地使用或修改。

  2. 第5节

     struct nWorker *worker = (struct nWorker*) arg;
    

    这行代码创建了一个指向 struct nWorker 结构的指针 worker,并将其初始化为 (struct nWorker*) arg。通常这样的语句在多线程编程中会被用到,其中 arg 是传递给线程的参数,这里将其转换为 struct nWorker* 类型的指针以便在线程中使用。

  3. 第6节

    pthread_cond_signalpthread_cond_broadcast 是 POSIX 线程库中用于线程同步的函数,通常与条件变量(condition variable)一起使用。

    1. pthread_cond_signal 函数用于唤醒一个正在等待条件变量的线程。如果有多个线程正在等待条件变量,那么只会唤醒其中的一个。通常情况下,这是因为某个线程执行了某些操作,使得条件变量的条件满足,因此需要通知等待该条件变量的线程继续执行。
    2. pthread_cond_broadcast 函数用于唤醒所有正在等待条件变量的线程。这个函数会同时唤醒所有等待该条件变量的线程,而不是像 pthread_cond_signal 那样只唤醒其中的一个。通常情况下,这是在某个线程执行了某些操作,使得多个线程都能继续执行时使用。

    这两个函数通常与互斥锁(mutex)一起使用,以实现线程之间的同步。当某个线程需要等待某个条件满足时,它会先释放互斥锁并等待条件变量,而其他线程则可能在条件不满足时进入等待状态。当条件满足时,某个线程会调用 pthread_cond_signalpthread_cond_broadcast 来唤醒等待的线程,让它们继续执行。

1 线程池的使用场景与原理分析

  1. 使用场景:

    1. 百万级的client,server多线程 开线程来同时处理不同client发来的message

      在这里插入图片描述

      but开不了那么多thread,linux下一个posix线程占8M

      1G=1024M开128个最多

      16G内存最多开128*16=2048个thread

    2. 日志文件

      1. disk磁盘操作比memory操作慢不是一个数量级,日志存储到磁盘的文件里,刷新到disk

        处理IO读写,准备好写log里的文字是memory操作,

        log存到文件是disk操作,会引起thread挂起,等IO就绪。 写log任务放到线程池里

  2. 线程池好处

    1. 避免线程太多,内存memory耗尽

    2. 避免反复重复创建和销毁thread, 创建完就放池子,用完还回去

    3. 任务与执行分离(日志写和存储,写内容生成和存到文件)

      例子:银行营业厅,办业务的是任务, 柜员是执行

      在这里插入图片描述

  3. def:

    线程池=

    1. 任务队列
    2. 执行队列
    3. 管理组件 mutex或spinlock加锁 调节任务和执行

2 线程池的结构体定义 threadpool

线程池sdk组件封装software Development Kit

  1. 任务队列:

    任务组成,先定义任务task struct

    再任务队列:链表串起tasks 双向链表

    //1.定义task
    struct nTask{void(*task_func)(struct nTask *task);//一个函数指针,指向一个接受 struct nTask* 参数并且没有返回值的函数。这个指针用于表示任务的执行函数。void *user data;//一个指向 void 类型的指针,用于存储任务函数可能需要的额外数据或参数。struct nTask *prev;struct nTask *next;
    }; // 双向链表
    

3 线程池的架构分析与实现

1 最底层:系统层,支持层——实现数据结构+宏定义的基本操作

任务队列,执行队列,管理组件

链表(struct)操作:直接用通讯录那一张的宏定义

#define LIST_INSERT(item, list)do{\item->prev = NULL;\item->next = list;\if((list)!= NULL) (list)->prev = item;\(list) = item;    \
} while(0)
//二级指针,list要括号(*ppeople)#define LIST_REMOVE(item, list) do {	\if (item->prev != NULL) item->prev->next = item->next; \if (item->next != NULL) item->next->prev = item->prev; \if (list == item) list = item->next;                    \item->prev = item->next = NULL;                         \
} while(0)//1.定义task
struct nTask{void(*task_func)(struct nTask *task);void *user data;struct nTask *prev;struct nTask *next;
};//2.执行
struct nWorker{pthread_t threadid;struct nWorker *prev;struct nWorker *next;
};//3管理组件 连接worker和task
struct nManager{struct nTask *tasks;  //任务队列struct nWorker *workers; //执行队列pthread_mutex_t mutex; //加互斥锁pthread_cond_t cond; //加条件变量,等待满足条件不锁了
};

2 接口层 ,在支持层上包一层

这里管理组件nManager就是threadpool,这里对类型起别名用typedef

4个:创建、销毁、加任务、线程涉及的回调函数

typedef struct nManager{struct nTask *tasks;  //任务队列struct nWorker *workers; //执行队列pthread_mutex_t mutex; //加互斥锁pthread_cond_t cond; //加条件变量,等待满足条件不锁了
}ThreadPool;static void *nThreadPoolCallback(void *arg){}int nThreadPoolCreate(ThreadPool*pool, int nworker){}int nThreadPoolDestroy(ThreadPool*pool, int nworker){}int nThreadPoolPushTask(ThreadPool*pool, struct nTask *task){}

4 线程池初始化实现

多用才能对接口熟悉

函数—— 参数,函数体,返回值

  1. 最终function做成sdk,所以做成API接口给其他人调就行
  2. 初始化struct内四个,除了task
  3. 堆上malloc出来的动态数据,要memset置零,防止内容不确定野指针了
  4. 业务功能(callback)一样,但是实际task任务不同,相当于task是callback的具体实现
// API
int nThreadPoolCreate(ThreadPool*pool, int numWorker){if(pool == NULL) return -1;if(numWorker < 1) numWorker = 1; //运行线程没有,那就默认1个// 2 对struct里4个初始化,task外界扔进来不用pthread_cond_t blank_cond = PHTREAD_COND_INITIALIZER; //定义空白锁的条件变量memcpy(&pool->cond, &blank_cond,sizeof(pthread_cond_t));//blank_cond 中的 pthread_cond_t 结构体的内容复制到 pool->cond 中。pthread_mutex_init(&pool->mutex,NULL);int i = 0;for(int i =0; i < numWorker; i++){struct nWorker *worker = malloc(sizeof(struct nWorker));//创建失败if(worker ==NULL){perror("malloc");return -2;}memset(worker, 0,sizeof(struct worker));worker->manager = pool;//创建线程int ret = pthread_create(worker->threadid, NULL, nThreadPoolCallback, worker); //创建成功返回0,失败1if(ret){perror("pthread_create");free(worker);return -3;}LIST_INSERT(worker, pool->worker);}return 0; //创建成功, callback是业务功能,一样,但是不等同于task任务,但是执行的任务不同}

5 线程池的线程回调函数实现

核心:三件事

判任务队列里有任务

没就等

有就拿出执行,取用户数据

// API
// callback!=task
static void *nThreadPoolCallback(void *arg){struct nWorker *worker = (struct nWorker*) arg;while(1){pthread_mutex_lock(worker->manager->mutex); //对任务加一把锁while(worker->manager->tasks == NULL){//判有任务,没就等,有就拿出执行,取用户数据pthread_cond_wait(&worker->manager->cond, &worker->manager->mutex);}struct nTask *task = worker->manager->tasks;LIST_REMOVE(task, worker->manager->tasks); //把任务队列tasks的首节点task执行完了,移出来pthread_mutex_unlock(worker->manager->mutex);task->task_func(task->user_data);}free(worker);// but没有退出的break的地方,struct nWorker里引入终止标识    
}

问题:but没有退出的break的地方,struct nWorker里引入终止标识

//2.执行
struct nWorker{pthread_t threadid;int terminate;struct nManager *manager; //worker需要有manager联系方式struct nWorker *prev;struct nWorker *next;
};

同时

static void *nThreadPoolCallback(void *arg){struct nWorker *worker = (struct nWorker*) arg;while(1){pthread_mutex_lock(worker->manager->mutex); //对任务加一把锁while(worker->manager->tasks == NULL){//判有任务,没就等,有就拿出执行,取用户数据if(worker->terminate) break; //是1就是终止pthread_cond_wait(&worker->manager->cond, &worker->manager->mutex);}if(worker->terminate){// 退出最外层while,先解锁,不然可能死锁了pthread_mutex_unlock(worker->manager->mutex); break; }struct nTask *task = worker->manager->tasks;LIST_REMOVE(task, worker->manager->tasks); //把任务队列tasks的首节点task执行完了,移出来pthread_mutex_unlock(worker->manager->mutex);task->task_func(task->user_data);}free(worker);// but没有退出的break的地方,struct nWorker里引入终止标识    
}

6 线程池的任务添加与线程池销毁

terminate置1就退出来了

int nThreadPoolDestroy(ThreadPool*pool, int nworker){struct nWorker *worker = NULL;for(worker = pool->workers; worker != NULL; worker = worker->next){worker->terminate;//都置1}//信号什么时候往下走,广播使所有条件满足让信号往下走pthread_mutex_lock(&pool->mutex);pthread_cond_broadcast(&pool->cond);// 唤醒所有广播和等待用的同一把锁,不会有死锁,什么东西没听懂pthread_mutex_unlock(&pool->mutex);pool->workers= NULL;pool->tasks = NULL;return 0;
}

任务添加

int nThreadPoolPushTask(ThreadPool*pool, struct nTask *task){//通知thread有task来了pthread_mutex_lock(&pool->mutex);LIST_INSERT(task, pool->tasks);//通知条件变量可满足,唤醒一个threadpthread_cond_signal(&pool->cond);pthread_mutex_unlock(&pool->mutex);}

7 线程池代码gdb调试与bug修改

gcc -o threadpool threadpool.c -lpthread

一堆错 有问题, 视频里面没有写main后面的函数!! 根本看不懂了,这里后面没法调

//
// sdk --> debug thread pool#if 1#define THREADPOOL_INIT_COUNT	20
#define TASK_INIT_SIZE			1000void task_entry(struct nTask *task) { //type //struct nTask *task = (struct nTask*)task;int idx = *(int *)task->user_data;printf("idx: %d\n", idx);free(task->user_data);free(task);
}int main(void) {ThreadPool pool = {0};nThreadPoolCreate(&pool, THREADPOOL_INIT_COUNT);// pool --> memset();int i = 0;for (i = 0;i < TASK_INIT_SIZE;i ++) {struct nTask *task = (struct nTask *)malloc(sizeof(struct nTask));if (task == NULL) {perror("malloc");exit(1);}memset(task, 0, sizeof(struct nTask));task->task_func = task_entry;task->user_data = malloc(sizeof(int));*(int*)task->user_data  = i;nThreadPoolPushTask(&pool, task);}getchar();}#endif

gdb调试,适合小工程

gcc -o threadpool threadpool.c -lpthread -g
gdb ./threadpool

打断点:

  1. 在判断的地方加breakpoint,比如while if

    有可能出现空指针

    b 行数
    b 64 (while判断)
    b 76 (list remove)
    b 115 (list insert)
    r(就是run)
    c(continue) 没有出现视频里的问题
    

    nThreadPoolCreate里少 memset(pool, 0, sizeof(ThreadPool));

     b 80 (task->task_func)b 201(pushtask)rcc
    

    报错了 并没有解决了,还是segmentation fault

    Thread 3 "threadpool" received signal SIGSEGV, Segmentation fault.
    [Switching to Thread 0x7ffff6fee700 (LWP 12096)]
    0x0000000000400f08 in task_entry (task=0x604a80) at threadpool.c:170
    170		int idx = *(int *)task->user_data;
    

    太丑了,放弃了,sourceinsight长得太丑了,还卡的一批,用vscode连虚拟机ok了

    这节课基本没听懂!!!云里雾里乱起八糟的

    最后调出来了是这个问题

    nThreadPoolCallback(void *arg)里面的task->task_func(task->user_data);改成 task->task_func(task);

相关文章:

LINUX 入门 4

LINUX 入门 4 day6 7 20240429 20240504 耗时&#xff1a;240min 课程链接地址 第4章 LINUX环境编程——实现线程池 C基础 第3节 #define里面的行不能乱空行&#xff0c;要换行就打\ typedef 是 C 和 C 中的一个关键字&#xff0c;用于为已有的数据类型定义一个新的名字。…...

Imagine Flash、StyleMamba 、FlexControl、Multi-Scene T2V、TexControl

本文首发于公众号&#xff1a;机器感知 Imagine Flash、StyleMamba 、FlexControl、Multi-Scene T2V、TexControl You Only Cache Once: Decoder-Decoder Architectures for Language Models We introduce a decoder-decoder architecture, YOCO, for large language models, …...

Java Collections.emptyList() 方法详解

前言 在Java开发的日常中&#xff0c;我们常常需要处理集合数据结构&#xff0c;而这其中就免不了要面对“空集合”的场景。传统的做法可能是直接返回 null&#xff0c;但这往往会引入空指针异常的风险&#xff0c;降低了代码的健壮性。幸运的是&#xff0c;Java为我们提供了一…...

Vue前端环境准备

vue-cli Vue-cli是Vue官方提供的脚手架&#xff0c;用于快速生成一个Vue项目模板 提供功能&#xff1a; 统一的目录结构 本地调试 热部署 单元测试 集成打包上线 依赖环境&#xff1a;NodeJs 安装NodeJs与Vue-Cli 1、安装nodejs&#xff08;已经安装就不用了&#xff09; node-…...

代码随想录算法训练营第四十二天| 01背包问题(二维、一维)、416.分割等和子集

系列文章目录 目录 系列文章目录动态规划&#xff1a;01背包理论基础①二维数组②一维数组&#xff08;滚动数组&#xff09; 416. 分割等和子集①回溯法&#xff08;超时&#xff09;②动态规划&#xff08;01背包&#xff09;未剪枝版剪枝版 动态规划&#xff1a;01背包理论基…...

故障——蓝桥杯十三届2022国赛大学B组真题

问题分析 这道题纯数学&#xff0c;考察贝叶斯公式 AC_Code #include <bits/stdc.h> using namespace std; typedef pair<int,double> PI; bool cmp(PI a,PI b){if(a.second!b.second)return a.second>b.second;return a.first<b.first; } int main() {i…...

SSD存储基本知识

存储技术随着时间的推移经历了显著变化&#xff0c;新兴的存储介质正逐步挑战已经成为行业标准的硬盘驱动器&#xff08;HDD&#xff09;。在众多竞争者中&#xff0c;固态硬盘&#xff08;SSD&#xff09;是最广泛采用且最有潜力占据主导地位的——它们速度快、运行安静&#…...

buuctf-misc题目练习二

ningen 打开题目后是一张图片&#xff0c;放进winhex里面 发现PK&#xff0c;PK是压缩包ZIP 文件的文件头&#xff0c;下一步是想办法进行分离 Foremost可以依据文件内的文件头和文件尾对一个文件进行分离&#xff0c;或者识别当前的文件是什么文件。比如拓展名被删除、被附加…...

Nginx rewrite项目练习

Nginx rewrite练习 1、访问ip/xcz&#xff0c;返回400状态码&#xff0c;要求用rewrite匹配/xcz a、访问/xcz返回400 b、访问/hello时正常访问xcz.html页面server {listen 192.168.99.137:80;server_name 192.168.99.137;charset utf-8;root /var/www/html;location / {root …...

2024,AI手机“元年”? | 最新快讯

文 | 伯虎财经&#xff0c;作者 | 铁观音 2024年&#xff0c;小米、荣耀、vivo、一加、努比亚等品牌的AI手机新品如雨后春笋般涌现。因此&#xff0c;这一年也被业界广泛视为AI手机的“元年” 试想&#xff0c;当你轻触屏幕&#xff0c;你的手机不仅响应你的指令&#xff0c;更…...

5月9(信息差)

&#x1f30d; 可再生能源发电量首次占全球电力供应的三成 &#x1f384;马斯克脑机接口公司 Neuralink 计划将 Link 功能扩展至现实世界&#xff0c;实现控制机械臂、轮椅等 马斯克脑机接口公司 Neuralink 计划将 Link 功能扩展至现实世界&#xff0c;实现控制机械臂、轮椅等…...

leetcode203-Remove Linked List Elements

题目 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1a;[1,2,3,4,5] 示例 2&#xff1a; 输入&…...

2024付费进群系统,源码及搭建变现视频课程(教程+源码)

自从我做资源站项目盈利稳定后&#xff0c;我越来越对网站类项目感兴趣了&#xff0c;毕竟很多网站类项目还是需要一定技术门槛的&#xff0c;可以过滤掉一些人&#xff0c;很多新人做项目就只盯着短视频&#xff0c;所以网站类项目也就没那么的卷。 这个付费进群系统&#xf…...

深入理解Django:中间件与信号处理的艺术

title: 深入理解Django&#xff1a;中间件与信号处理的艺术 date: 2024/5/9 18:41:21 updated: 2024/5/9 18:41:21 categories: 后端开发 tags: Django中间件信号异步性能缓存多语言 引言 在当今的Web开发领域&#xff0c;Django以其强大的功能、简洁的代码结构和高度的可扩…...

rk3588局域网推流

最近无意间看见在网上有使用MediaMtx插件配合ffmpeg在Windows来进行推流&#xff0c;然后在使用其他软件进行拉流显示数据图像的&#xff0c;既然windows都可以使用 &#xff0c;我想linux应该也可以&#xff0c;正好手上也有一块RK3588的开发板&#xff0c;就测试了一下&#…...

Android虚拟机机制

目录 一、Android 虚拟机 dalvik/art&#xff08;6版本后&#xff09;二、Android dex、odex、oat、vdex、art区别 一、Android 虚拟机 dalvik/art&#xff08;6版本后&#xff09; 每个应用都在其自己的进程中运行&#xff0c;都有自己的虚拟机实例。ART通过执行DEX文件可在设…...

【触摸案例-手势解锁案例-按钮高亮 Objective-C语言】

一、我们来说这个self.btns,这个问题啊,为什么不用_btns, 1.我们说,在懒加载里边儿,经常是写下划线啊,_btns,为什么不写,首先啊,这个layoutSubviews:我们第一次,肯定会去执行这个layoutSubviews: 然后呢,去懒加载这个数组, 然后呢,接下来啊,走这一句话, 第一次…...

ChatPPT开启高效办公新时代,AI赋能PPT创作

目录 一、前言二、ChatPPT的几种用法1、通过在线生成2、通过插件生成演讲者模式最终成品遇到问题改进建议 三、ChatPPT其他功能 一、前言 想想以前啊&#xff0c;为了做个PPT&#xff0c;我得去网上找各种模板&#xff0c;有时候还得在某宝上花钱买。结果一做PPT&#xff0c;经…...

【C语言项目】贪吃蛇(上)

个人主页 ~ gitee仓库~ 欢迎大家来到C语言系列的最后一个篇章–贪吃蛇游戏的实现&#xff0c;当我们实现了贪吃蛇之后&#xff0c;我们的C语言就算是登堂入室了&#xff0c;基本会使用了&#xff0c;当然&#xff0c;想要更加熟练地使用还需要多多练习 贪吃蛇 一、目标二、需要…...

LeNet-5上手敲代码

LeNet-5 LeNet-5由Yann LeCun在1998年提出&#xff0c;旨在解决手写数字识别问题&#xff0c;被认为是卷积神经网络的开创性工作之一。该网络是第一个被广泛应用于数字图像识别的神经网络之一&#xff0c;也是深度学习领域的里程碑之一。 LeNet-5的整体架构&#xff1a; 总体…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

系统设计 --- MongoDB亿级数据查询优化策略

系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log&#xff0c;共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题&#xff0c;不能使用ELK只能使用…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...

HBuilderX安装(uni-app和小程序开发)

下载HBuilderX 访问官方网站&#xff1a;https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本&#xff1a; Windows版&#xff08;推荐下载标准版&#xff09; Windows系统安装步骤 运行安装程序&#xff1a; 双击下载的.exe安装文件 如果出现安全提示&…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

Java 二维码

Java 二维码 **技术&#xff1a;**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...