300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > Linux 内核实时补丁 PREEMPT_RT补丁 与 Linux4.1.15 + patch-4.1.15-rt18.patch 补丁 实测实时性差

Linux 内核实时补丁 PREEMPT_RT补丁 与 Linux4.1.15 + patch-4.1.15-rt18.patch 补丁 实测实时性差

时间:2020-05-02 19:17:37

相关推荐

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, &param); // 设置当前进程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, &param);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架构)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。