便携式航电实时系统测试平台操作系统服务

68 阅读6分钟

1.1 操作系统相关服务

ETest 提供了 Task_T Semaphore_T Mutex_T Counter_T 等类以提供操作系统相关的服务,可以实现任务调度与协同。

1.1.1 Task_T类

所在命名空间为:Kiyun::LowerComputer::Rasl::Os。这个类的对象代表在下位机中运行的任务。

/** 系统固定头文件 / #include <Rasl/rasl.hpp> #include <DataUploader/DataUploader.hpp> #include "StaticVariable.h" #include "rasl-dpd/user.hpp" #include "UserChannels.rasi" #include "DataCollect.hpp" /* 系统固定头文件 / //用户测试代码需要新增的头文件 namespace{ using namespace Kiyun::LowerComputer; using namespace Kiyun::LowerComputer::Rasl; using namespace Kiyun::LowerComputer::Rasl::Frame; using namespace Kiyun::LowerComputer::Rasl::Device; //通道设备命名空间 using namespace Kiyun::LowerComputer::DataUploader; //数据上传命名空间 using namespace Kiyun::Channel; using namespace Kiyun::DataCollect; //数据采集接口命名空间 using namespace Dpdp; //协议命名空间 using namespace std; using namespace Rasl::Frame; using Rasl::Logging_T; using Rasl::Os::Task_T; //本地变量、本地函数声明 //Os::Semaphore_T f_exitSem; int x(0); int adder(void) { for(int i = 0; i < 100000; ++i) ++x; return 0; } } //主函数入口 int Main() { //设置全局日志属性 KYLOG_GLOBAL().severity(Logging_T::Severity_E::DEBG_e); KYLOG_SCOPE("main").tag("信号相关").tag("硬件"); KYLOG(INFO) << "Hello world, Kiyun!\n"; //可保存到日志文件 KYIO(log) << "Hello World,Kiyun!\n"; //发送到控制台 /测试代码/ vector<Task_T> tasks; for(int i = 0; i < 200; ++i) { tasks.push_back(Task_T::spawn(adder).first); } for(auto t : tasks) t.wait(); KYLOG(INFO) << "x : " << x; KYLOG_DEF(INFO).tag("单项标记"); KYLOG_USE() << "Y : " << x; //f_exitSem.wait(); return 0; } bool Exit(Os::Task_T) { //返回值为true,表示能中止正在运行的实时任务 //f_exitSem.notifyOne(); //return true; return false; //默认情况下该实时任务不能被中止 }

1) spawn方法

函数原型:std::pair<Task_T, Error_T> spawn(const SimpleEntry_T& ent)

函数功能:启动一个任务。

参数:ent:型如 int (void*) 的函数。其参数忽略即可,正常情况应返回 0。

返回值:一个 pair 对象,first 成员是启动的 Task_T 对象,second 成员是错误情况。大多数情况下,second 成员可以安全的忽略。

2) wait方法

函数原型:void wait();

函数功能:等待任务结束。调用者任务本身阻塞,直到所 wait 的任务退出才继续运行。必须在 spawn 所返回的 Task_T 对象上使用。

3) waitFor方法

函数原型:

Mince::LowerComputer::Rasl::Error_T waitFor( Mince::LowerComputer::Rasl::Frame::Timeout_T t );

函数功能:等待任务结束或超时。调用者任务本身阻塞,直到所 wait 的任务退出或者超出指定的时间才继续运行。必须在 spawn 所返回的 Task_T 对象上使用。

参数:t:超时时长。

返回值:无错误代表所等待的任务已退出,有错误代表超时。

auto task = Task_T::spawn(someFunction); auto err = task.waitFor(5_s); if(err) KYLOG(WARN) << "任务在指定时间内未结束!";

1.1.2 Semaphore_T类

所在命名空间为:Kiyun::LowerComputer::Rasl::Os

  1. 构造方法

函数原型:Semaphore_T()

函数功能:初始化一个Semaphore_T对象

参数:无

返回值:无

2) notifyOne

函数原型:void notifyOne()

函数功能:发送一个信号量,通知正在等待信号量的第一个线程继续执行。

参数:无

返回值:无

3) notifyAll

函数原型:void notifyAll()

函数功能:通知所有等待信号量的线程继续执行。

参数:无

返回值: 无

4) wait

函数原型:void wait()

函数功能:等待信号量。执行此方法的任务立即阻塞,直到其它任务在此信号量上调用 notify 为止。

参数:无

返回值: 无

5) waitFor

函数原型:bool waitFor(Kiyun::LowerComputer::Rasl::Frame::Timeout_T time)

函数功能:等待信号量的到来,最长等待时间为time,单位为秒。

参数:time:等待时长

返回值: true: 信号量到达;false: 超时。

1.1.3 Mutex_T类

所在命名空间为:Kiyun::LowerComputer::Rasl::Os。这个类用作互斥锁,通常用于保护那些“不可同时访问的资源”。

#include <Rasl/rasl.hpp> namespace { using namespace std; using namespace Kiyun::LowerComputer; using namespace Rasl::Frame; using Rasl::Os::Task_T; using Rasl::Os::Mutex_T; int x = 0; Mutex_T xMut; int adder(void*) { KYLOG_SCOPE("add"); xMut.lock(); for(int i = 0; i < 100000; ++i) ++x; xMut.unlock(); KYLOG(INFO) << "加完"; return 0; } } int kiyunMain() { KYLOG_SCOPE("main"); vector<Task_T> tasks; for(int i = 0; i < 200; ++i) { tasks.push_back(Task_T::spawn(adder).first); } for(auto t : tasks) t.wait(); KYLOG(INFO) << "x : " << x; return 0; }

1) lock 方法

函数原型:void lock();

函数功能:取得锁。如果锁已被其它任务取得,则任务立即阻塞,直到锁被释放为止。如果锁已被本任务取得,再次调用 lock,后果未定义。

参数:无

返回值:无

2) unlock 方法

函数原型:void unlock();

函数功能:释放锁。

参数:无

返回值:无

3) tryLock 方法

函数原型:bool tryLock();

函数功能:取得锁。如果锁已被其它任务取得,则返回 false,否则返回 true。如果锁已被本任务取得,再次调用本方法,后果未定义。

参数:无

返回值:true: 取锁成功;false:未取得锁。

4) Guard_T内嵌类

其构造函数以一个 Mutex_T 对象为参数,并在构造时调用其 lock 方法。在析构时调用对应 Mutex_T 对象的 unlock 方法。

std::queue<命令_T> 队列; Mutex_T 队列锁; void 入列(const 命令_T& cmd) { MCLOG_SCOPE("入列"); { // 用花括号划定锁的保护范围 Mutex_T::Guard_T guard{队列锁}; 队列.push(cmd); } // guard 对象在此之前析构,这里不再是锁的保护范围 MCLOG(INFO) << "命令已入列。"; }

f="">1.1.4 Counter_T类

所在命名空间为:Kiyun::LowerComputer::Rasl::Os。这个类用作计数器,用于“生产者与消费者”模式时,给资源计数。在多个生产者和/或多个消费者的场合,计数器能够保证资源计数的正确性。

#include <Rasl/rasl.hpp> #include namespace { using namespace std; using namespace Kiyun::LowerComputer; using namespace Rasl::Frame; using Rasl::Error_T; using Rasl::Device::Com_T; using Rasl::Os::Task_T; using Rasl::Logging_T; auto com00 = Com_T::get(Com_T::Setup_T("com/0/0") .baudRate(115200) .parity(Com_T::Parity_E::NONE_e) ); auto com01 = Com_T::get(Com_T::Setup_T("com/0/1") .baudRate(115200) .parity(Com_T::Parity_E::NONE_e) ); auto com02 = Com_T::get(Com_T::Setup_T("com/0/2") .baudRate(115200) .parity(Com_T::Parity_E::NONE_e) ); queue que; Rasl::Os::Mutex_T bufMut; Rasl::Os::Counter_T readDone; struct Reader_T { string rs; bool operator() (char* buf, size_t size, Error_T) { rs += string{buf, buf + size}; auto done = rs.size() >= 7; if(done) { { Rasl::Os::Mutex_T::Guard_T guard(bufMut); que.emplace(move(rs)); } readDone.count(); } return true; } }; } int kiyunMain() { KYLOG_GLOBAL().severity(Logging_T::Severity_E::INFO_e); KYLOG_SCOPE("main"); Reader_T reader0, reader1, reader2; com00.intRead(reader0); com01.intRead(reader1); com02.intRead(reader2); // 10秒钟没有输入则退出 while(readDone.waitFor(10_s)) { string rs = que.front(); que.pop(); KYLOG(INFO) << rs; } return 0; }

1) count方法

函数原型:void count();

函数功能:使资源计数加1。应当由“生产者”调用,表示可供“消费者”使用的资源多了一个。

参数:无

返回值:无

2) countAll方法

函数原型:void countAll();

函数功能:应当由“生产者”调用。满足当前所有等待资源的“消费者”。

参数:无

返回值:无

3) wait方法

函数原型:void wait();

函数功能:使资源计数减1。应当由“消费者”调用,如果当前资源计数为0,则当前任务立即阻塞,直到有“生产者”将资源计数增加为止。

参数:无

返回值:无

4) waitFor方法

函数原型:bool waitFor ( Mince :: LowerComputer :: Rasl :: Frame :: Timeout_T );

函数功能:使资源计数减1或者超时。应当由“消费者”调用,如果当前可用资源计数为0,则当前任务立即阻塞,直到有“生产者”增加资源计数或超时为止。

参数:超时时限。

返回值:true:资源计数减1;false:超时。