版權宣告:本文為本文為博主原創文章,轉載請註明出處。如有錯誤,歡迎指正。
@
一、新增系統呼叫
下面給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排程及時間子系統相關文章,敬請關注。