xenomai内核解析--双核系统调用(三)--如何为xenomai添加一个系统调用
版权声明:本文为本文为博主原创文章,转载请注明出处。如有错误,欢迎指正。
@
一、添加系统调用
下面给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添加一个系统调用的更多相关文章
- 【原创】xenomai内核解析--双核系统调用(二)--应用如何区分xenomai/linux系统调用或服务
		版权声明:本文为本文为博主原创文章,转载请注明出处.如有错误,欢迎指正. 1. 引出问题 上一篇文章xenomai内核解析--双核系统调用(一)以X86处理器为例,分析了xenomai内核调用的流程, ... 
- 【原创】xenomai内核解析--xenomai与普通linux进程之间通讯XDDP(一)--实时端socket创建流程
		版权声明:本文为本文为博主原创文章,转载请注明出处.如有问题,欢迎指正.博客地址:https://www.cnblogs.com/wsg1100/ 1.概述 上篇文章xenomai内核解析--实时IP ... 
- 【xenomai内核解析】系列文章大纲
		xenomai内核解析 本博客为本人学习linux实时操作系统框架xenomai的一些记录,主要剖析xenomai内核实现,以及与linux相关的知识.方便读者定位具体文章,现列出本博客大纲,后续会陆 ... 
- 【原创】xenomai内核解析--xenomai与普通linux进程之间通讯XDDP(三)--实时与非实时数据交互
		版权声明:本文为本文为博主原创文章,转载请注明出处.如有问题,欢迎指正.博客地址:https://www.cnblogs.com/wsg1100/ 目录 1.概述 1.概述 [原创]实时IPC概述 [ ... 
- xenomai内核解析之信号signal(二)---xenomai信号处理机制
		xenomai信号 上篇文章讲了linux的信号在内核的发送与处理流程,现在加入了cobalt核,Cobalt内核为xenomai线程提供了信号机制.下面一一解析xenomai内核的信号处理机制. 1 ... 
- xenomai内核解析---内核对象注册表—xnregistry(重要组件)
		1. 概述 上篇文章xenomai内核解析--同步互斥机制(一)--优先级倒置讲到,对于所有内核对象: xnregistry:保存内核对象,提供内核对象存储和快速检索. xnsynch:资源抽象,提供 ... 
- 【原创】xenomai内核解析--xenomai与普通linux进程之间通讯XDDP(二)--实时与非实时关联(bind流程)
		版权声明:本文为本文为博主原创文章,转载请注明出处.如有问题,欢迎指正.博客地址:https://www.cnblogs.com/wsg1100/ 1.概述 上篇文章介绍了实时端socket创建和配置 ... 
- [保姆级教程] 如何在 Linux Kernel (V5.17.7) 中添加一个系统调用(System call)
		最近在学习 <linux Kernel Development>,本书用的linux kernel 是v2.6 版本的.看完"系统调用"一节后,想尝试添加一个系统调用, ... 
- xenomai内核解析之双核系统调用(一)
		版权声明:本文为本文为博主原创文章,转载请注明出处.如有错误,欢迎指正.博客地址:https://www.cnblogs.com/wsg1100/ 目录 xenomai 内核系统调用 一.32位Lin ... 
随机推荐
- Ubuntu16.06常见服务搭建
			摘要 系统环境Ubuntu 16.04 amd64 隔一段时间要配一次服务记不住,记录在这里方便以后安装. 目前更新了以下服务: ssh samba vimrc // 20200126更新 ssh 安 ... 
- Task.Result跟 Task.GetAwaiter.GetResult()相同吗?怎么选?
			前几天在用线程池执行一些任务时运到一种情形,就是回调方法中使用到了异步方法,但是回调方法貌似不支持async await的写法.这时候我应该如何处理呢?是使用Task.Result来获取返回结果,还是 ... 
- Elasticsearch的query phase和fetch phase
			对于一次query查询到数据返回到客户端,经历了两个过程 query phase和fetch phase的过程 query phase 查询阶段 fetch phase 获取阶段. 1 qu ... 
- linux中神奇的命令alias
			在linux中大家应该都知道,有些命令和参数特别繁琐,而且还是大量输入这些命令,这个时候我们就可以使用linux中的alias命令来给这些繁琐的命令起别名,但是,alias 命令只对当前终端有效,当终 ... 
- Redis系列(六):数据结构List双向链表LPUSH、LPOP、RPUSH、RPOP、LLEN命令
			1.介绍 redis中的list既实现了栈(先进后出)又实现了队列(先进先出) 1.示意图 2.各命令详解 LPUSH/RPUSH LPUSH: 从队列的左边入队一个或多个元素 将所有指定的值插入到存 ... 
- ABP(ASP.NET Boilerplate Project)快速入门
			前言 这两天看了一下ABP,做个简单的学习记录.记录主要有以下内容: 从官网创建并下载项目(.net core 3.x + vue) 项目在本地成功运行 新增实体并映射到数据库 完成对新增实体的基本增 ... 
- Docker入门(1):概述
			1.摘要 在这篇文章中,我将介绍一下为什么需要虚拟化的环境. 然后我将介绍耳熟能详的虚拟化技术:虚拟机,并大致的介绍一下虚拟机的原理,希望能够让你知道虚拟机的优劣. 在之后,针对虚拟机存在的问题,引出 ... 
- [javascript]js原型链以及原型链继承
			基础的三个要素: 函数 ,函数实例,实例原型. 实例原型相当于 父类, 函数相当于构造函数 举例: class Fn extends Fn.prototype{ } 实例: let f = new F ... 
- JS中字符串和数组的相互转化
			题目:利用var s1=prompt("请输入任意的字符串:") ,可以获取用户输入的字符串,试编程将用户输入的字符串“反转”,并且将字符串输出. 思路:字符串对象的方法中并没有实 ... 
- 洛谷 P4017 【最大食物链计数】
			看到这种明显的有向无环图,并且等级分明,自然而然就能想到拓补排序啦.对于这道题,我们就可以利用最短路计数的那种思想(不知道也没关系),设\(j\)是\(i\)的后继,\(dis_i\)表示以\(i\) ... 
