Xenomai内核探秘
Xenomai源码解析第一章-xenomai_init(一)
前言
一直都在使用xenomai,平常或多或少都会看一些xenomai的技术文档,对xenomai也有一个大致了解。最近为了找工作也看了一些操作系统Linux内核相关的信息,下午本来是在看linuxCNC的,但是实在没明白他是如何动态的使用到xenomai实时内核。然后自己就不小心开始看了一眼xenomai的源码。不看不要紧,一看突然醍醐灌顶,好多之前懵懵懂懂的突然就有点通透了。所以决定从今天起把xenomai源码过一遍,顺便探析其实时的实现机理。希望能够坚持下去。
本文包含从0开始的xenomai个人学习见解,也会顺便将之前看到的相关文档抛出,也作为研究生学习生涯的一个小小总结。
基础略有薄弱,如果各位大佬发现什么问题欢迎指正。
一、xenomai启动前的事情
xenomai 的启动函数为
xenomai_init(void)
源码中使用如下函数加载到内核的启动过程中。
device_initcall(xenomai_init);
如linux的initcall机制(针对编译进内核的驱动)中描述的情形。xenomai模块是再linux内核启动以后进行加载的,加载过程如下:
start_kernel
-> rest_init();
-> kernel_thread(kernel_init, NULL, CLONE_FS);
-> kernel_init()
-> kernel_init_freeable();
-> do_basic_setup();
-> do_initcalls();
->do_initcall_level(0);
````
->do_initcall_level(6);
自此启动xenomai内核;
二、xenomai_init(void)函数
static int __init xenomai_init(void)
{
int ret, __maybe_unused cpu;
setup_init_state();
if (!realtime_core_enabled()) {
printk(XENO_WARNING "disabled on kernel command line\n");
return 0;
}
#ifdef CONFIG_SMP
cpumask_clear(&xnsched_realtime_cpus);
for_each_online_cpu(cpu) {
if (supported_cpus_arg & (1UL << cpu))
cpumask_set_cpu(cpu, &xnsched_realtime_cpus);
}
if (cpumask_empty(&xnsched_realtime_cpus)) {
printk(XENO_WARNING "disabled via empty real-time CPU mask\n");
set_realtime_core_state(COBALT_STATE_DISABLED);
return 0;
}
cobalt_cpu_affinity = xnsched_realtime_cpus;
#endif /* CONFIG_SMP */
xnsched_register_classes();
ret = xnprocfs_init_tree();
if (ret)
goto fail;
ret = mach_setup();
if (ret)
goto cleanup_proc;
xnintr_mount();
ret = xnpipe_mount();
if (ret)
goto cleanup_mach;
ret = xnselect_mount();
if (ret)
goto cleanup_pipe;
ret = sys_init();
if (ret)
goto cleanup_select;
ret = mach_late_setup();
if (ret)
goto cleanup_sys;
ret = rtdm_init();
if (ret)
goto cleanup_sys;
ret = cobalt_init();
if (ret)
goto cleanup_rtdm;
rtdm_fd_init();
printk(XENO_INFO "Cobalt v%s %s%s%s%s\n",
XENO_VERSION_STRING,
boot_debug_notice,
boot_lat_trace_notice,
boot_evt_trace_notice,
boot_state_notice);
return 0;
cleanup_rtdm:
rtdm_cleanup();
cleanup_sys:
sys_shutdown();
cleanup_select:
xnselect_umount();
cleanup_pipe:
xnpipe_umount();
cleanup_mach:
mach_cleanup();
cleanup_proc:
xnprocfs_cleanup_tree();
fail:
set_realtime_core_state(COBALT_STATE_DISABLED);
printk(XENO_ERR "init failed, code %d\n", ret);
return ret;
}
主要包含以下函数
setup_init_state();
set_realtime_core_state();
xnsched_register_classes();
xnprocfs_init_tree();
mach_setup();
xnintr_mount();
xnpipe_mount();
xnselect_mount();
sys_init();
mach_late_setup();
rtdm_init();
cobalt_init();
rtdm_fd_init();
一个一个来
setup_init_state()
源码如下
static void __init setup_init_state(void)
{
static char warn_bad_state[] __initdata =
XENO_WARNING "invalid init state '%s'\n";
int n;
for (n = 0; n < ARRAY_SIZE(init_states); n++)
if (strcmp(init_states[n].label, init_state_arg) == 0) {
set_realtime_core_state(init_states[n].state);
return;
}
printk(warn_bad_state, init_state_arg);
}
这里其他相关参数的说明
static struct {
const char *label;
enum cobalt_run_states state;
} init_states[] __initdata = {
{
"disabled", COBALT_STATE_DISABLED },
{
"stopped", COBALT_STATE_STOPPED },
{
"enabled", COBALT_STATE_WARMUP },
};
enum cobalt_run_states {
COBALT_STATE_DISABLED,
COBALT_STATE_RUNNING,
COBALT_STATE_STOPPED,
COBALT_STATE_TEARDOWN,
COBALT_STATE_WARMUP,
};
xenomai对于其状态描述到枚举值类型的映射
static char init_state_arg[16] = "enabled";
默认情况下使能
比较到对应字符传时设置实时核的状态
static inline void set_realtime_core_state(enum cobalt_run_states state)
{
atomic_set(&cobalt_runstate, state);
}
这里的cobalt_runstate 是一个原子变量,其实就是一个int.
static inline void atomic_set(atomic_t *ptr, long v)
{
ptr->v = v;
}
typedef struct {
int v; } atomic_t;
atomic_t cobalt_runstate = ATOMIC_INIT(COBALT_STATE_WARMUP);
#define ATOMIC_INIT(__n) {
(__n) }