Kithara事件同步

事件同步


事件非常有价值,它是多线程应用程序中经常使用的同步工具。在Kithara RealTime Suite中,事件是必需的,它们也必须从内核级别进行设置。普通 Windows 事件不支持内核功能。除此之外,你还可以创建Kithara事件来同步实时任务。

创建事件

注意: 在创建事件是,参数 flag 决定该事件是线程事件还是任务事件!顾名思义,线程事件只能阻塞线程,任务事件只能阻塞任务!

KS_createEvent 创建一个事件并返回一个事件句柄(这不是 Windows-Event-Handle,不得与 Windows 函数一起使用),获取的句柄是所有其他事件函数所必需的。

可以使用系统范围的唯一名称来命名事件。这样,就可以在不同的应用程序实例中使用一个事件。该名称指定给参数 name,并且必须以零结尾("\0 空终止符),最大字符串长度为 64。使用 flags 参数在普通线程事件、任务事件 (‘KSF_KERNEL_EXEC’) 和手动重置选项 (‘KSF_MANUAL_RESET’) 之间进行选择。

事件状态变更

事件的状态可以通过不同的函数进行更改。这些函数分别在手动重置事件、自动重置事件上的工作方式不同。

设置事件

函数 KS_setEvent 将设置 hEvent 中给出的事件。自动重置事件将被消耗,并从等待它的最高线程或任务自动重置。在为此事件调用 reset-function 之前,manual-reset-event 将保持设置状态。

重置事件

KS_resetEvent 将重置 manual-reset-event(如果当前已设置)。

脉冲事件

函数 KS_pulseEvent 设置并立即重置事件。可以在三种不同的情况下调用此函数(当前未设置事件):

  • 没有任务/线程在等待:没有任何反应

  • 一个或多个任务/线程正在等待自动重置事件:优先级最高的任务/线程将使用该事件,并且该事件将被重置。

  • 一个或多个任务/线程正在等待手动重置事件:所有任务/线程都将使用该事件,然后该事件将被重置。

呼叫后将重置事件。

阻塞线程或任务

这是事件的主要功能。该事件可用于阻止线程或任务。使用“KSF_KERNEL_EXEC”创建的事件只能阻止任务,没有该标志的事件只能阻止线程。

等待事件

如果调用函数 KS_waitForEvent,则当前线程或任务将被阻止。可以通过参数 timeout 确定超时值。timeout-value 表示 100 ns 单位(与所有时间值一样)。线程或任务将被阻止,直到设置事件并可由当前线程或任务使用。当然,只有在未达到超时时。若要使用无限超时,请将参数设置为零。

查询事件状态

要读出事件的当前状态,可以调用 KS_getEventState 函数。

删除事件

要删除事件,请使用函数 KS_closeEvent。如果该事件在多个应用程序实例中使用,则必须在每个实例中关闭该事件,然后才能实际删除该事件。

项目实例

项目结构:
在这里插入图片描述

SharedData.h

#pragma once
#include <KrtsDemo.h>

// 内核层数据需要1字节对齐
#pragma pack(1)

typedef struct SharedData {                                                                     
    KSHandle event_handle;       // 事件句柄  
    int ret;                     // 返回的数据
}SharedData;

#pragma pack()

KitharaDll.cpp

#include "SharedData.h"
#include <cstdint>

SharedData* sys_data_ptr_ = nullptr;			
int compute;

// 初始化函数  
extern "C" __declspec(dllexport) KSError __stdcall _initFunction(void* pArgs, void* pConttext) {
	sys_data_ptr_ = (SharedData*)pArgs;

	// 创建事件
	KSError error = KS_createEvent(&sys_data_ptr_->event_handle, "DemoEvent", KSF_NO_FLAGS);
	if (error != KS_OK)
	{
		// Todo 
		return error;
	}

	return KS_OK;
}

// 数据处理
extern "C" __declspec(dllexport) KSError __stdcall _computeEvent(void* pArgs, void* pConttext) {
	compute++;
	sys_data_ptr_->ret += compute;

	KSError error = KS_setEvent(sys_data_ptr_->event_handle);
	if (error != KS_OK)
	{
		// Todo
		return error;
	}
	return KS_OK;
}


extern "C" __declspec(dllexport) KSError __stdcall _exitFunction(void* pArgs,void *pConttext) {

	if (sys_data_ptr_ != nullptr)
	{
		KS_closeEvent(sys_data_ptr_->event_handle);
	}
	return KS_OK;
}


#define WIN32_LEAN_AND_MEAN         
// Windows 头文件
#include <windows.h>

BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD reason, LPVOID pReserved) {
	return TRUE;
}

KitharaDemo.cpp

#include <iostream>
#include <mutex>
#include "../KitharaDll/SharedData.h"
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

const char customerNumber[256] = "DEMO";
SharedData* app_data_ptr_ = nullptr;		// 应用层共享内存指针	
SharedData* sys_data_ptr_ = nullptr;		// 内核层共享内存指针
											// 应用层不能使用内核层指针!!!
bool is_running_{false};					// 正在运行
KSHandle kermel_handle;

void OutputErr(KSError error, const char* pFuncName, const char* pComment)
{
	if (error == KS_OK)
		return;

	const char* pError;
	KS_getErrorString(error, &pError, KSLNG_DEFAULT);
	printf("ERROR (%08X = \'%s\') -  %s: %s\n", error, pError, pFuncName, pComment);
}

// 读取数据线程
KSError _stdcall ReadThread(void* pArgs)
{
	if (app_data_ptr_ != nullptr)
	{
		KSError error;
		while (is_running_)
		{
			error = KS_waitForEvent(app_data_ptr_->event_handle, KSF_NO_FLAGS, 0); 
			if (error != KS_OK)
			{
				return error;
			}
			printf("Event Read: %d \n", app_data_ptr_->ret);
		}
	}

	return KS_OK;
}

int main()
{
	KSError error;
	error = KS_openDriver(customerNumber);	// 所有Kithar项目的第一步
	if (error != KS_OK)
	{
		error = 1;
		OutputErr(error, "KS_openDriver", "Unable to open the driver!");

	}
	else
	{
		printf("Hello Kithara! \n");
	}

	// 创建共享内存
	error = KS_createSharedMem(reinterpret_cast<void**>(&app_data_ptr_), reinterpret_cast<void**>(&sys_data_ptr_), "KitharaDemo", sizeof(SharedData), 0);
	if (error != KS_OK)
	{
		OutputErr(error, "KS_createSharedMem", "failed to allocate shared memory");
		KS_closeDriver();
		return 0;
	}


	// 加载内核DLL
	error = KS_loadKernel(&kermel_handle, "KitharaDll.dll",nullptr, nullptr, KSF_KERNEL_EXEC | KSF_SAVE_FPU);
	if (error != KS_OK)
	{
		OutputErr(error, "KS_loadKernel", "load dll failed!");
		KS_closeDriver();
		return 0;
	}

	// 内核初始化
	error = KS_execKernelFunction(kermel_handle, "_initFunction", sys_data_ptr_, nullptr, KSF_REALTIME_EXEC | KSF_SAVE_FPU);
	if (error != KS_OK)
	{
		OutputErr(error, "KS_execKernelFunction", "init failed");
		KS_closeDriver();
		return 0;
	}

	// 创建线程
	is_running_ = true;
	app_data_ptr_->ret = 0;
	error = KS_createThread(ReadThread, nullptr, nullptr);
	if (error != KS_OK)
	{
		OutputErr(error, "KS_createThread", "create thread failed");
		KS_closeDriver();
		return 0;
	}

	// 结束线程
	int time_count = 0;
	while (is_running_)
	{
		if (++time_count > 10)
		{
			is_running_ = false;
		}

		// Todo ...
		error = KS_execKernelFunction(kermel_handle, "_computeEvent", sys_data_ptr_, nullptr, KSF_REALTIME_EXEC | KSF_SAVE_FPU);
		if (error != KS_OK)
		{
			OutputErr(error, "KS_execKernelFunction", "get compute failed");
			return error;
		}

		Sleep(1000);
	}

	// 资源释放
	KS_execKernelFunction(kermel_handle, "_exitFunction", sys_data_ptr_, nullptr, KSF_REALTIME_EXEC | KSF_SAVE_FPU);
	// 资源内核
	error = KS_freeKernel(kermel_handle);
	if (error != KS_OK)
	{
		OutputErr(error, "KS_freeKernel", "");
		KS_closeDriver();
		return 0;
	}
	// 资源共享内存
	error = KS_freeSharedMem(app_data_ptr_);
	if (error != KS_OK)
	{
		OutputErr(error, "KS_freeSharedMem", "");
		KS_closeDriver();
		return 0;
	}
	// 关闭驱动
	error = KS_closeDriver();
	if (error != KS_OK)
	{
		OutputErr(error, "KS_closeDriver", "");
		KS_closeDriver();
		return 0;
	}
	Sleep(1000);
	return 0;
}

更多实例:

        smp\CanFDRecv
        smp\EtherCATBridge
        smp\LibraryDlibOpenCV
        smp\NetworkEthernetMonitor
        smp\NetworkTcpClient
        smp\NetworkTcpServer
        smp\CameraImageAcquisition
  • 26
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值