6.2.1 Xenomai3: hello world演示线程创建

点击查看《Xenomai/IPIPE源代码情景解析》
原创不易,需要大家多多鼓励!您的关注、点赞、收藏就是我的创作动力!

6.2.1 Xenomai3: hello world演示线程创建

主函数中使用POSIX线程(pthread)库的pthread_create来创建一个线程,并在线程函数 helloworld 中,使用 clock_nanosleep 实现精确的周期性任务,每隔1s打印一次"Hello World!"。

#include <stdio.h>      // 标准输入输出库,用于打印输出
#include <unistd.h>     // 提供对POSIX操作系统API的访问,如`clock_nanosleep`
#include <pthread.h>    // POSIX线程库,用于创建和管理线程

static pthread_t hellothread; // 用于存储线程的标识符
#define NSEC_PER_SEC 1000000000 // 定义每秒的纳秒数(1秒 = 1,000,000,000纳秒)
static unsigned int cycle = 1000000; // 定义周期时间,单位为us

// 线程函数,每隔一定时间打印 "Hello World!"
static void *helloworld(void *arg)
{
    struct sched_param  param = { .sched_priority = 80 }; // 定义调度参数,设置线程优先级为80
    struct timespec next_period; // 用于存储下一次执行的时间点

    // 设置当前线程的名称为 "helloworld"
    pthread_setname_np(pthread_self(), "helloworld");

    // 设置当前线程的调度策略为 SCHED_FIFO(先进先出调度策略),并设置优先级
    pthread_setschedparam(pthread_self(), SCHED_FIFO, &param);

    // 获取当前的单调时间(系统启动后的时间,不受系统时间调整影响)
    clock_gettime(CLOCK_MONOTONIC, &next_period);

    // 无限循环,线程将一直运行
    while(1) {
        // 将下一次执行时间的纳秒部分增加 cycle * 1000
        next_period.tv_nsec += cycle * 1000;

        // 如果纳秒部分超过了1秒,则将其减去1秒,并将秒部分加1
        while (next_period.tv_nsec >= NSEC_PER_SEC) {
            next_period.tv_nsec -= NSEC_PER_SEC;
            next_period.tv_sec++;
        }
        
        // 使用绝对时间进行睡眠,直到 next_period 指定的时间
        clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next_period, NULL);
        
        // 打印 "Hello World!"
        printf("Hello World!\n");
    }
}

// 主函数
int main()
{
    int ret;
    pthread_attr_t thattr; // 定义线程属性对象

    // 初始化线程属性对象
    pthread_attr_init(&thattr);
    
    // 设置线程属性为可连接状态(即主线程可以等待该线程结束)
    pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE);
    
    // 创建一个新线程,执行 helloworld 函数
    pthread_create(&hellothread, &thattr, &helloworld, NULL);

    // 主线程等待 hellothread 线程结束
    // 注意:在这个例子中,hellothread 线程永远不会结束,因为它在无限循环中
    pthread_join(hellothread, NULL);

    return 0; // 主函数返回0,表示程序正常结束
}

使用posix skin来进行编译与链接,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。

aarch64-linux-gnu-g++ -g -o hello.o -c hello.c -I/usr/xenomai/include/cobalt -I/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,@/usr/xenomai/lib/cobalt.wrappers -Wl,@/usr/xenomai/lib/modechk.wrappers  /usr/xenomai/lib/xenomai/bootstrap.o -Wl,--wrap=main -Wl,--dynamic-list=/usr/xenomai/lib/dynlist.ld -L/usr/xenomai/lib -lcobalt -lmodechk -lpthread -lrt -march=armv8-a

把可执行文件hello拷贝到QEMU ARM64中,使用gdb中断hello的执行:
(1)通过(gdb) break hello.c:60 在pthread_join语句定义一个断点。
(2)执行(gdb) run,在pthread_join中断。
(3)通过(gdb) info threads打印出当前线程信息,存在3个线程:主进程/线程“hello”、线程cobalt_print、线程“helloworld”。其中前两个线程的创建过程,在上一章已经分析过了,不再重复!
在这里插入图片描述
(4)通过(gdb) shell cat /proc/xenomai/sched/stat,执行shell命令,查看xenomai的线程调度情况。发现“helloworld”线程是一个Xenomai线程。
在这里插入图片描述
在代码中,实际使用的是pthread_create来创建线程,是如何转成Xenomai线程的呢?

下一章节解密!

点击查看《Xenomai/IPIPE源代码情景解析》
原创不易,需要大家多多鼓励!您的关注、点赞、收藏就是我的创作动力!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值