zoukankan      html  css  js  c++  java
  • 【原创】xenomai内核解析--双核系统调用(三)--如何为xenomai添加一个系统调用

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

    一、添加系统调用

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

    在前两篇文中说到,xenomai每个系统的系统系统调用号在cobaltuapisyscall.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相关,那就放在kernelxenomaiposixclock.h中吧。

    #include <linux/ipipe_tickdev.h>
    
    COBALT_SYSCALL_DECL(get_timer_hits,
    		   (unsigned long __user *u_tick));
    

    然后是该函数的内核实现,放在/kernelxenomaiposixclock.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发起,所以修改应用库来添加该函数接口,添加声明includecobalt ime.h

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

    xenomai3.x.xlibcobaltclock.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
    ",
    			__func__,strerror(-ret));
    		return ret;
    	}	
        fprintf(stdout,"timer_hits:%ld
    ",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
    ",
    			__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调度及时间子系统相关文章,敬请关注。

  • 相关阅读:
    Protocol https not supported or disabled in libcurl
    初学require.js
    HTML中的IE条件注释
    前端,我为什么不要你
    敲点JavaScript代码
    小白科普之JavaScript的函数
    小白科普之JavaScript的BOM模型
    小白科普之JavaScript的JSON
    小白科普之JavaScript的数组
    document.documentElement和document.body的区别
  • 原文地址:https://www.cnblogs.com/wsg1100/p/13338774.html
Copyright © 2011-2022 走看看