day07

回顾:
面试题:谈谈对中断的理解
1.谈为什么有中断
2.中断的硬件触发流程
  画图
3.中断的软件编程
  画图
4.linux内核中断编程
5.linux内核对中断处理函数的要求
6.linux内核中断编程的顶半部和底半部机制
7.顶半部特点
8.底半部特点
9.底半部实现方式
  tasklet特点
  工作队列特点
  软中断特点
 
2.linux内核软件定时器
  硬件定时器特点
  硬件定时器的中断处理函数
  HZ/jiffies
  struct timer_list
          .expires
          .function
          .data
  配套函数
  init_timer/add_timer/del_timer/mod_timer
  软件定时器基于软中断实现,不能进行休眠操作
 
3.linux内核并发和竞态
    3.1.掌握笔记中的两个经典案例
    3.2.概念
            并发
            竞态
            共享资源
            临界区
            互斥访问
            执行路径具有原子性
  3.3.竞态引起异常的四种情形
      多核
      同一CPU上的进程与进程的抢占
      中断和进程
      中断和中断
      画图
  3.4.解决竞态引起异常的四种方法
      中断屏蔽
      自旋锁
      信号量
      原子操作
 
4.解决竞态引起异常的方法之中断屏蔽
  中断屏蔽特点:
  能够解决进程与进程之前的抢占引起的异常(进程之前的抢占本身基于软中断实现)
  能够解决中断和进程的抢占引起的异常
  能够解决中断和中断引起的异常
  无法解决多核引起的异常
  中断屏蔽保护的临界区的代码执行速度要越快越好,更不能进行休眠操作
  因为linux系统的很多机制跟中断密切相关(tasklet,软件定时器,硬件定时器等)
  长时间的屏蔽中断非常危险
   
  利用中断屏蔽解决竞态引起的异常的编程步骤:
  1.明确驱动代码中哪些是共享资源
  2.明确驱动代码中哪些是临界区
  3.明确保护的临界区中是否有休眠操作
    如果有休眠操作,势必不考虑中断屏蔽
    如果没有,并且没有多核参与竞态,可以考虑使用中断屏蔽
  4.访问临界区之前屏蔽中断
      unsigned long flags;
      local_irq_save(flags);//屏蔽中断,保存中断标志到flags(内核来完成)
  5.任务踏踏实实的访问临界区
    此时会有其他进程的抢占吗?没有
    此时会有其他的中断来打断吗?没有
  6.访问临界区之后,记得将中断进行恢复
    local_irq_restore(flags);//恢复中断
  7.屏蔽中断和恢复中断务必要逻辑上成对使用
   
  案例:利用中断屏蔽来解决之前案例1中的代码漏洞
  实施步骤:同上
  案例:利用中断屏蔽解决LCD显示屏的问题
  void lcd_config(void) {
      unsigned long flags;
      local_irq_save(flags);
      //临界区
      gpio_set_value(..., 1);
      mdelay(5);
      gpio_set_value(..., 0);
      mdelay(5);
      local_irq_restore(flags);
  }
   
5.解决竞态引起异常的方法之自旋锁
  自旋锁特点:
  自旋锁能够解决多核引起的竞态问题
  自旋锁能够解决进程与进程之前的抢占引起的竞态问题
  自旋锁无法解决中断引起的竞态问题
  自旋锁保护的临界区的代码执行速度要快,更不能进行休眠操作
  没有获取自旋锁的任务将会原地忙等待(原地空转)
   
  linux内核描述自旋锁的数据类型:spinlock_t
   
  利用自旋锁解决竞态引起异常的编程步骤:
  1.明确驱动代码中哪些是临界区
  2.明确驱动代码中哪些是共享资源
  3.明确临界区中是否有休眠操作
    如果有,势必不考虑此方法
    如果没有,还要考虑是否有中断参与
    如果有中断参与,势必不考虑
    如果没有中断参与,可以考虑使用
  4.访问临界区之前先获取自旋锁
    //定义初始化一个自旋锁对象
    spinlock_t lock; //定义
    spin_lock_init(&lock); //初始化
    spin_lock(&lock);//获取自旋锁,如果获取成功,立马返回即可访问临界区
                                         如果获取失败,任务将在此函数中进行循环忙等待
                                         直到持有自旋锁的任务释放自旋锁
  5.任务获取自旋锁以后,即可踏踏实实的访问临界区
  6.访问临界区之后,记得要释放自旋锁
      spin_unlock(&lock);
  7.注意:获取自旋锁和释放自旋锁务必在逻辑上成对使用
   
  案例:利用自旋锁来解决案例1中的代码漏洞
  实验步骤同上
  案例:利用中断屏蔽解决LCD显示屏的问题
  void lcd_config(void) {
    spin_lock(&lock);
      //临界区
      gpio_set_value(..., 1);
      mdelay(5);
      gpio_set_value(..., 0);
      mdelay(5);
    spin_unlock(&lock);
  }
  //如果用自旋锁进行保护,发现LCD显示照样有问题,拿示波器抓取
    波形发现周期同样超过10ms,说明引起问题的原因在于中断参与抢占
    CPU资源
     
6.解决竞态引起异常的方法之衍生自旋锁
  衍生自旋锁特点:
  衍生自旋锁能够解决所有的竞态引起的异常问题
  衍生自旋锁=屏蔽中断+自旋锁
  衍生自旋锁保护的临界区的代码执行速度要快,更不能进行休眠操作
  没有获取衍生自旋锁的任务将会原地忙等待(原地空转)
   
  linux内核描述衍生自旋锁的数据类型:spinlock_t
   
  利用衍生自旋锁解决竞态引起异常的编程步骤:
  1.明确驱动代码中哪些是临界区
  2.明确驱动代码中哪些是共享资源
  3.明确临界区中是否有休眠操作
    如果有,势必不考虑此方法
    如果没有,可以考虑使用
  4.访问临界区之前先获取自旋锁
    //定义初始化一个衍生自旋锁对象
    spinlock_t lock; //定义
    spin_lock_init(&lock); //初始化
        unsigned long flags;
    spin_lock_irqsave(&lock, flags);//屏蔽中断,获取衍生自旋锁,如果获取成功,立马返回即可访问临界区
                                         如果获取失败,任务将在此函数中进行循环忙等待
                                         直到持有自旋锁的任务释放自旋锁
  5.任务获取衍生自旋锁以后,即可踏踏实实的访问临界区
  6.访问临界区之后,记得要释放衍生自旋锁,恢复中断
      spin_unlock_irqrestore(&lock);
  7.注意:获取衍生自旋锁和释放衍生自旋锁务必在逻辑上成对使用
   
  案例:利用衍生自旋锁来解决案例1中的代码漏洞
  实验步骤同上                                          
  案例:利用中断屏蔽解决LCD显示屏的问题
  void lcd_config(void) {
      unsigned long flags
    spin_lock_irqsave(&lock, flags);
      //临界区
      gpio_set_value(..., 1);
      mdelay(5);
      gpio_set_value(..., 0);
      mdelay(5);
    spin_unlock_irqrestore(&lock,flags);
  }
  利用衍生自旋锁能够解决异常问题!
 
7.解决竞态引起异常的方法之信号量
  内核信号量和用户的信号量一模一样
  信号量特点:
  信号量又称睡眠锁,基于自旋锁实现的
  信号量就是解决自旋锁保护的临界区不能休眠问题,有些场合
  临界区中需要进行休眠操作,此时此刻只能用信号量
  "休眠操作"仅仅存在于进程的世界中,进程休眠是指
  当前进程会释放占用的CPU资源给他们进程使用,信号量仅用于进程
  如果进程获取信号量,在访问临界区时,是可以进行休眠操作
  如果进程获取信号量失败,那么进程将进行休眠操作
   
  linux内核描述信号量的数据结构:struct semaphore
   
  利用信号量来解决竞态引起异常的编程步骤:
  1.明确驱动代码中哪些是共享资源
  2.明确驱动代码中哪些是临界区
  3.明确临界区中是否有休眠
    如果有,必须使用信号量
    如果没有,可以考虑使用信号量
  4.访问临界区之前,先获取信号量
    //定义初始化信号量对象
    struct seamphore sema; //定义信号量对象
    sema_init(&sema, 1); //初始化信号量对象
     
    //获取信号量
    down(&sema);
    说明:获取信号量,如果获取信号量成功,进程从此函数中立马返回
          然后可以踏踏实实的访问临界区
          如果获取信号量失败,进程将进入此函数中进入不可中断的
          休眠状态(释放CPU资源,在休眠期间接收到信号不会立即处理信号)
          直到持有信号量的进程释放了信号量并且唤醒这个休眠的等待进程
          "不可中断的休眠状态":进程在休眠期间,如果接收到了一个kill信号
                                                      进程不会立即处理接收到的信号,而是获取信号量的
                                                      任务释放信号量以后唤醒这个休眠的进程,进程一旦
                                                      被唤醒以后会处理之前接收到的信号
          “可中断的休眠状态”:进程在休眠期间,如果接收到了一个信号
                             进程会被立即唤醒并且处理接收到的信号
                                                                         
    或者
    down_interruptible(&sema);//获取信号量,如果获取信号量成功,进程从此函数中立马
                              返回,然后去访问临界区
                              如果获取信号量失败,进程将进入可中断的休眠状态
                              (休眠期间会立即处理接收到的信号)
                              直到获取信号被唤醒或者持有信号量的任务
                              释放信号量唤醒之前休眠的进程
   5.一旦获取信号量成功,进程可以踏踏实实的访问临界区
   6.访问临界区之后,记得释放信号量并且唤醒休眠的进程
     up(&sema);   
   7.获取信号量和释放信号量一定要在逻辑上成对使用
    
   案例:利用信号量down,实现一个设备只能被打开一次
   上位机实施步骤:同上
   下位机测试步骤:
   cd /home/drivers/
   insmod led_drv.ko
   ./led_test & //启动A进程,A进程打开成功,A进程调用sleep进行休眠
                                 不关闭
   ./led_test & //启动B进程,B进程获取信号量失败,进入不可中断的休眠状态
                                   等待A进程来唤醒
   ps //查看A,B的PID
   top //查看A,B的进程状态
           S:进程进入可中断的休眠状态
           D:进程进入不可中断的休眠状态
   按Q键退出top命令
   kill B的PID //给B进程发送kill信号
   ps
   top
   kill A的PID //杀死A进程,A进程关闭设备,释放信号量并且唤醒
                 B进程,B进程一旦被唤醒,B还要去处理之前接收到
                 的信号
   ps
   top
                                        
   ./led_test & //启动A进程,A进程打开成功,A进程调用sleep进行休眠
                                 不关闭
   ./led_test & //启动B进程,B进程获取信号量失败,进入不可中断的休眠状态
                                   等待A进程来唤醒
   ps //查看A,B的PID
   top //查看A,B的进程状态
           S:进程进入可中断的休眠状态
           D:进程进入不可中断的休眠状态
   按Q键退出top命令
   kill A的PID //给A进程发送kill信号
   ps
   top  //查看B进程的状态是否还是D,不是,变成了S,因为应用程序调用sleep
   kill B的PID  
    
    
   问题:内核吐核问题:
   INFO: task led_test:1032 blocked for more than 10 seconds.
   "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message
    
   解决办法:下位机执行:
   echo 0 > /proc/sys/kernel/hung_task_timeout_secs
    
           
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 支持向量机非线性回归通用MATLAB程序解析 #### 一、概述 本文将详细介绍一个基于MATLAB的支持向量机(SVM)非线性回归的通用程序。该程序采用支持向量机方法来实现数据的非线性回归,并通过不同的核函数设置来适应不同类型的数据分布。此外,该程序还提供了数据预处理的方法,使得用户能够更加方便地应用此程序解决实际问题。 #### 二、核心功能与原理 ##### 1. 支持向量机(SVM) 支持向量机是一种监督学习模型,主要用于分类和回归分析。对于非线性回归任务,SVM通过引入核技巧(kernel trick)将原始低维空间中的非线性问题转换为高维空间中的线性问题,从而实现有效的非线性建模。 ##### 2. 核函数 核函数的选择直接影响到模型的性能。本程序内置了三种常用的核函数: - **线性核函数**:`K(x, y) = x'y` - **多项式核函数**:`K(x, y) = (x'y + 1)^d` - **径向基函数(RBF)**:`K(x, y) = exp(-γ|x - y|^2)` 其中RBF核函数被广泛应用于非线性问题中,因为它可以处理非常复杂的非线性关系。本程序默认使用的是RBF核函数,参数`D`用于控制高斯核函数的宽度。 ##### 3. 数据预处理 虽然程序本身没有直接涉及数据预处理的过程,但在实际应用中,对数据进行适当的预处理是非常重要的。常见的预处理步骤包括归一化、缺失值处理等。 ##### 4. 模型参数 - **Epsilon**: ε-insensitive loss function的ε值,控制回归带宽。 - **C**: 松弛变量的惩罚系数,控制模型复杂度与过拟合的风险之间的平衡。 #### 三、程序实现细节 ##### 1. 函数输入与输出 - **输入**: - `X`: 输入特征矩阵,维度为(n, l),其中n是特征数量,l是样本数量。 - `Y`: 目标值向量,长度为l。 - `Epsilon`: 回归带宽。 - `C`: 松弛变量的惩罚系数。 - `D`: RBF核函数的参数。 - **输出**: - `Alpha1`: 正的拉格朗日乘子向量。 - `Alpha2`: 负的拉格朗日乘子向量。 - `Alpha`: 拉格朗日乘子向量。 - `Flag`: 标记向量,表示每个样本的类型。 - `B`: 偏置项。 ##### 2. 核心代码解析 程序首先计算所有样本间的核矩阵`K`,然后构建二次规划问题并求解得到拉格朗日乘子向量。根据拉格朗日乘子的值确定支持向量,并计算偏置项`B`。 - **核矩阵计算**:采用RBF核函数,通过`exp(-(sum((xi-xj).^2)/D))`计算任意两个样本之间的相似度。 - **二次规划**:构建目标函数和约束条件,使用`quadprog`函数求解最小化问题。 - **支持向量识别**:根据拉格朗日乘子的大小判断每个样本是否为支持向量,并据此计算偏置项`B`。 #### 四、程序扩展与优化 - **多核函数支持**:可以通过增加更多的核函数选项,提高程序的灵活性。 - **自动调参**:实现参数自动选择的功能,例如通过交叉验证选择最优的`Epsilon`和`C`值。 - **并行计算**:利用MATLAB的并行计算工具箱加速计算过程,特别是当样本量很大时。 #### 五、应用场景 该程序适用于需要进行非线性回归预测的场景,如经济预测、天气预报等领域。通过调整核函数和参数,可以有效应对各种类型的非线性问题。 ### 总结 本程序提供了一个支持向量机非线性回归的完整实现框架,通过灵活的核函数设置和参数调整,能够有效地处理非线性问题。对于需要进行回归预测的应用场景,这是一个非常实用且强大的工具。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值