【原創】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調度及時間子系統相關文章,敬請關注。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM