版权声明:本文为本文为博主原创文章,转载请注明出处。如有错误,欢迎指正。

@

一、添加系统调用

下面给xenomai添加一个系统调用get_timer_hits(),用于获取应用程序运行CPU的定时器中断产生的次数,类似于VxWorks里的tickGet()。需要说明一下VxWorks是采用周期tick的方式来驱动系统运作,tickGet()获取的也就是tick定时器中断的次数,但xenomai使用的tickless,即定时器不是周期产生tick的。所以get_timer_hits()用于获取定时器中断次数,get_timer_hits()没有具体用途,这里主要用来举例怎么为xenomai添加一个实时系统调用。

在前两篇文中说到,xenomai每个系统的系统系统调用号在\cobalt\uapi\syscall.h中:

#define sc_cobalt_bind				0
#define sc_cobalt_thread_create 1
#define sc_cobalt_thread_getpid 2
......
#define sc_cobalt_extend 96

在此添加sc_cobalt_get_timer_hits的系统,为了避免与xenomai系统调用冲突(xenomai官方添加的系统调用号从小到大),那我们就从最后一个系统调用添加,即127号系统调用,如下。

#define sc_cobalt_bind				0
#define sc_cobalt_thread_create 1
#define sc_cobalt_thread_getpid 2
......
#define sc_cobalt_extend 96
#define sc_cobalt_ftrace_puts 97
#define sc_cobalt_recvmmsg 98
#define sc_cobalt_sendmmsg 99
#define sc_cobalt_clock_adjtime 100
#define sc_cobalt_thread_setschedprio 101 #define sc_cobalt_get_timer_hits 127
#define __NR_COBALT_SYSCALLS 128 /* Power of 2 */

先确定一下我们这个函数的API形式,由于是一个非标准的形式,这里表示如下:

int get_timer_hits(unsigned long *u_tick);

参数为保存hits的变量地址;

返回值:成功0;出错 <0;

系统调用的头文件,然后添加一个系统调用的声明,觉得它和clock相关,那就放在kernel\xenomai\posix\clock.h中吧。

#include <linux/ipipe_tickdev.h>

COBALT_SYSCALL_DECL(get_timer_hits,
(unsigned long __user *u_tick));

然后是该函数的内核实现,放在/kernel\xenomai\posix\clock.c,如下:

COBALT_SYSCALL(get_timer_hits, primary,
(unsigned long __user *u_tick))
{
struct xnthread *thread;
unsigned long tick;
int cpu;
int ret = 0;
unsigned int irq; thread = xnthread_current();
if (thread == NULL)
return -EPERM; /*得到当前任务CPU号*/
cpu = xnsched_cpu(thread->sched); irq = per_cpu(ipipe_percpu.hrtimer_irq, cpu);
/*读取该CPU中断计数*/
tick = __ipipe_cpudata_irq_hits(&xnsched_realtime_domain, cpu,
irq);
if (cobalt_copy_to_user(u_tick, &tick, sizeof(tick)))
return -EFAULT; return ret;
}

需要注意的是该系统调用的权限,这里使用primary,表示只有cobalt上下文(实时线程)才能调用。

修改完成后重新编译内核并安装。

二、Cobalt库添加接口

在前两篇文中说到,xenomai系统调用由libcobalt发起,所以修改应用库来添加该函数接口,添加声明include\cobalt\time.h

COBALT_DECL(int, get_timer_hits(unsigned long tick));

xenomai3.x.x\lib\cobalt\clock.c添加该接口定义:

COBALT_IMPL(int, get_timer_hits, (unsigned long * tick))
{
int ret; ret = -XENOMAI_SYSCALL1(sc_cobalt_get_tick,
tick); return ret;
}

重新编译并安装xenomai库,详见本博客其他文章。

三、应用使用

由于我们添加get_timer_hits()系统调用时,指定了系统调用的权限为primary,这里创建一个实时任务,使用宏__RT()指定链接到libcobalt库。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sched.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#include <alchemy/sem.h>
#include <boilerplate/trace.h>
#include <xenomai/init.h> #define PRIO 50 void test(void *cookie)
{
unsigned long tick;
int ret;
ret = __RT(get_timer_hits(&tick));
if (ret){
fprintf(stderr,
"%s: failed to get_tick,%s\n",
__func__,strerror(-ret));
return ret;
}
fprintf(stdout,"timer_hits:%ld\n",tick);
/*....*/
return 0;
} int main(int argc, char *const *argv)
{
struct sigaction sa __attribute__((unused));
int sig, cpu = 0;
char sem_name[16];
sigset_t mask;
RT_TASK task;
int ret; sigemptyset(&mask);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGTERM);
sigaddset(&mask, SIGHUP);
sigaddset(&mask, SIGALRM);
pthread_sigmask(SIG_BLOCK, &mask, NULL);
setlinebuf(stdout); ret = rt_task_spawn(&task, "test_task", 0, PRIO,
T_JOINABLE, test, NULL);
if (ret){
fprintf(stderr,
"%s: failed to create task,%s\n",
__func__,strerror(-ret));
return ret;
} __STD(sigwait(&mask, &sig));
rt_task_join(&task);
rt_task_delete(&task); return 0;
}

编译Makefile:

XENO_CONFIG := /usr/xenomai/bin/xeno-config

PROJPATH = .

CFLAGS := $(shell $(XENO_CONFIG)   --posix --alchemy --cflags)
LDFLAGS := $(shell $(XENO_CONFIG) --posix --alchemy --ldflags)
INCFLAGS= -I$(PROJPATH)/include/ EXECUTABLE := get-timer-hits src = $(wildcard ./*.c)
obj = $(patsubst %.c, %.o, $(src)) all: $(EXECUTABLE) $(EXECUTABLE): $(obj)
$(CC) -g -o $@ $^ $(INCFLAGS) $(CFLAGS) $(LDFLAGS) %.o:%.c
$(CC) -g -o $@ -c $< $(INCFLAGS) $(CFLAGS) $(LDFLAGS) .PHONY: clean
clean:
rm -f $(EXECUTABLE) $(obj)

运行结果:

$./get-timer-hits
timer_hits:3

可以看到,虽然系统已经启动十几分钟了,但一直没有运行xenomai应用,xenomai tick相关中断才产生了3次,这就是tickless,后面会出xenomai调度及时间子系统相关文章,敬请关注。

xenomai内核解析--双核系统调用(三)--如何为xenomai添加一个系统调用的更多相关文章

  1. 【原创】xenomai内核解析--双核系统调用(二)--应用如何区分xenomai/linux系统调用或服务

    版权声明:本文为本文为博主原创文章,转载请注明出处.如有错误,欢迎指正. 1. 引出问题 上一篇文章xenomai内核解析--双核系统调用(一)以X86处理器为例,分析了xenomai内核调用的流程, ...

  2. 【原创】xenomai内核解析--xenomai与普通linux进程之间通讯XDDP(一)--实时端socket创建流程

    版权声明:本文为本文为博主原创文章,转载请注明出处.如有问题,欢迎指正.博客地址:https://www.cnblogs.com/wsg1100/ 1.概述 上篇文章xenomai内核解析--实时IP ...

  3. 【xenomai内核解析】系列文章大纲

    xenomai内核解析 本博客为本人学习linux实时操作系统框架xenomai的一些记录,主要剖析xenomai内核实现,以及与linux相关的知识.方便读者定位具体文章,现列出本博客大纲,后续会陆 ...

  4. 【原创】xenomai内核解析--xenomai与普通linux进程之间通讯XDDP(三)--实时与非实时数据交互

    版权声明:本文为本文为博主原创文章,转载请注明出处.如有问题,欢迎指正.博客地址:https://www.cnblogs.com/wsg1100/ 目录 1.概述 1.概述 [原创]实时IPC概述 [ ...

  5. xenomai内核解析之信号signal(二)---xenomai信号处理机制

    xenomai信号 上篇文章讲了linux的信号在内核的发送与处理流程,现在加入了cobalt核,Cobalt内核为xenomai线程提供了信号机制.下面一一解析xenomai内核的信号处理机制. 1 ...

  6. xenomai内核解析---内核对象注册表—xnregistry(重要组件)

    1. 概述 上篇文章xenomai内核解析--同步互斥机制(一)--优先级倒置讲到,对于所有内核对象: xnregistry:保存内核对象,提供内核对象存储和快速检索. xnsynch:资源抽象,提供 ...

  7. 【原创】xenomai内核解析--xenomai与普通linux进程之间通讯XDDP(二)--实时与非实时关联(bind流程)

    版权声明:本文为本文为博主原创文章,转载请注明出处.如有问题,欢迎指正.博客地址:https://www.cnblogs.com/wsg1100/ 1.概述 上篇文章介绍了实时端socket创建和配置 ...

  8. [保姆级教程] 如何在 Linux Kernel (V5.17.7) 中添加一个系统调用(System call)

    最近在学习 <linux Kernel Development>,本书用的linux kernel 是v2.6 版本的.看完"系统调用"一节后,想尝试添加一个系统调用, ...

  9. xenomai内核解析之双核系统调用(一)

    版权声明:本文为本文为博主原创文章,转载请注明出处.如有错误,欢迎指正.博客地址:https://www.cnblogs.com/wsg1100/ 目录 xenomai 内核系统调用 一.32位Lin ...

随机推荐

  1. Python 为什么不支持 i++ 自增语法,不提供 ++ 操作符?

    在 C/C++/Java 等等语言中,整型变量的自增或自减操作是标配,它们又可分为前缀操作(++i 和 --i)与后缀操作(i++ 和 i--),彼此存在着一些细微差别,各有不同的用途. 这些语言的使 ...

  2. Oracle调用Java方法(下)复杂Jar包封装成Oracle方法以及ORA-29521错误

    上一篇随笔中已经说了简单的Jar是如何封装的,但是我的需求是根据TIPTOP的查询条件产生XML文件并上传到FTP主机中,那么就要涉及到XML生成的方法和FTP上传的方法 所以在Eclipse写的时候 ...

  3. 初识Java Java基础知识

    今天给大家带来的是初级Java基础部分的知识:包括初识Java.变量.常量.数据类型.运算符.各种选择结构.循环结构.数组等Java的基础语法部分!!!内容.步骤超详细,附有各种案例的源代码(可以直接 ...

  4. 基础的markdown用法

    首先推荐一款在线的markdown编辑器:Editor.md 一篇博客里面就是文字与图片的集合.markdown其实就是编辑文字,插入图片的工具.对于大多数人来说,学习几个标签就可以了. 标题 #** ...

  5. 前端笔记(关于webpack打包时内存溢出问题的解决)

    首先安装increase-memory-limit cnpm install -g increase-memory-limit 重启cmd,并在项目跟目录中运行一下 increase-memory-l ...

  6. Redis系列(八):发布与订阅

    Redis的发布与订阅,有点类似于消息队列,发送者往频道发送消息,频道的订阅者接收消息. 1. 发布与订阅示例 首先,在本机开启第1个Redis客户端,执行如下命令订阅blog.redis频道: SU ...

  7. Nacos配置中心原理

    动态配置管理是 Nacos 的三大功能之一,通过动态配置服务,我们可以在所有环境中以集中和动态的方式管理所有应用程序或服务的配置信息. 动态配置中心可以实现配置更新时无需重新部署应用程序和服务即可使相 ...

  8. JasperReport报表中输出Excel时,部分列不显示的问题

    JasperReport开源报表功能强大,是我们WEB系统中做报表开发的一个强有力的工具,上手也比较简单.我碰到的问题是进行报表输出时,在html网页中显示正常,但如果导出为Excel时,部分列不显示 ...

  9. Mybatis架构相关的知识

    如上所示,这是一个简单的Mybaits执行流程. 我们其实可以看到,一直到第三步(Sqlsession)那么一步,这都是我们的程序里需要创建的.而之后的步骤才是底层完成的任务. 这里就有了一个引申的概 ...

  10. zookeeper搭建和kafka搭建

    zookeeper和kafka都是基于java的 zookeeper 1.安装jdk 官网下载rpm文件 rpm -ivh 文件.rpm 2.下载zookeeper tar -xv 压缩文件 -C 目 ...