前言
本文主要是一些学习笔记的汇总,主要参考公众号:嵌入式与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;
}
大端模式:低位字节存在高地址上,高位字节存在低地址上
小端模式:高位字节存在高地址上,低位字节存在低地址上