笔记汇总2(中断、GDB、编程实例)

news2024/11/26 12:18:10

前言

  本文主要是一些学习笔记的汇总,主要参考公众号:嵌入式与Linux那些事,GDB多线程调试,自实现unique_ptr,share_ptr,宏,线程池仅供自己学习使用。

中断与异常有何区别?
中断是指外部硬件产生的一个电信号从CPU的中断引脚进入,打断CPU的运行;
异常是指软件运行过程中发生了一些必须作出处理的事件,CPU自动产生一个陷入来打断CPU的运行.异常在处理的时候必须考虑与处理器的时钟同步,实际上异常也称为同步中断,在处理器执行到因编译错误而导致的错误指令时,或者在执行期间出现特殊错误,必须靠内核处理的时候,处理器就会产生-个异常。
中断与DMA
DMA: 是一种无须CPU的参与,就可以让外设与系统内存之间进行双向数据传输的硬件机制,使用DMA可以使系统CPU从实际的I/O数据传输过程中摆脱出来,从而大大提高系统的吞吐率。
中断:是指CPU在执行程序的过程中,出现了某些突发事件时,CPU必须暂停执行当前的程序,转去处理突发事件,处理完毕后CPU又返回源程序被中断的位置并继续执行。

中断的响应执行流程是什么?
中断的响应流程: cpu接受中断->保存中断上下文跳转到中断处理历程->执行中断上半部->执行中断下半部->恢复中断上下文。

SPI的应用
SPI(Serial PeripheralInterface)协议即串行外围设备接口,是一种高速全双工的通信总线。SPl总线系统是一种同步串行外设接口,它可以使MCU与各种外围设备以串行方式进行通信以交换信息。SPI总线可直接与各人厂家生产的多种标准外围器件相连,包括ELASHRAM、网络控制器、LCD显示驱动器、A/D转换器和MCU等。

IIC协议
IC协议是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据,是一个多主机的半双工通信方式每个挂接在总线上的器件都有个唯一的地址。位速在标准模式下可达 100kbit/s,在快速模式下可达400kbit/s,在高速模式下可待3.4Mbit/s。

GDB调试

多线程调试命令
在这里插入图片描述
进入主线程后可以使用bt查看主线程堆栈,或者使用pstack/gstack直接打印堆栈信息。

多线程/单例/智能指针/构造函数/宏,实例

单例模式

class Singleton
{
public:
	static Singleton* GetInstance() {
	// 注意这里一定要使用Double-Check的方式加锁,才能保证效率和线程安全
		if (nullptr == m_Instance) {
			m_mtx.lock();
			if (nullptr == m_Instance) {
				static single m_pInstance;
			}
			m_mtx.unlock();
		}
		return m_Instance;
	}// 实现一个内嵌垃圾回收类
	class CGarbo {
	public:
		~CGarbo(){
			if (Singleton::m_Instance)
				delete Singleton::m_Instance;
		}
	};// 定义一个静态成员变量,程序结束时,系统会自动调用它的析构函数从而释放单例对象
	static CGarbo Garbo;
private:
	// 构造函数私有
	Singleton(){};
	// 防拷贝
	Singleton(Singleton const&) = delete;
	Singleton& operator=(Singleton const&) = delete;
	static Singleton* m_Instance; // 单例对象指针
	static mutex m_mtx; //互斥锁
};
Singleton* Singleton::m_Instance = nullptr;
Singleton::CGarbo Garbo;

uniqur_ptr实现

namespace cpp_lib{
class Deletor{//先完成一个删除器
public:
    Deletor() = default;

    template <typename U>
    void operator()(U *p) noexcept{
        if(p){
            delete p;
        }
    }
};

template <typename T, typename U = Deletor>
class unique_ptr{
public:
    explicit unique_ptr():ptr(nullptr){}; //显示构造函数
    explicit unique_ptr(T* p):ptr(p){}; //显示构造函数
    explicit unique_ptr(unique_ptr&& p){ //移动构造函数
    	ptr = std::forward<T*>(p.ptr);
    	deletor = std::forward<U>(p.deletor);
    	p.ptr = nullptr;//结尾都要加上nullptr否则如果错误使用会导致程序崩溃
    }
    void operator=(unique_ptr&& p){ //移动赋值运算符
    	ptr = std::forward<T*>(p.ptr);
    	deletor = std::forward<U>(p.deletor);
    	p.ptr = nullptr;
    }
    ~unique_ptr(){//析构函数
		if(ptr)
			deletor(ptr);
		ptr = nullptr;
	}
    unique_ptr(const unique_ptr& p) = delete; //不支持复制构造函数
    unique_ptr operator=(const unique_ptr& p) = delete; //不支持复制运算符函数
    unique_ptr operator=(T* p) = delete; //不支持裸指针赋值
    T* release(){
    	T *p = ptr;
    	ptr = nullptr;
    	return p;
    }
    void reset(T* p = nullptr) noexcept{
		if(ptr)
			deletor(ptr);
		ptr = p;
	}
    void swap(unique_ptr& rhs) noexcept{
    	std::swap(ptr, rhs.ptr);
    	std::swap(deletor, rhs.deletot);)
    }
    T* get() noexcept{
		return ptr;
	}
    U& get_deletor() noexcept{
    	return deletor;
    }
    explicit operator bool() const noexcept{
    	if(ptr)
    		return true;
   		else return false;
    }
    T& operator*() const noexcept{
		return ptr;
	}
    T* operator->() const noexcept{
		return ptr;
	}

private:
    T *ptr; //值指针
    U deletor; //删除器
};
}//自定义命名空间为了防止和标准库里的unique_ptr冲突

share_ptr

template<typename T>
class smart
{
private:
	T* _ptr;
	int* _count; //reference couting

public:
	//构造函数
	smart(T* ptr = nullptr) :_ptr(ptr)
	{
		if (_ptr){
		 _count = new int(1);
		}
		else{
			_count = new int(0);
		}
	}
	//拷贝构造
	smart(const smart& ptr)	{
		if (this != &ptr){
			this->_ptr = ptr._ptr;
			this->_count = ptr._count;
			(*this->_count)++;
		}
	}
	//重载operator=
	smart& operator=(const smart & ptr){
		if (this->_ptr == ptr._ptr)	{
			return *this;
		}
		if (this->_ptr){
			(*this->_count)--;
			if (*this->_count == 0)	{
				delete this->_ptr;
				delete this->_count;
			}
		}
		this->_ptr = ptr._ptr;
		this->_count = ptr._count;
		(*this->_count)++;
		return *this;
	}
	//operator*重载
	T& operator*(){
		if (this->_ptr)	{
			return *(this->_ptr);
		}
	}
	//operator->重载
	T* operator->()	{
		if (this->_ptr)	{
			return this->_ptr;
		}
	}
	//析构函数
	~smart(){
		(*this->_count)--;
		if (*this->_count == 0)	{
			delete this->_ptr;
			delete this->_count;
		}
	}
	//return reference couting
	int use_count()	{
		return *this->_count;
	}
};

拷贝构造函数-深拷贝(默认构造函数已经是浅拷贝了):

template<typename T>
class Rect
{
public:
  Rect()
  {
   p=new T(100);
  }
  
  Rect(const Rect& r)
  {
   width=r.width;
   height=r.height;
   p=new T(100);
   *p= *(r.p);
  }
   
  ~Rect()
  {
   assert(p!=NULL);
      delete p;
  }
private:
  T width;
  T height;
  T *p;
};

最大宏(需要考虑变量自增,运算符优先级,支持任意类型)

#define max(x, y) ({
    typeof(x) _max1 = (x);//typeof查看变量类型
    typeof(y) _max2 = (y);
    (void) (&_max1 == &_max2);//对于不同类型的比较编译器会报警,两个值比较但是结果没有用到也会报警使用void可以消除这个warning
    _max1 > _max2 ? _max1 : _max2;
    })

多线程编程

class ThreadPool{
private:
    struct NWORKER{//工作队列
        pthread_t threadid;			 //线程id
        bool terminate;				 //是否需要结束worker的标志
        int isWorking;				 //判断是否在工作
        ThreadPool *pool;			 //隶属于的线程池
    } *m_workers;

    struct NJOB{//任务队列
        void (*func)(void *arg);     //任务函数
        void *user_data;			 //函数参数
    };
public:
    //线程池初始化
    //numWorkers:线程数量
    ThreadPool(int numWorkers, int max_jobs);
    //销毁线程池
    ~ThreadPool();
    //面向用户的添加任务
    int pushJob(void (*func)(void *data), void *arg, int len);

private:
    //向线程池中添加任务
    bool _addJob(NJOB* job);
    //回调函数
    static void* _run(void *arg);
    void _threadLoop(void *arg);

private:
    std::list<NJOB*> m_jobs_list;
    int m_max_jobs;							//任务队列中的最大任务数
    int m_sum_thread;						//worker总数
    int m_free_thread;						//空闲worker数
    pthread_cond_t m_jobs_cond;           //线程条件等待
    pthread_mutex_t m_jobs_mutex;         //为任务加锁防止一个任务被两个线程执行等其他情况
};

//run为static函数,回调函数
void* ThreadPool::_run(void *arg) {
    NWORKER *worker = (NWORKER *)arg;
    worker->pool->_threadLoop(arg);
}

//线程池
void ThreadPool::_threadLoop(void *arg) {
    NWORKER *worker = (NWORKER*)arg;
    while (1){
        //线程只有两个状态:执行\等待
        //查看任务队列前先获取锁
        pthread_mutex_lock(&m_jobs_mutex);
        //当前没有任务
        while (m_jobs_list.size() == 0) {
        	//检查worker是否需要结束生命
            if (worker->terminate) break;
            //条件等待直到被唤醒
            pthread_cond_wait(&m_jobs_cond,&m_jobs_mutex);
        }
        //检查worker是否需要结束生命
        if (worker->terminate){
            pthread_mutex_unlock(&m_jobs_mutex);
            break;
        }
        //获取到job后将该job从任务队列移出,免得其他worker过来重复做这个任务
        struct NJOB *job = m_jobs_list.front();
        m_jobs_list.pop_front();
		//对任务队列的操作结束,释放锁
        pthread_mutex_unlock(&m_jobs_mutex);
        m_free_thread--;
        worker->isWorking = true;
        //执行job中的func
        job->func(job->user_data);
        worker->isWorking = false;
        free(job->user_data);
        free(job);
    }
    free(worker);
    pthread_exit(NULL);
}

//添加任务
bool ThreadPool::_addJob(NJOB *job) {
	//尝试获取锁
    pthread_mutex_lock(&m_jobs_mutex);
    //判断队列是否超过任务数量上限
    if (m_jobs_list.size() >= m_max_jobs){
        pthread_mutex_unlock(&m_jobs_mutex);
        return false;
    }
    //向任务队列添加job
    m_jobs_list.push_back(job);
    //唤醒休眠的线程
    pthread_cond_signal(&m_jobs_cond);
    //释放锁
    pthread_mutex_unlock(&m_jobs_mutex);
	return true;
}

//构造函数
ThreadPool::ThreadPool(int numWorkers, int max_jobs = 10) : m_sum_thread(numWorkers), m_free_thread(numWorkers), m_max_jobs(max_jobs){   //numWorkers:线程数量
    if (numWorkers < 1 || max_jobs < 1){
        perror("workers num error");
    }
    //初始化jobs_cond
    if (pthread_cond_init(&m_jobs_cond, NULL) != 0)
        perror("init m_jobs_cond fail\n");

    //初始化jobs_mutex
    if (pthread_mutex_init(&m_jobs_mutex, NULL) != 0)
        perror("init m_jobs_mutex fail\n");

    //初始化workers
    m_workers = new NWORKER[numWorkers];
    if (!m_workers){
        perror("create workers failed!\n");
    }
	//初始化每个worker
    for (int i = 0; i < numWorkers; ++i){
        m_workers[i].pool = this;
        int ret = pthread_create(&(m_workers[i].threadid), NULL, _run, &m_workers[i]);
        if (ret){
            delete[] m_workers;
            perror("create worker fail\n");
        }
        if (pthread_detach(m_workers[i].threadid)){
            delete[] m_workers;
            perror("detach worder fail\n");
        }
        m_workers[i].terminate = 0;
    }
}
//析构函数
ThreadPool::~ThreadPool(){
	//terminate值置1
    for (int i = 0; i < m_sum_thread; i++){
        m_workers[i].terminate = 1;
    }
    //广播唤醒所有线程
    pthread_mutex_lock(&m_jobs_mutex);//因为使用了detach创造线程,必须唤醒所有条件等待的线程
    pthread_cond_broadcast(&m_jobs_cond);
    pthread_mutex_unlock(&m_jobs_mutex);
    delete[] m_workers;
}

大端模式:低位字节存在高地址上,高位字节存在低地址上
小端模式:高位字节存在高地址上,低位字节存在低地址上

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

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

相关文章

【Linux】socket编程(二)

目录 前言 TCP通信流程 TCP通信的代码实现 tcp_server.hpp编写 tcp_server.cc服务端的编写 tcp_client.cc客户端的编写 整体代码 前言 上一章我们主要讲解了UDP之间的通信&#xff0c;本章我们将来讲述如何使用TCP来进行网络间通信&#xff0c;主要是使用socket API进…

whisper 语音识别项目部署

1.安装anaconda软件 在如下网盘免费获取软件&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1zOZCQOeiDhx6ebHh5zNasA 提取码&#xff1a;hfnd 2.使用conda命令创建python3.8环境 conda create -n whisper python3.83.进入whisper虚拟环境 conda activate whisper4.…

MyBatis的核心技术掌握---分页功能,详细易懂(下)

目录 一.前言 二.MyBatis 的分页 三.MyBatis 的特殊字符处理 一.前言 继上篇MyBatis 的文章&#xff0c;我们继续来学习MyBatis吧&#xff01;&#xff01;&#xff01; 上篇的博客链接&#xff1a; http://t.csdn.cn/5iUEDhttp://t.csdn.cn/5iUED 接下来进…

什么是梯度下降

什么是梯度下降 根据已有数据的分布来预测可能的新数据&#xff0c;这是回归 希望有一条线将数据分割成不同类别&#xff0c;这是分类 无论回归还是分类&#xff0c;我们的目的都是让搭建好的模型尽可能的模拟已有的数据 除了模型的结构&#xff0c;决定模型能否模拟成功的关键…

电商项目part05 分布式ID服务实战

背景 日常开发中&#xff0c;需要对系统中的各种数据使用 ID 唯一表示&#xff0c;比如用户 ID 对应且仅对应一个人&#xff0c;商品 ID 对应且仅对应一件商品&#xff0c;订单 ID 对应且仅对应 一个订单。现实生活中也有各种 ID&#xff0c;比如身份证 ID 对应且仅对应一个人…

XL74HC165 Parallel-2-Serail Controller

XL74HC165 Parallel-2-Serail Controller (SOP16) ( SN74LS165, CD74LS165 - DIP16 / SOP16 ) ( 不频繁存取, 可以考虑 I2C I/O Expender ) PCF8574/ T module (8bits Address *0x40~0x4E* ) PCF8574A module (8bit address *0x70~0x7E* )XL74HC165 fmax : VCC 3.3V &l…

冠达管理股票分析:首家!券商放大招,立马拉升

A股的“回购潮”&#xff0c;开始蔓延至券商行业。 广东研山私募证券投资&#xff08;百度搜索冠达管理)基金管理有限公司成立于2022年&#xff0c;是一家专注于私募基金管理的公司。8月23日盘后&#xff0c;国金证券发布公告称&#xff0c;收到控股股东长沙涌金&#xff08;集…

Fegin异步情况丢失上下文问题

在微服务的开发中&#xff0c;我们经常需要服务之间的调用&#xff0c;并且为了提高效率使用异步的方式进行服务之间的调用&#xff0c;在这种异步的调用情况下会有一个严重的问题&#xff0c;丢失上文下 通过以上图片可以看出异步丢失上下文的原因是不在同一个线程&#xff0c…

『PyQt5-基础篇』| 01 简单的基础了解

『PyQt5-基础篇』&#xff5c; 01 简单的基础了解 1 Qt了解1.1 支持的平台1.2 Qt Creator 2 PyQt52.1 PyQt5主要模块2.2 PyQt5主要类2.3 重要类的继承关系2.4 常用控件 1 Qt了解 跨平台C图形用户界面应用程序开发框架&#xff1b;既可以开发GUI程序&#xff0c;也可用于开发非…

JMeter分布式集群---部署多台机器进行性能压力测试

有些时候&#xff0c;我们在进行压力测试的时候&#xff0c;随着模拟用户的增加&#xff0c;电脑的性能&#xff08;CPU,内存&#xff09;占用是非常大的&#xff0c;为了我们得到更加理想的测试结果&#xff0c;我们可以利用jmeter的分布式来缓解机器的负载压力&#xff0c;分…

LVS集群 (四十四)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、集群概述 1. 负载均衡技术类型 2. 负载均衡实现方式 二、LVS结构 三、LVS工作模式 四、LVS负载均衡算法 1. 静态负载均衡 2. 动态负载均衡 五、ipvsadm命令详…

npm报错:xxx packages are looking for funding run `npm fund` for details(解决办法)

报错信息&#xff1a;30 packages are looking for funding run npm fund for details 报错原因&#xff1a;这里是开发者捐赠支持的提示&#xff0c;打开一个github的链接之后&#xff0c;会显示是否需要打赏捐赠的信息。 解决方案&#xff1a;这个打赏是资源的&#xff0c;因…

Golang Gorm 一对多关系 关系表创建

一对多关系 我们先从一对多开始多表关系的学习因为一对多的关系生活中到处都是&#xff0c;例如&#xff1a; 老板与员工女神和添狗老师和学生班级与学生用户与文章 在创建的时候先将没有依赖的创建。表名称ID就是外键。外键要和关联的外键的数据类型要保持一致。 package ma…

投影标杆,旗舰实力,极米投影仪Z7X为用户创造影院级体验

2023年&#xff0c;在彩电消费市场复苏疲软的背景下&#xff0c;智能投影这个显示新品类却持续走红。今年第一季度&#xff0c;极米科技推出Z系列全新一代产品极米Z7X&#xff0c;和极米Z6相比&#xff0c;在保持轻薄体积不变的情况下将亮度提升了83%&#xff0c;达到600CCB 流…

五、linux分析命令

linux分析命令 一、服务器基础知识二、linux文件结构三、linux文件权限四、linux命令1、安装应用fedora家族: 如centosdebain家族&#xff1a;如ubuntu 2、获取帮助第一种&#xff1a;command --help第二种&#xff1a;man command第三种&#xff1a;info 3、服务器性能分析基础…

先加密后签名还是先签名后加密?

先签名后加密还是先加密后签名呢&#xff1f; 先说结论&#xff0c;通常情况下应该先签名后加密。 签名算法计算出来的签名是为了验证消息的完整性&#xff0c;签名算法有比如HMAC-SHA256&#xff0c;加密算法则是为了保证消息的机密性&#xff0c;类似AES-GCM、AES-CBC&#…

海马优化(SHO)算法(含开源MATLAB代码)

先做一个声明&#xff1a;文章是由我的个人公众号中的推送直接复制粘贴而来&#xff0c;因此对智能优化算法感兴趣的朋友&#xff0c;可关注我的个人公众号&#xff1a;启发式算法讨论。我会不定期在公众号里分享不同的智能优化算法&#xff0c;经典的&#xff0c;或者是近几年…

最小二乘法——参数估计过程推导

一 准备 1 给定数据集 D{(),(),...,()},其中假设X是一维的情况&#xff0c;即只有一个自变量 2 线性回归学习的目标&#xff1a;,使得 3 如何确定w和b&#xff1f;关键在于衡量f(x)和y之间距离的方法&#xff0c;此处使用的是‘均方误差’&#xff0c;其具有非常好的几何意义&a…

23款奔驰GLE450时尚型升级ACC自适应巡航系统,解放双脚缓解驾驶疲劳

有的时候你是否厌倦了不停的刹车、加油&#xff1f;是不是讨厌急刹车&#xff0c;为掌握不好车距而烦恼&#xff1f;如果是这样&#xff0c;那么就升级奔驰原厂ACC自适应式巡航控制系统&#xff0c;带排队自动辅助和行车距离警报功能&#xff0c;感受现代科技带给你的舒适安全和…

英特尔开始加码封装领域 | 百能云芯

在积极推进先进制程研发的同时&#xff0c;英特尔正在加大先进封装领域的投入。在这个背景下&#xff0c;该公司正在马来西亚槟城兴建一座全新的封装厂&#xff0c;以加强其在2.5D/3D封装布局领域的实力。据了解&#xff0c;英特尔计划到2025年前&#xff0c;将其最先进的3D Fo…