Linux 内核实时补丁 PREEMPT_RT补丁 与 Linux4.1.15 + patch-4.1.15-rt18.patch 补丁,实测实时性差
Linux4.1.15 + patch-4.1.15-rt18.patch 补丁,实测实时性差
开发环境
发行环境
该环境用于发行
Linux: 4.1.15
preempt_rt: patch-4.1.15-rt18.patch
SOC: i.MX6Q
board: 飞凌OK_MX6X_C_V1.3
运行程序: main (最终部署程序)
开发环境
在开发阶段使用的该环境
Linux: 3.14.52
preempt_rt: patch-3.14.51-rt52.patch
SOC: i.MX6Q
board: LYS-IMX6Q
测试程序:test (实时测试程序)
测试环境
测试环境
使用Keysight MSOX4034A示波器进行测试, 探头一接入网络数据输入口RGMII_RXD0, 探头二接入CAN数据输出口TXD; 触发方式采用依次按边沿触发, 当1通道触发4ns后2通道触发即触发; 示波器水平时间/格为1ms; 数据输入周期为100ms/10Hz.
测试程序
创建服务器端socket套接字接受客户端发送过来的指令, 当接受到指令后, 立即向CAN总线发送一帧数据
目标
在发行环境中搭建起Linux实时环境并运行程序,实测达到实时性要求(抖动在200us内)
在开发环境中已经实现目标,现需要迁移到发行环境中
问题
在10000次的测试中,平均延时225.63us;最小延时207.0us;最大延时7.0243ms;计数值低于实际发送值
其最大延时远超预期,不是实时操作系统的结果。而且在随着示波器水平时间的增大最大延时也随之增大。可以推出:在测试过程中有在示波器当前配置的检测范围外的数据。
解决过程
我仔细梳理了以前的测试过程,结果,以及现在测试的过程,结果。首先明确了并再次证实了以前测试的结果是正确的,通过打补丁,测试实时进程,测试方法这一系列流程都是正确的。并在之前的板子是验证了。但现在的这块飞凌板不行。问题出在哪了?
仔细与上一个开发板的步骤与环境进行对比,得出如下结论:
补丁文件正确,打补丁无误,针对补丁的内核配置无误,测试方法无误,程序交叉测试也正常运行。(消耗2天时间)
那这过程中所有步骤都正确无误,那又是什么问题导致了呢。
既然过程中的步骤无误,那就从过程中不同点出发,不同点如下:
1.Linux内核版本不同
2.preempt_rt版本不同,跟随内核版本变化
3.设备树不同
4.根文件系统不同
5.测试程序不同
遂针对以上不同点进行排查。
首先在经过验证的。然后是根文件系统,安装了两个不同的根文件系统,运行相同程序,实验结果无实时。说明根文件系统的不同对其无影响。
然后是测试程序不同,将test/main运行在开发环境,最大延时200us左右,抖动在100us以内,说明程序中实时性操作步骤对于开发环境是正确的。然而将test/main运行在发行环境,最大延时都在ms级;当时就联想到了会不会是Linux内核版本不同所以实时进程的操作方式会不同呢。翻阅了很多资料,其中最有效的链接如下:
Real-Time Linux Wiki
HOWTO: RTOS and RT Applications
参照其中创建RT线程的步骤,顺利解决了我的问题。后面我将结合我之前的操作步骤以及链接中的内容。给出我的实现步骤
Linux + PREEMPT_RT 实现步骤
1.参照HOWTO setup Linux with PREEMPT_RT properly该链接下载补丁,并打上补丁,配置内核,最后编译内核
2.步骤1中的编译环节如果出现问题。请参考如下修改:
1.include/linux/imx_sema4.h
+#include <linux/wait-simple.h> +20
- wait_queue_head_t *wqp; +43
+ struct swait_head *wqp;2.drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c +7365/+7402/+7430
- spin_lock_irq(&x->wait.lock);
+ raw_spin_lock_irq(&x->wait.lock);
- spin_unlock_irq(&signal->obj.wait.lock);
+ raw_spin_unlock_irq(&signal->obj.wait.lock);
总共有4处3.drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c +7390
- DECLARE_WAITQUEUE(wait, current);
- wait.flags |= WQ_FLAG_EXCLUSIVE;
- __add_wait_queue_tail(&signal->obj.wait, &wait);
+ DEFINE_SWAITER(wait);
+ swait_prepare_locked(&signal->obj.wait, &wait);
3.drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c +7429
- __remove_wait_queue(&signal->obj.wait, &wait);
+ swait_finish_locked(&signal->obj.wait, &wait);
3.编译好内核后,进行烧录,并启动。启动好的系统运行程序,并不是实时的。需要程序去控制实时。
在Linux 3.14.52版本中,我的操作方式如下
int process_set_rt(void)
{/* 设置进程为实时进程, 提高优先级 */pid_t pid = getpid();struct sched_param param;param.sched_priority = sched_get_priority_max(SCHED_FIFO); // 也可用SCHED_RRsched_setscheduler(pid, SCHED_FIFO, ¶m); // 设置当前进程return 0;
}
然后在你需要实时的进程运行业务前执行**process_set_rt()**函数。经过实测,该进程创建的线程也是实时的。
在Linux 4.1.15版本中,我的操作方式如下
int create_rt_thread(pthread_t* thread, void *(*thread_func)(void))
{struct sched_param param;pthread_attr_t attr;int ret;/* Lock memory */if(mlockall(MCL_CURRENT|MCL_FUTURE) == -1) {printf("mlockall failed: %m\n");return -1;}/* Initialize pthread attributes (default values) */ret = pthread_attr_init(&attr);if(ret) {printf("init pthread attributes failed\n");return -1;}/* Set a specific stack size */ret = pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN);if(ret) {printf("pthread setstacksize failed\n");return -1;}/* Set scheduler policy and priority of pthread */ret = pthread_attr_setschedpolicy(&attr, SCHED_FIFO);if(ret) {printf("pthread setschedpolicy failed\n");return -1;}param.sched_priority = 80;ret = pthread_attr_setschedparam(&attr, ¶m);if (ret) {printf("pthread setschedparam failed\n");return -1;}/* Use scheduling parameters of attr */ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);if (ret) {printf("pthread setinheritsched failed\n");return -1;}/* Create a pthread with specified attributes */ret = pthread_create(thread, &attr, thread_func, NULL);if (ret) {printf("create pthread failed\n");return -1;}return 0;
}
对于需要实时的线程,用**create_rt_thread()**函数创建实时线程。
注意:
Keep in mind that the usual sequence is for an application to begin its execution as a regular (non-RT) application, then create the RT threads with appropriate resources and scheduling parameters.
意思就是说:创建实时线程的进程需是非实时进程。
以上是我对实时补丁的理解,如有错误欢迎指正,同时期待猿友给出为什么在Linux3.14.52中能实时的操作,在Linux4.1.15中却无法实时。期待你们的答案,谢谢!
附上我解决问题中参考的链接
Linux内核Kconfig语法
PREEMPT_RT下载地址
关于Linux Preempt RT补丁的实时编程问题?
Linux内核配置解析 - 概述(基于ARM64架构)
Linux 内核实时补丁 PREEMPT_RT补丁 与 Linux4.1.15 + patch-4.1.15-rt18.patch 补丁,实测实时性差相关推荐
- Scratch 被禁止访问;Linux 内核历史报告2020 等开源之道每周评论2020 09 15
点击上方蓝字,关注开源之道 声明:本文所言论,仅代表适兕个人观点 论文阅读心得与体会 Linux 内核历史报告2020 原文链接:the 2020 Linux Kernel History Repor ...
- Linux 内核开发者完成了对所有来自 UMN.edu 补丁的审查
导读 前段时间,明尼苏达大学被禁止为 Linux 内核做贡献,因为该大学的研究人员被发现试图通过新的补丁故意向内核提交错误,而使这个过程作为一篇有问题的研究论文的一部分这种不诚实甚至恶意行为而引发轩然 ...
- Linux内核之时间系统
Linux内核之时间系统 1.Linux时间系统 (1)CMOS时钟 (2)系统时钟 (3)节拍数(jiffies) (4)墙上时间(xtime) 2.重要数据结构 (1)struct tk_read ...
- Linux 内核修复5个高危漏洞
聚焦源代码安全,网罗国内外最新资讯! 作者: Steven J. Vaughan-Nichols 编译:奇安信代码卫士团队 Positive Technologies 公司的Linux 安全开发员 ...
- Linux内核开发_1_编译LInux内核
目录 1. 准备工作 1.1 学习环境 1.2 下载Linux内核源码 1.3 解压Linux内核 1.4 目录结构介绍 2. Linux内核配置 2.1 配置选项 1. make config 2. ...
- 【Linux 内核】线程调度示例一 ② ( 获取指定调度策略的最大和最小优先级 | 代码示例 )
文章目录 一.获取指定调度策略的最大和最小优先级函数 二.获取指定调度策略的最大和最小优先级代码示例 一.获取指定调度策略的最大和最小优先级函数 Linux 内核中 , 通过下面 222 个函数 , ...
- 【Linux 内核】进程优先级与调度策略 ② ( 获取调度策略对应的进程优先级函数 | sched_get_priority_max 函数 | sched_get_priority_min 函数 )
文章目录 一.获取进程优先级函数 二.调度策略参数 三.进程优先级说明 在上一篇博客 [Linux 内核]进程优先级与调度策略 ① ( SCHED_FIFO 调度策略 | SCHED_RR 调度策略 ...
- Linux内核学习之路_1_编译Linux内核
1.准备工作 1.1 学习环境 1.2 下载Linux内核源码 1.3 解压Linux内核 1.4 目录结构介绍 1.2.2 Linux内核配置 1.1 学习环境 本系列教程使用的环境如下: 操作系统 ...
- linux内核时间函数us,Linux上系统时间函数、DST等相关有关问题总结
http://www.reader8.cn/jiaocheng/20120910/1995886.html 2012 Linux下系统时间函数.DST等相关问题总结1. 内核中时间的基本类型:在Lin ...
最新文章
- Java项目:在线蛋糕商城系统(java+jsp+jdbc+mysql)
- R假设检验之Shapiro检验(正太分布判断)
- 群同态基本定理证明_近世代数(3)——群的基本性质
- [模板]tarjan求强连通分量
- php实现单选和多选功能,input:checkbox多选框实现单选效果跟radio一样
- 正负相关 最大信息系数mic_求二项展开式中二项式系数最大项、系数最大项的问题...
- 【SSH】——Struts2中的动态方法调用(一)
- OPCClient远程连接OPC服务器配置手册 【转】
- circle后面是什么意思 python_Ape circle Python操作-第2-01章-列表操作,小猿圈,作业
- 多版本opencv 兼容
- MySQL系统自带的数据库information schema
- [转载] 手工制作Win7 OEM版
- Ghost4J库安装,找不到gsdll64.dll或libgs.so报错
- louvain算法python_python – 如何在igraph中运行louvain社区检测算法?
- 爬取链家网上海二手房数据,并进行分析建模
- 【Python】socket编程——使用TCP协议实现智能聊天机器人
- 汇编语言编写程序从1加到100要求使用循环结构。
- Incorrect string value: '\xF0\x9F\x91\x80' for column数据库中添加表情报错
- 充分必要条件与C语言,充分条件与必要条件知识点总结,高中数学充分条件与必要条件知识点总结...
- 最强解决网页复制文字等问题