处理抢占式多任务的服务。
每个 Alchemy 任务都是整体应用代码的独立部分,体现为一个 C 过程,在其自己的堆栈上下文中执行。
int rt_task_bind (RT_TASK *task, const char *name, RTIME timeout);
绑定到任务。
此例程创建一个新的描述符,以引用由其符号名称标识的现有 Alchemy 任务。如果在进入时对象不存在,调用者可能会阻塞,直到创建具有给定名称的任务。
参数
返回值
成功时返回零。否则:
标签
xthread-nowait
, switch-primary
注释
超时值被解释为 Alchemy 时钟分辨率的倍数(参见 --alchemy-clock-resolution 选项,默认为 1 纳秒)。
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"
RT_TASK demo_task_desc;
void demo_task(void *arg)
{
RT_TASK current_task;
RT_TASK_INFO info;
printf("This is a Demo Task\n");
// 通过TASK_NAME绑定到描述符
if (rt_task_bind(¤t_task, TASK_NAME, TM_INFINITE)) {
printf("Error creating sender task\n");
return;
}
// 使用描述符
int ret = rt_task_inquire(¤t_task,&info);
if(ret == 0){
printf("Get task info:\n");
printf(" name:%s, prio:%d, pid:%d, cpu:%d\n",info.name,info.prio,info.pid,info.stat.cpu);
}else{
printf("Error while inquire task: %d\n", ret);
}
// 解除绑定
rt_task_unbind(¤t_task);
}
int main(int argc, char *argv[])
{
// 创建任务
if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating sender task\n");
return 1;
}
// 启动任务
rt_task_start(&demo_task_desc, &demo_task, NULL);
// 等待任务结束
rt_task_join(&demo_task_desc);
// 清理
rt_task_delete(&demo_task_desc);
return 0;
}
int rt_task_create (RT_TASK *task, const char *name, int stksize, int prio, int mode);
创建具有 Alchemy 特性的任务。
此服务创建一个可以访问完整 Alchemy 服务集的任务。如果 prio 非零,新任务属于 Xenomai 的实时 FIFO 调度类,即 SCHED_FIFO。如果 prio 为零,任务属于常规的 SCHED_OTHER 类。
创建优先级为零的任务对于运行可能调用阻塞实时服务的非实时进程非常有用,例如等待信号量、从消息队列或缓冲区读取等。
一旦创建,任务将保持休眠状态,直到通过 rt_task_start() 实际启动。
参数
返回值
成功时返回零。否则:
标签
xthread-only
, mode-unrestricted
, switch-secondary
副作用
注意
多个属于同一 Xenomai 会话的进程可以引用任务。
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"
RT_TASK demo_task_desc;
void demo_task(void *arg)
{
printf("This is a Demo Task\n");
}
int main(int argc, char *argv[])
{
// 创建任务
if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating sender task\n");
return 1;
}
// 启动任务
rt_task_start(&demo_task_desc, &demo_task, NULL);
// 等待任务结束
rt_task_join(&demo_task_desc);
// 清理
rt_task_delete(&demo_task_desc);
return 0;
}
int rt_task_delete (RT_TASK *task);
删除实时任务。
此调用终止先前由 rt_task_create() 创建的任务。
使用 T_JOINABLE 标志创建的任务在成功删除后应通过后续调用 rt_task_join() 来回收所有资源。
参数
返回值
成功时返回零。否则:
标签
mode-unrestricted
, switch-secondary
注意
如果 task 为 NULL,则调用者必须是 Alchemy 任务。
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"
RT_TASK demo_task_desc;
void demo_task(void *arg)
{
printf("This is a Demo Task\n");
}
int main(int argc, char *argv[])
{
// 创建任务
if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating sender task\n");
return 1;
}
// 启动任务
rt_task_start(&demo_task_desc, &demo_task, NULL);
// 等待任务结束
rt_task_join(&demo_task_desc);
// 清理
rt_task_delete(&demo_task_desc);
return 0;
}
int rt_task_inquire (RT_TASK *task, RT_TASK_INFO *info);
检索实时任务的信息。
返回有关 Alchemy 任务的各种信息。此服务也可用于探测任务是否存在。
参数
返回值
如果任务存在,则返回零。此外,如果 info 非 NULL,则填充任务信息。否则:
标签
mode-unrestricted
, switch-primary
注意
如果 task 为 NULL,则调用者必须是 Alchemy 任务。
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"
RT_TASK demo_task_desc;
void demo_task(void *arg)
{
int ret;
RT_TASK_INFO info;
printf("This is a Demo Task\n");
ret = rt_task_inquire(&demo_task_desc,&info);
if(ret == 0){
printf("Get task info:\n");
printf(" name:%s, prio:%d, pid:%d, cpu:%d\n",info.name,info.prio,info.pid,info.stat.cpu);
}else{
printf("Error while inquire task: %d\n", ret);
}
}
int main(int argc, char *argv[])
{
// 创建任务
if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating sender task\n");
return 1;
}
// 启动任务
rt_task_start(&demo_task_desc, &demo_task, NULL);
// 等待任务结束
rt_task_join(&demo_task_desc);
// 清理
rt_task_delete(&demo_task_desc);
return 0;
}
int rt_task_join (RT_TASK *task);
等待实时任务的终止。
此服务在非实时上下文中阻塞调用者,直到任务终止。成功完成此服务后,所有资源将被释放。
指定的任务必须由希望加入它的同一进程创建,并且在调用 rt_task_create() 时必须设置 T_JOINABLE 模式标志。
使用 T_JOINABLE 标志创建的任务在成功删除后应通过后续调用 rt_task_join() 来回收所有资源。
参数
返回值
成功时返回零。否则:
标签
mode-unrestricted
, switch-primary
注意
成功完成此服务后,不需要也不应再对同一任务调用 rt_task_delete()。
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"
RT_TASK demo_task_desc;
void demo_task(void *arg)
{
printf("This is a Demo Task\n");
}
int main(int argc, char *argv[])
{
// 创建任务
if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating sender task\n");
return 1;
}
// 启动任务
rt_task_start(&demo_task_desc, &demo_task, NULL);
// 等待任务结束
rt_task_join(&demo_task_desc);
// 清理
rt_task_delete(&demo_task_desc);
return 0;
}
ssize_t rt_task_receive (RT_TASK_MCB *mcb_r, RTIME timeout);
从实时任务接收消息(具有相对标量超时)。
此例程是 rt_task_receive_timed() 的变体,接受以标量值表示的相对超时规范。
参数
标签
xthread-only
, switch-primary
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define RECEIVER_TASK_NAME "receiver_task"
#define SENDER_TASK_NAME "sender_task"
RT_TASK receiver_task_desc, sender_task_desc;
int cycle_time = 3;
void receiver_task(void *arg)
{
RT_TASK_MCB mcb_r;
char buffer[100];
int ret;
mcb_r.data = buffer;
mcb_r.size = sizeof(buffer);
while (cycle_time) {
printf("Receiver: Waiting for a message...\n");
ret = rt_task_receive(&mcb_r, TM_INFINITE);
if (ret > 0) {
printf("Receiver: Received message: %s\n", (char *)mcb_r.data);
rt_task_reply(ret, NULL); // 发送空回复
} else {
printf("Receiver: Error receiving message, code: %d\n", ret);
}
}
}
void sender_task(void *arg)
{
RT_TASK_MCB mcb_s;
char message[] = "Hello from sender!";
int ret;
while (cycle_time--) {
rt_task_sleep(1000000000); // 睡眠1秒
mcb_s.data = message;
mcb_s.size = sizeof(message);
printf("Sender: Sending message...\n");
ret = rt_task_send(&receiver_task_desc, &mcb_s, NULL, TM_INFINITE);
if (ret >= 0) {
printf("Sender: Message sent successfully\n");
} else {
printf("Sender: Error sending message, code: %d\n", ret);
}
}
}
int main(int argc, char *argv[])
{
// 创建接受任务
if (rt_task_create(&receiver_task_desc, RECEIVER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating receiver task\n");
return 1;
}
// 创建发送任务
if (rt_task_create(&sender_task_desc, SENDER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating sender task\n");
return 1;
}
// 启动任务
rt_task_start(&receiver_task_desc, &receiver_task, NULL);
rt_task_start(&sender_task_desc, &sender_task, NULL);
// 等待任务结束
rt_task_join(&receiver_task_desc);
rt_task_join(&sender_task_desc);
// 清理
rt_task_delete(&receiver_task_desc);
rt_task_delete(&sender_task_desc);
return 0;
}
int rt_task_receive_timed (RT_TASK_MCB *mcb_r, const struct timespec *abs_timeout);
从实时任务接收消息。
此服务是 Alchemy 任务可用的同步消息传递支持的一部分。调用者从另一个任务接收可变大小的消息。发送方被阻塞,直到调用者调用 rt_task_reply() 完成事务。
基本消息控制块用于存储从客户端接收数据区域的位置和大小,以及用户定义的操作码。
参数
mcb_r: 指向消息控制块的地址,该块引用接收消息区域。此控制块的字段应设置如下:
abs_timeout: 基于 Alchemy 时钟,以秒/纳秒表示的绝对时间,指定等待接收消息的时间限制。传递 NULL 会导致调用者无限期阻塞,直到远程任务最终发送消息。传递 {.tv_sec = 0, .tv_nsec = 0} 会导致服务立即返回而不等待,如果当前没有远程任务等待发送消息。
返回值
成功时返回一个严格正值,表示打开事务的流标识符;此令牌应传递给 rt_task_reply(),以便发送回复并适当地解除远程任务的阻塞。否则:
标签
xthread-only
, switch-primary
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define RECEIVER_TASK_NAME "receiver_task"
#define SENDER_TASK_NAME "sender_task"
RT_TASK receiver_task_desc, sender_task_desc;
int cycle_time = 3;
void receiver_task(void *arg)
{
RT_TASK_MCB mcb_r;
char buffer[100];
int ret;
struct timespec ts;
mcb_r.data = buffer;
mcb_r.size = sizeof(buffer);
while (cycle_time) {
printf("Receiver: Waiting for a message...\n");
clock_gettime(CLOCK_MONOTONIC, &ts);
ts.tv_sec += 2; // 超时时间 2 秒
ret = rt_task_receive_timed(&mcb_r, &ts);
if (ret > 0) {
printf("Receiver: Received message: %s\n", (char *)mcb_r.data);
rt_task_reply(ret, NULL); // 发送空回复
} else if(ret == -ETIMEDOUT) {
printf("Receiver: Timeout while waiting for message.\n");
} else {
printf("Receiver: Error receiving message, code: %d\n", ret);
}
}
}
void sender_task(void *arg)
{
RT_TASK_MCB mcb_s;
char message[] = "Hello from sender!";
int ret;
struct timespec ts;
while (cycle_time--) {
if(cycle_time == 2)
{
rt_task_sleep(2000000000); // 睡眠2秒,触发接受超时
}
rt_task_sleep(1000000000); // 睡眠1秒
mcb_s.data = message;
mcb_s.size = sizeof(message);
printf("Sender: Sending message...\n");
clock_gettime(CLOCK_MONOTONIC, &ts);
ts.tv_sec += 2; // 超时时间 2 秒
ret = rt_task_send_timed(&receiver_task_desc, &mcb_s, NULL, &ts);
if (ret >= 0) {
printf("Sender: Message sent successfully\n");
} else if(ret == -ETIMEDOUT) {
printf("Sender: Timeout while waiting for Reply.\n");
} else {
printf("Sender: Error sending message, code: %d\n", ret);
}
}
}
int main(int argc, char *argv[])
{
// 创建接受任务
if (rt_task_create(&receiver_task_desc, RECEIVER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating receiver task\n");
return 1;
}
// 创建发送任务
if (rt_task_create(&sender_task_desc, SENDER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating sender task\n");
return 1;
}
// 启动任务
rt_task_start(&receiver_task_desc, &receiver_task, NULL);
rt_task_start(&sender_task_desc, &sender_task, NULL);
// 等待任务结束
rt_task_join(&receiver_task_desc);
rt_task_join(&sender_task_desc);
// 清理
rt_task_delete(&receiver_task_desc);
rt_task_delete(&sender_task_desc);
return 0;
}
ssize_t rt_task_receive_until (RT_TASK_MCB *mcb_r, RTIME abs_timeout);
从实时任务接收消息(具有绝对标量超时)。
此例程是 rt_task_receive_timed() 的变体,接受以标量值表示的绝对超时规范。
参数
标签
xthread-only
, switch-primary
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define RECEIVER_TASK_NAME "receiver_task"
#define SENDER_TASK_NAME "sender_task"
RT_TASK receiver_task_desc, sender_task_desc;
int cycle_time = 3;
void receiver_task(void *arg)
{
RT_TASK_MCB mcb_r;
char buffer[100];
int ret;
RTIME timeout;
mcb_r.data = buffer;
mcb_r.size = sizeof(buffer);
while (cycle_time) {
printf("Receiver: Waiting for a message...\n");
timeout = rt_timer_read() + 2000000000; // 超时时间 2 秒
ret = rt_task_receive_until(&mcb_r, timeout);
if (ret > 0) {
printf("Receiver: Received message: %s\n", (char *)mcb_r.data);
rt_task_reply(ret, NULL); // 发送空回复
} else if(ret == -ETIMEDOUT) {
printf("Receiver: Timeout while waiting for message.\n");
} else {
printf("Receiver: Error receiving message, code: %d\n", ret);
}
}
}
void sender_task(void *arg)
{
RT_TASK_MCB mcb_s;
char message[] = "Hello from sender!";
int ret;
RTIME timeout;
while (cycle_time--) {
if(cycle_time == 2)
{
rt_task_sleep(2000000000); // 睡眠2秒,触发接受超时
}
rt_task_sleep(1000000000); // 睡眠1秒
mcb_s.data = message;
mcb_s.size = sizeof(message);
printf("Sender: Sending message...\n");
timeout = rt_timer_read() + 2000000000; // 超时时间 2 秒
ret = rt_task_send_until(&receiver_task_desc, &mcb_s, NULL, timeout);
if (ret >= 0) {
printf("Sender: Message sent successfully\n");
} else if(ret == -ETIMEDOUT) {
printf("Sender: Timeout while waiting for Reply.\n");
} else {
printf("Sender: Error sending message, code: %d\n", ret);
}
}
}
int main(int argc, char *argv[])
{
// 创建接受任务
if (rt_task_create(&receiver_task_desc, RECEIVER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating receiver task\n");
return 1;
}
// 创建发送任务
if (rt_task_create(&sender_task_desc, SENDER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating sender task\n");
return 1;
}
// 启动任务
rt_task_start(&receiver_task_desc, &receiver_task, NULL);
rt_task_start(&sender_task_desc, &sender_task, NULL);
// 等待任务结束
rt_task_join(&receiver_task_desc);
rt_task_join(&sender_task_desc);
// 清理
rt_task_delete(&receiver_task_desc);
rt_task_delete(&sender_task_desc);
return 0;
}
int rt_task_reply (int flowid, RT_TASK_MCB *mcb_s);
回复远程任务消息。
此服务是 Alchemy 任务可用的同步消息传递支持的一部分。调用者将可变大小的消息发送回远程任务,以响应通过调用 rt_task_receive() 接收到的初始消息。调用 rt_task_reply() 的结果是,远程任务将从 rt_task_send() 服务中解除阻塞。
基本消息控制块用于存储要发送回的数据区域的位置和大小,以及用户定义的状态码。
参数
返回值
成功时返回零。否则:
标签
xthread-only
, switch-primary
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define RECEIVER_TASK_NAME "receiver_task"
#define SENDER_TASK_NAME "sender_task"
RT_TASK receiver_task_desc, sender_task_desc;
int cycle_time = 3;
void receiver_task(void *arg)
{
RT_TASK_MCB mcb_r;
char buffer[100];
int ret;
mcb_r.data = buffer;
mcb_r.size = sizeof(buffer);
while (cycle_time) {
printf("Receiver: Waiting for a message...\n");
ret = rt_task_receive(&mcb_r, TM_INFINITE);
if (ret > 0) {
printf("Receiver: Received message: %s\n", (char *)mcb_r.data);
rt_task_reply(ret, NULL); // 发送空回复
} else {
printf("Receiver: Error receiving message, code: %d\n", ret);
}
}
}
void sender_task(void *arg)
{
RT_TASK_MCB mcb_s;
char message[] = "Hello from sender!";
int ret;
while (cycle_time--) {
rt_task_sleep(1000000000); // 睡眠1秒
mcb_s.data = message;
mcb_s.size = sizeof(message);
printf("Sender: Sending message...\n");
ret = rt_task_send(&receiver_task_desc, &mcb_s, NULL, TM_INFINITE);
if (ret >= 0) {
printf("Sender: Message sent successfully\n");
} else {
printf("Sender: Error sending message, code: %d\n", ret);
}
}
}
int main(int argc, char *argv[])
{
// 创建接受任务
if (rt_task_create(&receiver_task_desc, RECEIVER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating receiver task\n");
return 1;
}
// 创建发送任务
if (rt_task_create(&sender_task_desc, SENDER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating sender task\n");
return 1;
}
// 启动任务
rt_task_start(&receiver_task_desc, &receiver_task, NULL);
rt_task_start(&sender_task_desc, &sender_task, NULL);
// 等待任务结束
rt_task_join(&receiver_task_desc);
rt_task_join(&sender_task_desc);
// 清理
rt_task_delete(&receiver_task_desc);
rt_task_delete(&sender_task_desc);
return 0;
}
int rt_task_resume (RT_TASK *task);
恢复实时任务。
强制恢复先前通过调用 rt_task_suspend() 挂起的任务的执行,如果挂起嵌套计数递减到零。
参数
返回值
成功时返回零。否则:
标签
unrestricted
, switch-primary
注意
阻塞和挂起的任务状态是累积的。因此,恢复当前正在等待同步对象(例如信号量、队列)的任务不会使其有资格进行调度,直到最终获取到等待的资源或超时。
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"
RT_TASK demo_task_desc;
void demo_task(void *arg)
{
printf("This is a Demo Task\n");
rt_task_suspend(&demo_task_desc);
printf("Demo Task Continue to run\n");
}
int main(int argc, char *argv[])
{
// 创建任务
if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating sender task\n");
return 1;
}
// 启动任务
rt_task_start(&demo_task_desc, &demo_task, NULL);
// 等待任务运行
rt_task_sleep(1000000000); // 1 秒
rt_task_resume(&demo_task_desc);
// 等待任务结束
rt_task_join(&demo_task_desc);
// 清理
rt_task_delete(&demo_task_desc);
return 0;
}
int rt_task_same (RT_TASK *task1, RT_TASK *task2);
比较实时任务描述符。
如果 task1 和 task2 引用相同的任务,则此谓词返回 true。
参数
返回值
如果两个描述符引用相同的任务,则返回非零值,否则返回零。
标签
unrestricted
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME_1 "Demo1"
#define TASK_NAME_2 "Demo2"
RT_TASK demo_task_desc_1, demo_task_desc_2;
void demo_task(void *arg)
{
printf("This is a Demo Task\n");
rt_task_sleep(1000000000);
}
int main(int argc, char *argv[])
{
// 创建任务
if (rt_task_create(&demo_task_desc_1, TASK_NAME_1, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating sender task\n");
return 1;
}
if (rt_task_create(&demo_task_desc_2, TASK_NAME_2, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating sender task\n");
return 1;
}
// 启动任务
rt_task_start(&demo_task_desc_1, &demo_task, NULL);
rt_task_start(&demo_task_desc_2, &demo_task, NULL);
if(rt_task_same(&demo_task_desc_1,&demo_task_desc_2))
{
printf("Both tasks are the same\n");
}else{
printf("The two tasks are different\n");
}
RT_TASK same_of_desc_1;
if (rt_task_bind(&same_of_desc_1,TASK_NAME_1,TM_INFINITE)) {
printf("Error bind to TASK_NAME_1\n");
return 1;
}
if(rt_task_same(&demo_task_desc_1,&same_of_desc_1))
{
printf("Both tasks are the same\n");
}else{
printf("The two tasks are different\n");
}
// 等待任务结束
rt_task_join(&demo_task_desc_1);
rt_task_join(&demo_task_desc_2);
// 清理
rt_task_delete(&demo_task_desc_1);
rt_task_delete(&demo_task_desc_2);
return 0;
}
RT_TASK* rt_task_self (void);
检索当前任务描述符。
返回当前 Alchemy 任务描述符的地址。
返回值
成功时返回引用当前 Alchemy 任务的任务描述符地址,如果不是从有效的 Alchemy 任务上下文调用,则返回 NULL。
标签
xthread-only
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"
RT_TASK demo_task_desc;
void demo_task(void *arg)
{
int ret;
RT_TASK_INFO info;
RT_TASK* current_task;
printf("This is a Demo Task\n");
current_task = rt_task_self();
ret = rt_task_inquire(current_task,&info);
if(ret == 0){
printf("Get task info:\n");
printf(" name:%s, prio:%d, pid:%d, cpu:%d\n",info.name,info.prio,info.pid,info.stat.cpu);
}else{
printf("Error while inquire task: %d\n", ret);
}
}
int main(int argc, char *argv[])
{
// 创建任务
if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating sender task\n");
return 1;
}
// 启动任务
rt_task_start(&demo_task_desc, &demo_task, NULL);
// 等待任务结束
rt_task_join(&demo_task_desc);
// 清理
rt_task_delete(&demo_task_desc);
return 0;
}
ssize_t rt_task_send (RT_TASK *task, RT_TASK_MCB *mcb_s, RT_TASK_MCB *mcb_r, RTIME timeout);
向实时任务发送消息(具有相对标量超时)。
此例程是 rt_task_send_timed() 的变体,接受以标量值表示的相对超时规范。
参数
标签
xthread-only
, switch-primary
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define RECEIVER_TASK_NAME "receiver_task"
#define SENDER_TASK_NAME "sender_task"
RT_TASK receiver_task_desc, sender_task_desc;
int cycle_time = 3;
void receiver_task(void *arg)
{
RT_TASK_MCB mcb_r;
char buffer[100];
int ret;
mcb_r.data = buffer;
mcb_r.size = sizeof(buffer);
while (cycle_time) {
printf("Receiver: Waiting for a message...\n");
ret = rt_task_receive(&mcb_r, TM_INFINITE);
if (ret > 0) {
printf("Receiver: Received message: %s\n", (char *)mcb_r.data);
rt_task_reply(ret, NULL); // 发送空回复
} else {
printf("Receiver: Error receiving message, code: %d\n", ret);
}
}
}
void sender_task(void *arg)
{
RT_TASK_MCB mcb_s;
char message[] = "Hello from sender!";
int ret;
while (cycle_time--) {
rt_task_sleep(1000000000); // 睡眠1秒
mcb_s.data = message;
mcb_s.size = sizeof(message);
printf("Sender: Sending message...\n");
ret = rt_task_send(&receiver_task_desc, &mcb_s, NULL, TM_INFINITE);
if (ret >= 0) {
printf("Sender: Message sent successfully\n");
} else {
printf("Sender: Error sending message, code: %d\n", ret);
}
}
}
int main(int argc, char *argv[])
{
// 创建接受任务
if (rt_task_create(&receiver_task_desc, RECEIVER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating receiver task\n");
return 1;
}
// 创建发送任务
if (rt_task_create(&sender_task_desc, SENDER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating sender task\n");
return 1;
}
// 启动任务
rt_task_start(&receiver_task_desc, &receiver_task, NULL);
rt_task_start(&sender_task_desc, &sender_task, NULL);
// 等待任务结束
rt_task_join(&receiver_task_desc);
rt_task_join(&sender_task_desc);
// 清理
rt_task_delete(&receiver_task_desc);
rt_task_delete(&sender_task_desc);
return 0;
}
ssize_t rt_task_send_timed (RT_TASK *task, RT_TASK_MCB *mcb_s, RT_TASK_MCB *mcb_r, const struct timespec *abs_timeout);
向实时任务发送消息。
此服务是 Alchemy 任务可用的同步消息传递支持的一部分。调用者将可变大小的消息发送到另一个任务,等待远程任务通过调用 rt_task_receive() 接收初始消息,然后使用 rt_task_reply() 回复。
基本消息控制块用于存储要发送或在回复时检索的数据区域的位置和大小,以及用户定义的操作码。
参数
task
任务描述符。
mcb_s
指向消息控制块的地址,该块引用要发送的消息。此控制块的字段应设置如下:
mcb_s->data
应包含要发送到远程任务的有效负载数据的地址。
mcb_s->size
应包含 mcb_s->data
指向的有效负载数据的字节大小。零是合法值,表示不会传输任何有效负载数据。
mcb_s->opcode
是在消息传输过程中携带的不透明操作码,调用者可以填充任何适当的值。它将通过 rt_task_receive() 服务按原样提供给远程任务的操作码字段。
mcb_r
指向可选消息控制块的地址,该块引用回复消息区域。如果 mcb_r
为 NULL 且远程任务发送了回复,回复消息将被丢弃,并返回 -ENOBUFS
给调用者。当 mcb_r
有效时,此控制块的字段应设置如下:
mcb_r->data
应包含足够大的缓冲区地址,以收集来自远程任务的回复数据。
mcb_r->size
应包含 mcb_r->data
指向的缓冲区空间的字节大小。如果 mcb_r->size
小于实际回复消息的大小,则不会进行数据复制,并返回 -ENOBUFS
给调用者。
返回时,mcb_r->opcode
将包含远程任务使用 rt_task_reply() 发送回的状态码,或零(如果未指定)。
abs_timeout
以秒/纳秒表示的绝对时间,基于 Alchemy 时钟,指定等待接收任务回复初始消息的时间限制。传递 NULL 会导致调用者无限期阻塞,直到收到回复。传递 {.tv_sec = 0, .tv_nsec = 0} 会导致服务在接收任务在调用时不等待消息的情况下立即返回而不阻塞。
返回值
成功时返回正值,表示远程任务返回的回复消息的长度(以字节为单位)。零表示成功状态,意味着 mcb_r
在输入时为 NULL,或者没有实际消息传递给远程调用 rt_task_reply()。否则:
如果 task
不是有效的任务描述符,则返回 EINVAL。
如果从无效上下文调用此服务,则返回 EPERM。
如果 mcb_r
未指向足够大的消息区域以收集远程任务的回复,则返回 ENOBUFS。这包括 mcb_r
在输入时为 NULL,且远程任务试图发送回复消息的情况。
如果 abs_timeout
为 {.tv_sec = 0, .tv_nsec = 0} 且接收任务当前未等待 rt_task_receive() 服务上的消息,则返回 EWOUDBLOCK。
如果 task
在等待回复时被删除,则返回 EIDRM。
如果在收到接收任务的任何回复之前调用了 rt_task_unblock(),则返回 EINTR。
标签
xthread-only
, switch-primary
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define RECEIVER_TASK_NAME "receiver_task"
#define SENDER_TASK_NAME "sender_task"
RT_TASK receiver_task_desc, sender_task_desc;
int cycle_time = 3;
void receiver_task(void *arg)
{
RT_TASK_MCB mcb_r;
char buffer[100];
int ret;
struct timespec ts;
mcb_r.data = buffer;
mcb_r.size = sizeof(buffer);
while (cycle_time) {
printf("Receiver: Waiting for a message...\n");
clock_gettime(CLOCK_MONOTONIC, &ts);
ts.tv_sec += 2; // 超时时间 2 秒
ret = rt_task_receive_timed(&mcb_r, &ts);
if (ret > 0) {
printf("Receiver: Received message: %s\n", (char *)mcb_r.data);
if(cycle_time == 2)
{
rt_task_sleep(2000000000); // 睡眠2秒,触发接受超时
}else{
rt_task_reply(ret, NULL); // 发送空回复
}
} else if(ret == -ETIMEDOUT) {
printf("Receiver: Timeout while waiting for message.\n");
} else {
printf("Receiver: Error receiving message, code: %d\n", ret);
}
}
}
void sender_task(void *arg)
{
RT_TASK_MCB mcb_s;
char message[] = "Hello from sender!";
int ret;
struct timespec ts;
while (cycle_time--) {
rt_task_sleep(1000000000); // 睡眠1秒
mcb_s.data = message;
mcb_s.size = sizeof(message);
printf("Sender: Sending message...\n");
clock_gettime(CLOCK_MONOTONIC, &ts);
ts.tv_sec += 2; // 超时时间 2 秒
ret = rt_task_send_timed(&receiver_task_desc, &mcb_s, NULL, &ts);
if (ret >= 0) {
printf("Sender: Message sent successfully\n");
} else if(ret == -ETIMEDOUT) {
printf("Sender: Timeout while waiting for Reply.\n");
} else {
printf("Sender: Error sending message, code: %d\n", ret);
}
}
}
int main(int argc, char *argv[])
{
// 创建接受任务
if (rt_task_create(&receiver_task_desc, RECEIVER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating receiver task\n");
return 1;
}
// 创建发送任务
if (rt_task_create(&sender_task_desc, SENDER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating sender task\n");
return 1;
}
// 启动任务
rt_task_start(&receiver_task_desc, &receiver_task, NULL);
rt_task_start(&sender_task_desc, &sender_task, NULL);
// 等待任务结束
rt_task_join(&receiver_task_desc);
rt_task_join(&sender_task_desc);
// 清理
rt_task_delete(&receiver_task_desc);
rt_task_delete(&sender_task_desc);
return 0;
}
ssize_t rt_task_send_until (RT_TASK *task, RT_TASK_MCB *mcb_s, RT_TASK_MCB *mcb_r, RTIME abs_timeout);
向实时任务发送消息(具有绝对标量超时)。
此例程是 rt_task_send_timed() 的变体,接受以标量值表示的绝对超时规范。
参数
task
任务描述符。
mcb_s
指向消息控制块的地址,该块引用要发送的消息。
mcb_r
指向可选消息控制块的地址,该块引用回复消息区域。
abs_timeout
以时钟滴答表示的绝对时间。传递 TM_INFINITE 会导致调用者无限期阻塞,直到收到回复。传递 TM_NONBLOCK 会导致服务在接收任务在调用时不等待消息的情况下立即返回而不阻塞。
标签
xthread-only
, switch-primary
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define RECEIVER_TASK_NAME "receiver_task"
#define SENDER_TASK_NAME "sender_task"
RT_TASK receiver_task_desc, sender_task_desc;
int cycle_time = 3;
void receiver_task(void *arg)
{
RT_TASK_MCB mcb_r;
char buffer[100];
int ret;
RTIME timeout;
mcb_r.data = buffer;
mcb_r.size = sizeof(buffer);
while (cycle_time) {
printf("Receiver: Waiting for a message...\n");
timeout = rt_timer_read() + 2000000000; // 超时时间 2 秒
ret = rt_task_receive_until(&mcb_r, timeout);
if (ret > 0) {
printf("Receiver: Received message: %s\n", (char *)mcb_r.data);
if(cycle_time == 2)
{
rt_task_sleep(2000000000); // 睡眠2秒,触发接受超时
}else{
rt_task_reply(ret, NULL); // 发送空回复
}
} else if(ret == -ETIMEDOUT) {
printf("Receiver: Timeout while waiting for message.\n");
} else {
printf("Receiver: Error receiving message, code: %d\n", ret);
}
}
}
void sender_task(void *arg)
{
RT_TASK_MCB mcb_s;
char message[] = "Hello from sender!";
int ret;
RTIME timeout;
while (cycle_time--) {
rt_task_sleep(1000000000); // 睡眠1秒
mcb_s.data = message;
mcb_s.size = sizeof(message);
printf("Sender: Sending message...\n");
timeout = rt_timer_read() + 2000000000; // 超时时间 2 秒
ret = rt_task_send_until(&receiver_task_desc, &mcb_s, NULL, timeout);
if (ret >= 0) {
printf("Sender: Message sent successfully\n");
} else if(ret == -ETIMEDOUT) {
printf("Sender: Timeout while waiting for Reply.\n");
} else {
printf("Sender: Error sending message, code: %d\n", ret);
}
}
}
int main(int argc, char *argv[])
{
// 创建接受任务
if (rt_task_create(&receiver_task_desc, RECEIVER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating receiver task\n");
return 1;
}
// 创建发送任务
if (rt_task_create(&sender_task_desc, SENDER_TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating sender task\n");
return 1;
}
// 启动任务
rt_task_start(&receiver_task_desc, &receiver_task, NULL);
rt_task_start(&sender_task_desc, &sender_task, NULL);
// 等待任务结束
rt_task_join(&receiver_task_desc);
rt_task_join(&sender_task_desc);
// 清理
rt_task_delete(&receiver_task_desc);
rt_task_delete(&sender_task_desc);
return 0;
}
int rt_task_set_affinity (RT_TASK *task, const cpu_set_t *cpus);
设置实时任务的 CPU 亲和性。
此调用使 task
亲和于由 cpus
定义的 CPU 集。
参数
task
任务描述符。如果 task 为 NULL,则更改当前任务的 CPU 亲和性。
cpus
task
应该亲和的 CPU 集。
返回值
成功时返回零。否则:
task
为 NULL 但调用者不是 Xenomai 任务,或者 task
非 NULL 但不是有效的任务描述符,则返回 -EINVAL
。cpus
不包含当前系统上物理存在且根据 cpuset(7)
中描述的 cpuset
机制允许进程使用的处理器,则返回 -EINVAL
。标签
mode-unrestricted
, switch-secondary
注意
如果 task
为 NULL,则调用者必须是 Alchemy 任务。
示例代码
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#include <sched.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"
RT_TASK demo_task_desc;
void demo_task(void *arg)
{
int ret;
RT_TASK_INFO info;
cpu_set_t cpu;
rt_task_set_mode(0,TASK_MODE,NULL);
printf("This is a Demo Task\n");
ret = rt_task_inquire(&demo_task_desc,&info);
if(ret != 0){
printf("Error while inquire task: %d\n", ret);
return;
}
printf("Get task info:\n");
printf(" name:%s, prio:%d, pid:%d, cpu:%d\n",info.name,info.prio,info.pid,info.stat.cpu);
CPU_ZERO(&cpu);
CPU_SET(1, &cpu); // 设置到cpu1
rt_task_set_affinity(&demo_task_desc,&cpu);
rt_task_set_priority(&demo_task_desc,TASK_PRIO+10);
ret = rt_task_inquire(&demo_task_desc,&info);
if(ret != 0){
printf("Error while inquire task: %d\n", ret);
return;
}
printf("Get New task info:\n");
printf(" name:%s, prio:%d, pid:%d, cpu:%d\n",info.name,info.prio,info.pid,info.stat.cpu);
}
int main(int argc, char *argv[])
{
// 创建任务
if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, 0)) {
printf("Error creating sender task\n");
return 1;
}
// 启动任务
rt_task_start(&demo_task_desc, &demo_task, 0);
rt_task_sleep(1000000000); // 等待 1 秒
// 等待任务结束
rt_task_join(&demo_task_desc);
// 清理
rt_task_delete(&demo_task_desc);
return 0;
}
int rt_task_set_mode(int clrmask, int setmask, int *mode_r);
更改当前任务模式。
每个 Alchemy 任务都有一组内部标志,用于确定若干操作条件。rt_task_set_mode()
接受一个位掩码,用于清除当前任务的相应模式位以禁用这些模式,并接受另一个位掩码,用于设置相应模式位以启用这些模式。可以根据需要返回更改前生效的模式位。
模式位
setmask
中传递,以将当前 Alchemy 任务切换到其首选的运行时模式。此开关的唯一有意义的用途是将实时任务强制切换回主模式。参数
setmask
之前。零是一个可接受的值,这将导致无操作。mode_r
必须是一个指向内存位置的指针,成功时将写入先前的活动模式位集。如果为 NULL,则不会返回先前的活动模式位集。返回值
task
不是有效的任务描述符,或者 clrmask
或 setmask
中的任何位无效,则返回 -EINVAL
。-EPERM
。标签
xthread-only
switch-primary
注意
T_CONFORMING
位强制任务模式几乎总是错误的,因为 Xenomai/cobalt 内核在需要时会内部处理模式切换。示例代码
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#include <sched.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"
RT_TASK demo_task_desc;
void demo_task(void *arg)
{
int ret;
RT_TASK_INFO info;
cpu_set_t cpu;
rt_task_set_mode(0,TASK_MODE,NULL);
printf("This is a Demo Task\n");
ret = rt_task_inquire(&demo_task_desc,&info);
if(ret != 0){
printf("Error while inquire task: %d\n", ret);
return;
}
printf("Get task info:\n");
printf(" name:%s, prio:%d, pid:%d, cpu:%d\n",info.name,info.prio,info.pid,info.stat.cpu);
CPU_ZERO(&cpu);
CPU_SET(1, &cpu); // 设置到cpu1
rt_task_set_affinity(&demo_task_desc,&cpu);
rt_task_set_priority(&demo_task_desc,TASK_PRIO+10);
ret = rt_task_inquire(&demo_task_desc,&info);
if(ret != 0){
printf("Error while inquire task: %d\n", ret);
return;
}
printf("Get New task info:\n");
printf(" name:%s, prio:%d, pid:%d, cpu:%d\n",info.name,info.prio,info.pid,info.stat.cpu);
}
int main(int argc, char *argv[])
{
// 创建任务
if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, 0)) {
printf("Error creating sender task\n");
return 1;
}
// 启动任务
rt_task_start(&demo_task_desc, &demo_task, 0);
rt_task_sleep(1000000000); // 等待 1 秒
// 等待任务结束
rt_task_join(&demo_task_desc);
// 清理
rt_task_delete(&demo_task_desc);
return 0;
}
int rt_task_set_periodic(RT_TASK *task, RTIME idate, RTIME period);
使实时任务周期化。
通过在处理器时间线上编程任务的第一个释放点及其周期,使任务周期化。然后任务应调用 rt_task_wait_period()
以休眠,直到处理器时间线中的下一个周期释放点到达。
参数:
task
为 NULL,则当前任务被设为周期性任务。任务必须属于当前进程。idate
等于 TM_NOW
,则使用当前系统日期,或者任务立即变为周期性任务。TM_INFINITE
将停止任务的周期定时器(如果已启用),然后成功返回。返回值:
task
为 NULL 但调用者不是 Xenomai 任务,或者 task
非 NULL 但不是有效的任务描述符,则返回 -EINVAL
。idate
不等于 TM_INFINITE
并且表示过去的日期,则返回 -ETIMEDOUT
。标签:
mode-unrestricted
, switch-primary
注意:
task
为 NULL,则调用者必须是 Alchemy 任务。period
不等于 TM_INFINITE
但短于目标系统的用户调度延迟值,则返回 -EINVAL
。idate
和 period
值被解释为 Alchemy 时钟分辨率的倍数。注意事项:
rt_task_set_periodic()
不会阻塞 task
直到 idate
到达。周期时间线中的第一个节拍应通过调用 rt_task_wait_period()
来等待。示例代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"
RT_TASK demo_task_desc;
void demo_task(void *arg)
{
int data =0;
printf("This is a Demo Task\n");
while(1){
printf("%d\n",++data);
if(data >= 5)
break;
rt_task_wait_period(NULL);
}
}
int main(int argc, char *argv[])
{
// 创建任务
if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating sender task\n");
return 1;
}
// 设置周期任务,初始日期为当前时间,周期 1 秒
rt_task_set_periodic(&demo_task_desc, rt_timer_read(), 1000000000);
// 启动任务
rt_task_start(&demo_task_desc, &demo_task, NULL);
// 等待任务结束
rt_task_join(&demo_task_desc);
// 清理
rt_task_delete(&demo_task_desc);
return 0;
}
int rt_task_set_priority(RT_TASK *task, int prio);
更改实时任务的基本优先级。
任务的基本优先级定义了每个任务所执行工作的相对重要性,从而相应地获得 CPU 的控制权。
更改任务的基本优先级不会影响目标任务由于优先级继承而可能获得的优先级提升。
参数:
task
为 NULL,则更改当前任务的优先级。[T_LOPRIO .. T_HIPRIO]
(包括边界)范围内,其中 T_LOPRIO
是最低有效优先级。返回值:
task
不是有效的任务描述符,或者 prio
无效,则返回 -EINVAL
。task
为 NULL 并且从无效上下文调用此服务,则返回 -EPERM
。标签:
mode-unrestricted
, switch-primary
, switch-secondary
注意:
task
为 NULL,则调用者必须是 Alchemy 任务。示例代码
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#include <sched.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"
RT_TASK demo_task_desc;
void demo_task(void *arg)
{
int ret;
RT_TASK_INFO info;
cpu_set_t cpu;
rt_task_set_mode(0,TASK_MODE,NULL);
printf("This is a Demo Task\n");
ret = rt_task_inquire(&demo_task_desc,&info);
if(ret != 0){
printf("Error while inquire task: %d\n", ret);
return;
}
printf("Get task info:\n");
printf(" name:%s, prio:%d, pid:%d, cpu:%d\n",info.name,info.prio,info.pid,info.stat.cpu);
CPU_ZERO(&cpu);
CPU_SET(1, &cpu); // 设置到cpu1
rt_task_set_affinity(&demo_task_desc,&cpu);
rt_task_set_priority(&demo_task_desc,TASK_PRIO+10);
ret = rt_task_inquire(&demo_task_desc,&info);
if(ret != 0){
printf("Error while inquire task: %d\n", ret);
return;
}
printf("Get New task info:\n");
printf(" name:%s, prio:%d, pid:%d, cpu:%d\n",info.name,info.prio,info.pid,info.stat.cpu);
}
int main(int argc, char *argv[])
{
// 创建任务
if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, 0)) {
printf("Error creating sender task\n");
return 1;
}
// 启动任务
rt_task_start(&demo_task_desc, &demo_task, 0);
rt_task_sleep(1000000000); // 等待 1 秒
// 等待任务结束
rt_task_join(&demo_task_desc);
// 清理
rt_task_delete(&demo_task_desc);
return 0;
}
int rt_task_shadow(RT_TASK *task, const char *name, int prio, int mode);
将调用者转换为实时任务。
将调用线程的个性设置为 Alchemy API,启用完整的 Alchemy 服务集。成功后,调用者不再是常规的 POSIX 线程,而是一个 Xenomai 扩展线程。
如果 prio
非零,新任务将移动到 Xenomai 的实时 FIFO 调度类,即 SCHED_FIFO
。如果 prio
为零,任务将移动到常规的 SCHED_OTHER
类。
以零优先级运行 Xenomai 任务对于运行可能调用阻塞实时服务的非实时进程非常有用,例如等待信号量、从消息队列或缓冲区读取等。
参数:
[0 .. 99]
范围内,其中 0 是最低有效优先级。T_LOCK
使当前任务在返回调用者之前锁定调度器,防止当前 CPU 上的所有进一步的非自愿任务切换。需要从当前任务调用 rt_task_set_mode()
来解除此锁。T_WARNSW
使 SIGDEBUG 信号在当前任务切换到次级模式时发送。此功能对于检测到不必要的迁移到 Linux 域非常有用。此标志在 Mercury 内核上无效。返回值:
prio
无效,则返回 -EINVAL
。-ENOMEM
。name
与已注册的任务冲突,则返回 -EEXIST
。-EBUSY
。-EPERM
。标签:
pthread-only
, switch-secondary
, switch-primary
副作用:
注意:
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#define TASK_PRIO 50
#define TASK_MODE 0
#define TASK_NAME "ShadowDemo"
RT_TASK shadow_task;
void *thread_function(void *arg)
{
int ret;
printf("Regular POSIX thread starting...\n");
// 将当前线程转换为 Xenomai 实时任务
ret = rt_task_shadow(&shadow_task, TASK_NAME, TASK_PRIO, TASK_MODE);
if (ret < 0) {
printf("Error converting to real-time task: %d\n", ret);
return NULL;
}
printf("Now running as Xenomai real-time task\n");
// 获取任务信息
RT_TASK_INFO info;
ret = rt_task_inquire(&shadow_task, &info);
if (ret == 0) {
printf("Task info:\n");
printf(" Name: %s\n", info.name);
printf(" Priority: %d\n", info.prio);
printf(" PID: 0x%x\n", info.pid);
} else {
printf("Error getting task info: %d\n", ret);
}
// 演示实时任务功能:周期性执行
rt_task_set_periodic(NULL, TM_NOW, 500000000); // 500ms 周期
for (int i = 0; i < 5; i++) {
printf("Periodic execution: %d\n", i);
rt_task_wait_period(NULL);
}
printf("Real-time task complete\n");
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t thread;
int ret;
// 创建普通 POSIX 线程
ret = pthread_create(&thread, NULL, thread_function, NULL);
if (ret != 0) {
printf("Error creating thread\n");
return 1;
}
// 等待线程完成
pthread_join(thread, NULL);
printf("Main program exiting\n");
return 0;
}
int rt_task_sleep(RTIME delay);
延迟当前实时任务(相对延迟)。
此例程是 rt_task_sleep_until()
的变体,接受相对超时规范。
参数:
返回值:
rt_task_sleep_until()
。标签:
xthread-only
, switch-primary
注释:
delay
值被解释为 Alchemy 时钟分辨率的倍数(参见 --alchemy-clock-resolution
选项,默认为 1 纳秒)。示例代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"
RT_TASK demo_task_desc;
void demo_task(void *arg)
{
printf("This is a Demo Task\n");
rt_task_suspend(&demo_task_desc);
printf("Demo Task Continue to run\n");
}
int main(int argc, char *argv[])
{
// 创建任务
if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating sender task\n");
return 1;
}
// 启动任务
rt_task_start(&demo_task_desc, &demo_task, NULL);
// 等待任务运行
rt_task_sleep(1000000000); // 1 秒
rt_task_resume(&demo_task_desc);
// 等待任务结束
rt_task_join(&demo_task_desc);
// 清理
rt_task_delete(&demo_task_desc);
return 0;
}
int rt_task_sleep_until(RTIME date);
延迟当前实时任务(绝对唤醒日期)。
延迟调用任务的执行,直到达到给定日期。调用者进入休眠状态,在此状态下不消耗任何 CPU 时间。
参数:
TM_INFINITE
是一个可接受的值,它会导致调用者无限期阻塞,直到调用 rt_task_unblock()
。否则,任何过去的唤醒日期都会导致任务立即返回。返回值:
rt_task_unblock()
,则返回 -EINTR
。date
已经过期,则返回 -ETIMEDOUT
。-EPERM
。标签:
xthread-only
, switch-primary
注释:
task
为 NULL,则调用者必须是 Alchemy 任务。date
值被解释为 Alchemy 时钟分辨率的倍数(参见 --alchemy-clock-resolution
选项,默认为 1 纳秒)。示例代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"
RT_TASK demo_task_desc;
void demo_task(void *arg)
{
printf("This is a Demo Task\n");
rt_task_suspend(&demo_task_desc);
printf("Demo Task Continue to run\n");
}
int main(int argc, char *argv[])
{
// 创建任务
if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating sender task\n");
return 1;
}
// 启动任务
rt_task_start(&demo_task_desc, &demo_task, NULL);
// 等待任务运行
RTIME timeout = rt_timer_read() + 1000000000; // 1 秒
rt_task_sleep_until(timeout);
rt_task_resume(&demo_task_desc);
// 等待任务结束
rt_task_join(&demo_task_desc);
// 清理
rt_task_delete(&demo_task_desc);
return 0;
}
int rt_task_slice(RT_TASK *task, RTIME quantum);
设置任务的时间片轮转量。
设置任务在时间片轮转调度中分配的时间额度。如果 quantum
非零,rt_task_slice()
还会重新填充目标任务的当前时间片。否则,将停止该任务的时间片轮转。
换句话说,rt_task_slice()
应用于切换 Alchemy 任务的时间片轮转调度。
参数:
task
为 NULL,则更改当前任务的时间额度。task
必须属于当前进程。返回值:
task
不是有效的任务描述符或 prio
无效,则返回 -EINVAL
。task
为 NULL 并且从无效上下文调用此服务,则返回 -EPERM
。标签:
mode-unrestricted
, switch-primary
注释:
task
为 NULL,则调用者必须是 Alchemy 任务。quantum
值被解释为 Alchemy 时钟分辨率的倍数(参见 --alchemy-clock-resolution
选项,默认为 1 纳秒)。示例代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME_PREFIX "SliceDemo"
#define NUM_TASKS 3
RT_TASK task_descs[NUM_TASKS];
void demo_task(void *arg)
{
int task_id = *(int*)arg;
int count = 0;
while(count < 5) {
printf("Task %d running (count: %d)\n", task_id, count);
rt_task_sleep(100000000); // Sleep for 100ms
count++;
}
}
int main(int argc, char *argv[])
{
int i;
char task_name[20];
int task_ids[NUM_TASKS];
// 创建并启动多个任务
for (i = 0; i < NUM_TASKS; i++) {
snprintf(task_name, sizeof(task_name), "%s%d", TASK_NAME_PREFIX, i);
task_ids[i] = i;
if (rt_task_create(&task_descs[i], task_name, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating task %d\n", i);
return 1;
}
// 为每个任务设置200ms的时间片
rt_task_slice(&task_descs[i], 200000000);
rt_task_start(&task_descs[i], &demo_task, &task_ids[i]);
}
// 等待所有任务完成
for (i = 0; i < NUM_TASKS; i++) {
rt_task_join(&task_descs[i]);
}
// 清理
for (i = 0; i < NUM_TASKS; i++) {
rt_task_delete(&task_descs[i]);
}
return 0;
}
int rt_task_spawn(RT_TASK *task, const char *name, int stksize, int prio, int mode, void(*entry)(void *), void *arg);
创建并启动一个实时任务。
此服务通过组合调用 rt_task_create()
和 rt_task_start()
来生成一个新任务。
参数:
[0 .. 99]
范围内,其中 0 是最低有效优先级。rt_task_create()
。entry
将接收的用户定义的不透明参数。返回值:
rt_task_create()
。标签:
mode-unrestricted
, switch-secondary
副作用:
rt_task_create()
。示例代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"
RT_TASK demo_task_desc;
void demo_task(void *arg)
{
printf("This is a Demo Task\n");
}
int main(int argc, char *argv[])
{
// 创建并启动任务
if (rt_task_spawn(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE, &demo_task, NULL)) {
printf("Error creating sender task\n");
return 1;
}
// 等待任务结束
rt_task_join(&demo_task_desc);
// 清理
rt_task_delete(&demo_task_desc);
return 0;
}
int rt_task_start(RT_TASK *task, void(*entry)(void *arg), void *arg);
启动实时任务。
此调用启动先前由 rt_task_create()
创建的任务的执行。此服务使启动的任务离开初始的休眠状态。
参数:
entry
将接收的用户定义的不透明参数。返回值:
task
不是有效的任务描述符,则返回 -EINVAL
。标签:
mode-unrestricted
, switch-primary
注意:
启动已经启动的任务会导致无操作,并返回成功状态。
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"
RT_TASK demo_task_desc;
void demo_task(void *arg)
{
printf("This is a Demo Task\n");
}
int main(int argc, char *argv[])
{
// 创建任务
if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating sender task\n");
return 1;
}
// 启动任务
rt_task_start(&demo_task_desc, &demo_task, NULL);
// 等待任务结束
rt_task_join(&demo_task_desc);
// 清理
rt_task_delete(&demo_task_desc);
return 0;
}
int rt_task_suspend(RT_TASK *task);
挂起实时任务。
强制挂起任务的执行。此任务在被显式调用 rt_task_resume()
之前将不具备调度资格。换句话说,由 rt_task_suspend()
调用引起的挂起状态与其他服务引起的延迟和阻塞状态是累积的,并且与它们分开管理。
维护一个嵌套计数,因此 rt_task_suspend()
和 rt_task_resume()
必须成对使用。
接收 Linux 信号会导致挂起的任务立即恢复。
参数:
task
为 NULL,则挂起当前任务。返回值:
task
为 NULL 但调用者不是 Xenomai 任务,或者 task
非 NULL 但不是有效的任务描述符,则返回 -EINVAL
。-EINTR
。task
为 NULL 并且从无效上下文调用此服务,则返回 -EPERM
。标签:
mode-unrestricted
, switch-primary
注意:
如果 task
为 NULL,则调用者必须是 Alchemy 任务。
阻塞和挂起任务状态是累积的。因此,挂起当前等待同步对象(例如信号量、队列)的任务会保持其执行挂起状态,直到其恢复,尽管在此期间可能已获取到等待的资源或超时已过。
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"
RT_TASK demo_task_desc;
void demo_task(void *arg)
{
printf("This is a Demo Task\n");
rt_task_suspend(&demo_task_desc);
printf("Demo Task Continue to run\n");
}
int main(int argc, char *argv[])
{
// 创建任务
if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating sender task\n");
return 1;
}
// 启动任务
rt_task_start(&demo_task_desc, &demo_task, NULL);
// 等待任务运行
rt_task_sleep(1000000000); // 1 秒
rt_task_resume(&demo_task_desc);
// 等待任务结束
rt_task_join(&demo_task_desc);
// 清理
rt_task_delete(&demo_task_desc);
return 0;
}
int rt_task_unbind(RT_TASK *task);
解除任务绑定。
参数:
此例程释放先前对 Alchemy 任务的绑定。在此调用返回后,该描述符将不再有效,无法引用此对象。
标签:
thread-unrestricted
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"
RT_TASK demo_task_desc;
void demo_task(void *arg)
{
RT_TASK current_task;
RT_TASK_INFO info;
printf("This is a Demo Task\n");
// 通过TASK_NAME绑定到描述符
if (rt_task_bind(¤t_task, TASK_NAME, TM_INFINITE)) {
printf("Error creating sender task\n");
return;
}
// 使用描述符
int ret = rt_task_inquire(¤t_task,&info);
if(ret == 0){
printf("Get task info:\n");
printf(" name:%s, prio:%d, pid:%d, cpu:%d\n",info.name,info.prio,info.pid,info.stat.cpu);
}else{
printf("Error while inquire task: %d\n", ret);
}
// 解除绑定
rt_task_unbind(¤t_task);
}
int main(int argc, char *argv[])
{
// 创建任务
if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating sender task\n");
return 1;
}
// 启动任务
rt_task_start(&demo_task_desc, &demo_task, NULL);
// 等待任务结束
rt_task_join(&demo_task_desc);
// 清理
rt_task_delete(&demo_task_desc);
return 0;
}
int rt_task_unblock(RT_TASK *task);
解除实时任务的阻塞状态。
将任务从当前的任何等待状态中解除。此调用会清除目标任务的所有延迟和/或资源等待条件。
然而,rt_task_unblock()
不会恢复先前通过 rt_task_suspend()
强制挂起的任务。如果所有的挂起条件都消失了,任务将重新具备调度资格。
参数:
返回值:
task
不是有效的任务描述符,则返回 -EINVAL
。标签:
unrestricted
, switch-primary
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"
RT_TASK demo_task_desc;
void demo_task(void *arg)
{
printf("This is a Demo Task\n");
RTIME timeout = rt_timer_read() + 10000000000; // 10 秒
rt_task_sleep_until(timeout);
printf("Demo Task Continue to run\n");
}
int main(int argc, char *argv[])
{
// 创建任务
if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating sender task\n");
return 1;
}
// 启动任务
rt_task_start(&demo_task_desc, &demo_task, NULL);
rt_task_sleep(1000000000); // 1 秒
// 解除线程sleep状态
printf("Unblocking task\n");
rt_task_unblock(&demo_task_desc);
// 等待任务结束
rt_task_join(&demo_task_desc);
// 清理
rt_task_delete(&demo_task_desc);
return 0;
}
int rt_task_wait_period(unsigned long *overruns_r)
等待下一个周期释放点。
将当前任务延迟到下一个周期释放点。周期定时器应已通过调用 rt_task_set_periodic()
为 task
预先启动。
参数:
overruns_r
应为指向内存位置的指针,该位置将被写入待处理的超时次数。仅当 rt_task_wait_period()
返回 -ETIMEDOUT
或成功时才会写入此值。否则,该内存位置保持不变。如果为 NULL,则不会返回此计数。返回值:
overruns_r
非 NULL,则零将写入指向的内存位置。否则:
rt_task_set_periodic()
,则返回 -EWOULDBLOCK
。rt_task_unblock()
,则返回 -EINTR
。-ETIMEOUT
。如果 overruns_r
非 NULL,则待处理的超时次数将写入指向的内存位置。-EPERM
。标签:
xthread-only
, switch-primary
注意:
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME "Demo"
RT_TASK demo_task_desc;
void demo_task(void *arg)
{
int data =0;
printf("This is a Demo Task\n");
while(1){
printf("%d\n",++data);
if(data >= 5)
break;
rt_task_wait_period(NULL);
}
}
int main(int argc, char *argv[])
{
// 创建任务
if (rt_task_create(&demo_task_desc, TASK_NAME, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating sender task\n");
return 1;
}
// 设置周期任务,初始日期为当前时间,周期 1 秒
rt_task_set_periodic(&demo_task_desc, rt_timer_read(), 1000000000);
// 启动任务
rt_task_start(&demo_task_desc, &demo_task, NULL);
// 等待任务结束
rt_task_join(&demo_task_desc);
// 清理
rt_task_delete(&demo_task_desc);
return 0;
}
int rt_task_yield(void)
手动时间片轮转。
将当前任务移动到其优先级组的末尾,以便切换到下一个处于就绪状态的同等优先级任务。
返回值:
-EPERM
。标签:
xthread-only
, switch-primary
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#define TASK_PRIO 50
#define TASK_MODE T_JOINABLE
#define TASK_STKSZ 0
#define TASK_NAME_PREFIX "YieldDemo"
#define NUM_TASKS 3
RT_TASK task_descs[NUM_TASKS];
void demo_task(void *arg)
{
int task_id = *(int*)arg;
int count = 0;
while(count < 5) {
printf("Task %d running (count: %d)\n", task_id, count);
count++;
// 主动让出CPU
if(task_id == count - 1)
rt_task_yield();
// 短暂睡眠,以便观察输出
rt_task_sleep(10000000); // 10ms
}
}
int main(int argc, char *argv[])
{
int i;
char task_name[20];
int task_ids[NUM_TASKS];
// 创建并启动多个任务
for (i = 0; i < NUM_TASKS; i++) {
snprintf(task_name, sizeof(task_name), "%s%d", TASK_NAME_PREFIX, i);
task_ids[i] = i;
if (rt_task_create(&task_descs[i], task_name, TASK_STKSZ, TASK_PRIO, TASK_MODE)) {
printf("Error creating task %d\n", i);
return 1;
}
rt_task_start(&task_descs[i], &demo_task, &task_ids[i]);
}
// 等待所有任务完成
for (i = 0; i < NUM_TASKS; i++) {
rt_task_join(&task_descs[i]);
}
// 清理
for (i = 0; i < NUM_TASKS; i++) {
rt_task_delete(&task_descs[i]);
}
return 0;
}