Xenomai源码解析第一章-xenomai_init(一)
作者:互联网
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) }
//这里的COBALT_STATE_WARMUP就是之前定义的xenomai状态的一种
关于启动状态的设置可以再/etc/default/grub设置
GRUB_CMDLINE_LINUX="isolcpus=0,1 xenomai.supported_cpus=0x03"
官网 Installing_Xenomai_3中有提到
NAME
xenomai.state=
DESCRIPTION
Set the initial state of the Cobalt core at boot up, which may be enabled, stopped or disabled. See the documentation about the corectl(1) utility for a description of these states.
DEFAULT
enabled
corectl 可以再用户级对内核状态进项操作,文档如下corectl - Cobalt core control interface
该工具默认安装在/usr/xenomai/sbin
设置xenomai状态之后就会检查一手,如果没设置成功或者别的问题。就退出,如下
if (!realtime_core_enabled()) {
printk(XENO_WARNING "disabled on kernel command line\n");
return 0;
}
插曲 smp
我之前文章有提到虚拟机安装ubuntu +xenomai3.1补丁
现在的计算机基本都是多核,这个选项默认是要开启的.
#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 */
cpumask_clear顾名思义掩码清零,定义如下
/**
* cpumask_clear - clear all cpus (< nr_cpu_ids) in a cpumask
* @dstp: the cpumask pointer
*/
static inline void cpumask_clear(struct cpumask *dstp)
{
bitmap_zero(cpumask_bits(dstp), nr_cpumask_bits);
}
#define cpumask_bits(maskp) ((maskp)->bits)
static inline void bitmap_zero(unsigned long *dst, unsigned int nbits)
{
if (small_const_nbits(nbits))
*dst = 0UL;
else {
unsigned int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
memset(dst, 0, len);
}
}
然后设置xenomai支持的cpu掩码
#define for_each_online_cpu(cpu) for_each_cpu((cpu), cpu_online_mask)
#define for_each_cpu(cpu, mask) \
for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask)
这里不是很懂为什么cpu只遍历了0,然后设置cpu掩码.
这里也可以设置grub参数传入见官网 [Installing_Xenomai_3]。
cobalt_cpu_affinity = xnsched_realtime_cpus;
然后xenomai的cpu亲和性就会绑定在设置的cpu上面.linux就不会使用这两个核了。
这里可能还有问题,之后再补充.
xnsched_register_classes()
void xnsched_register_classes(void)
{
xnsched_register_class(&xnsched_class_idle);
#ifdef CONFIG_XENO_OPT_SCHED_WEAK
xnsched_register_class(&xnsched_class_weak);
#endif
#ifdef CONFIG_XENO_OPT_SCHED_TP
xnsched_register_class(&xnsched_class_tp);
#endif
#ifdef CONFIG_XENO_OPT_SCHED_SPORADIC
xnsched_register_class(&xnsched_class_sporadic);
#endif
#ifdef CONFIG_XENO_OPT_SCHED_QUOTA
xnsched_register_class(&xnsched_class_quota);
#endif
xnsched_register_class(&xnsched_class_rt);
}
dmesg 显示xenomai 只注册了以下两个
[ 1.629946] [Xenomai] scheduling class idle registered.
[ 1.629946] [Xenomai] scheduling class rt registered.
标签:state,ret,init,源码,xnsched,xenomai,cpu 来源: https://blog.csdn.net/pupil_wjj/article/details/119456869