点击查看系列文章 =》 Interrupt Pipeline系列文章大纲-优快云博客
原创不易,需要大家多多鼓励!您的关注、点赞、收藏就是我的创作动力!
5.3.3 Xenomai3: hello world演示应用编译与启动
从shell启动hello world,那么hello world会变成实时进程吗?
最简单的hello world实例。
root@u2204:~/ipipe-arm64/helloworld # cat hello.c
#include <stdio.h>
int main()
{
printf("Hello World!\n");
return 0;
}
使用posix skin来进行编译与链接,makefile内容如下。
root@u2204:~/ipipe-arm64/helloworld# cat makefile
# 指定编译器为针对aarch64架构的GNU编译器集合中的C++编译器
CC = aarch64-linux-gnu-g++
# 定义Xenomai安装目录的位置
XENO_DESTDIR=/root/ipipe-arm64/xenomai_install
# 定义一个变量来保存Xenomai配置工具的路径,该工具可以生成编译和链接标志
XENO_CONFIG =$(XENO_DESTDIR)/usr/xenomai/bin/xeno-config
# 使用Xenomai配置工具获取POSIX皮肤的编译标志,并存储在变量中
XENO_POSIX_CFLAGS =$(shell DESTDIR=$(XENO_DESTDIR) $(XENO_CONFIG) --skin=posix --cflags)
# 使用Xenomai配置工具获取POSIX皮肤的链接标志,并存储在变量中
XENO_POSIX_LDFLAGS =$(shell DESTDIR=$(XENO_DESTDIR) $(XENO_CONFIG) --skin=posix --ldflags)
# 设置项目路径为当前目录(.)
PROJPATH = .
# 定义最终生成的可执行文件名为hello
EXECUTABLE := hello
# 通过通配符找到所有以.c结尾的源代码文件,并将它们的名称赋值给src变量
src = $(wildcard ./*.c)
# 将找到的源文件名转换为目标文件(.o),并将其列表赋值给obj变量
obj = $(patsubst %.c, %.o, $(src))
# 默认目标:构建所有目标中最先出现的一个,这里是$(EXECUTABLE),即构建'hello'可执行文件
all: $(EXECUTABLE)
# 规则用于创建最终的可执行文件。它依赖于所有的目标文件(.o),使用链接标志进行链接
$(EXECUTABLE): $(obj)
$(CC) -g -o $@ $^ $(XENO_POSIX_LDFLAGS)
# 规则用于从每个源文件(.c)创建对应的目标文件(.o)。这里使用编译标志进行编译
%.o:%.c
$(CC) -g -o $@ -c $< $(XENO_POSIX_CFLAGS)
# 清理规则,删除生成的可执行文件和目标文件,用于清理工作目录
.PHONY: clean
clean:
rm -f $(EXECUTABLE) $(obj)
执行make V=1完成交叉编译与链接,生成可执行文件hello。
root@u2204:~/ipipe-arm64/helloworld# make V=1
aarch64-linux-gnu-g++ -g -o hello.o -c hello.c -I/root/ipipe-arm64/xenomai_install/usr/xenomai/include/cobalt -I/root/ipipe-arm64/xenomai_install/usr/xenomai/include -march=armv8-a -D_GNU_SOURCE -D_REENTRANT -fasynchronous-unwind-tables -D__COBALT__ -D__COBALT_WRAP__
aarch64-linux-gnu-g++ -g -o hello hello.o -Wl,--no-as-needed -Wl,@/root/ipipe-arm64/xenomai_install/usr/xenomai/lib/cobalt.wrappers -Wl,@/root/ipipe-arm64/xenomai_install/usr/xenomai/lib/modechk.wrappers /root/ipipe-arm64/xenomai_install/usr/xenomai/lib/xenomai/bootstrap.o -Wl,--wrap=main -Wl,--dynamic-list=/root/ipipe-arm64/xenomai_install/usr/xenomai/lib/dynlist.ld -L/root/ipipe-arm64/xenomai_install/usr/xenomai/lib -lcobalt -lmodechk -lpthread -lrt -march=armv8-a
把可执行文件hello拷贝到QEMU ARM64中,使用gdb中断hello的执行:
(1)通过(gdb) break hello.c:5 在return语句定义一个断点。
(2)执行(gdb) run,走到return。
(3)通过(gdb) info threads打印出当前线程信息,存在2个线程。“hello”线程是符合预期的,线程号是782。怎么多出了一个线程号785的"cobalt_printf"线程呢?
(4)通过(gdb) shell cat /proc/xenomai/sched/stat,执行shell命令,查看xenomai的线程调度情况。发现“hello”进程已经是一个Xenomai进程了,而不是普通的Linux进程。这是怎么做到的呢?
(5)通过(gdb) shell top -n 1 -p 782,785,执行shell命令,查看Linux下线程的信息。发现“hello”进程和"cobalt_printf"线程的优先级PR都是20(即20+NI)。加上一个参数启动hello:./hello --main-prio=<priority>,则可以设定“hello”在Linux中的优先级。
总结一下:通过上面的演示,得到两个问题,接下来探索一下。
“hello”进程已经是一个Xenomai进程了,而不是普通的Linux进程。这是怎么做到的呢?
怎么多出了一个线程号785的"cobalt_printf"线程呢?
在下一章节解密!
点击查看系列文章 =》 Interrupt Pipeline系列文章大纲-优快云博客
原创不易,需要大家多多鼓励!您的关注、点赞、收藏就是我的创作动力!