设备通信方式多种多样(USB/WIFI/BT等),不同通信方式使用差异很大且繁琐,同时通信链路的融合共享和冲突无法处理,通信安全问题也不好保证。分布式软总线是手机、平板、智能穿戴、智慧屏、车机等分布式设备的通信基座,为设备之间的互联互通提供了统一的分布式通信能力。 分布式软总线技术是基于华为多年的通信技术积累,参考计算机硬件总线,在1+8+N设备间搭建一条“无形”的总线,具备自发现、自组网、高带宽低时延的特点。
应用场景:
智能家居场景:在烹饪时,手机可以通过碰一碰和烤箱连接,并将自动按照菜谱设置烹调参数,控制烤箱来制作菜肴。与此类似,料理机、油烟机、空气净化器、空调、灯、窗帘等都可以在手机端显示并通过手机控制。设备之间即连即用,无需繁琐的配置。 多屏联动课堂:老师通过智慧屏授课,与学生开展互动,营造课堂氛围;学生通过手机完成课程学习和随堂问答。统一、全连接的逻辑网络确保了传输通道的高带宽、低时延、高可靠。
分布式软总线架构图:
鸿蒙分布式软总线的原理:
- 统一的通信协议:鸿蒙系统采用统一的通信协议,使不同设备之间可以进行无缝的通信。这个通信协议可以支持不同的通信方式,包括有线和无线通信。
- 分布式服务框架:鸿蒙系统提供了一个分布式服务框架,该框架可以将设备上的应用程序和服务进行管理和调度。通过这个框架,设备可以注册自己的服务,并可以通过分布式软总线来访问其他设备上的服务。
- 资源共享:鸿蒙系统通过分布式软总线实现了设备之间的资源共享。设备可以将自己的资源注册到分布式软总线上,其他设备可以通过分布式软总线来访问这些资源。例如,一个设备上的打印机可以注册到分布式软总线上,其他设备就可以通过分布式软总线来访问这个打印机,实现打印功能的共享。
- 事件通知机制:鸿蒙系统通过分布式软总线实现了设备之间的事件通知机制。当一个设备上发生了某个事件,比如温度传感器检测到了温度变化,它可以通过分布式软总线来通知其他设备。其他设备可以根据这个事件来做出相应的响应,比如调整空调的温度
设备间如何发现连接并传输数据:
软总线技术支持对不同协议的异构网络进行组网。传统场景下,需要蓝牙传输的两台设备必须都具有蓝牙,需要WiFi传输的设备必须都具有WiFi。而蓝牙/WiFi 之间是无法进行数据通信的。 软总线提出蓝牙/WiFi 融合网络组网技术(架构如下图所示),解决了不同协议设备进行数据通信的问题。使得多个鸿蒙设备能够自动构建一个逻辑全连接网络,用户或者业务开发者无需关心组网方式与物理协议。 传统开发模式: 在传统开发模式中开发者需要适配不同网络协议和标准规范。 分布式开发模式: 在HarmonyOS分布式开发模式中开发不再需要关心网络协议差异,业务开发与设备组网解耦,业务仅需监听设备上下线,开发成本大大降低。 软总线传输的优点: 高带宽(High Speed)、 低时延(Low Latency)、 高可靠(High Reliability) 极简协议 将中间的四层协议栈精简为一层提升有效载荷,有效传输带宽提升20%,极简协议在传统网络协议的基础上进行增强:
- 流式传输:基于UDP实现数据的保序和可靠传输;
- 双轮驱动:颠覆传统TCP每包确认机制;
- 不惧网损:摒弃传统滑动窗口机制,丢包快速恢复,避免阻塞;
- 不惧抖动:智能感知网络变化,自适应流量控制和拥塞控制;
软总线demo
1.dsoftbus_start()
入口启动函数,启动后循环发布、发现、发现节点后连接节点。
int dsoftbus_start(){
if (init() < 0) {
return -1;
}
if (!dsoftbus_init()) {
return -2;
}
if (dsoftbus_publish() < 0) {
return -3;
}
if (dsoftbus_create_session() < 0) {
return -4;
}
if (dsoftbus_send() < 0) {
return -5;
}
while (1) {
osDelay(5000);
dsoftbus_undiscover();
osDelay(1000);
dsoftbus_discovery();
osDelay(1000);
dsoftbus_node();
dsoftbus_connect();
}
return 0;
}
2.init()初始化mutex及数据
int init(){
if (pthread_mutex_init(&mutex_device, NULL) != 0)
return -1;
if (pthread_mutex_init(&mutex_session, NULL) != 0)
return -2;
pthread_mutex_lock(&mutex_session);
for (int i = 0; i < MAX_DEVICE_NUMBER; i++) {
allSessionInfos[i].session_id = -1;
allSessionInfos[i].opened = false;
}
pthread_mutex_unlock(&mutex_session);
return 0;
}
3.dsoftbus_init()初始化软总线
bool dsoftbus_init(){
InitSoftBusServer();
return GetServerIsInit();
}
4.dsoftbus_publish()软总线发布
int dsoftbus_publish(){
if (isPublished) {
return 0;
}
PublishInfo pub_info = {
.publishId = publishId,
.mode = DISCOVER_MODE_ACTIVE,
.medium = COAP,
.freq = LOW,
.capability = g_capabilityMap[SHARE_CAPABILITY_BITMAP].capability,
.capabilityData = NULL,
.dataLen = 0,
};
IPublishCb pub_cb = {
.OnPublishResult = OnPublishResult,
};
int32_t ret = PublishLNN(pkgName, &pub_info, &pub_cb);
if (ret == SOFTBUS_OK) {
isPublished = true;
return 0;
}
printf("PublishService failed %ld\n", ret);
return -1;
}
5.dsoftbus_discovery()软总线发现
int dsoftbus_discovery(){
if (isDiscoveryed) {
return 0;
}
SubscribeInfo sub_info = {
.subscribeId = publishId,
.mode = DISCOVER_MODE_ACTIVE,
.medium = COAP,
.freq = LOW,
.capability = g_capabilityMap[SHARE_CAPABILITY_BITMAP].capability,
.capabilityData = NULL,
.dataLen = 0,
.isSameAccount = true,
.isWakeRemote = true,
};
IRefreshCallback disc_cb = {
.OnDeviceFound = OnDeviceFound,
.OnDiscoverResult = OnDiscoverResult,
};
int32_t ret = RefreshLNN(pkgName, &sub_info, &disc_cb);
printf("RefreshLNN ret %ld\n", ret);
if (ret == SOFTBUS_OK) {
isDiscoveryed = true;
return 0;
}
return -1;
}
int dsoftbus_undiscover(){
int32_t ret = StopRefreshLNN(pkgName, publishId);
isDiscoveryed = false;
printf("StopRefreshLNN ret %ld\n", ret);
if (ret == SOFTBUS_OK) {
return 0;
}
return -1;
}
6.dsoftbus_create_session()创建session
int dsoftbus_create_session(){
INodeStateCb node_cb = {
.events = 0xff,
.onNodeOnline = OnNodeOnline,
.onNodeOffline = OnNodeOffline,
.onNodeBasicInfoChanged = OnNodeBasicInfoChanged,
.onNodeStatusChanged = OnNodeStatusChanged,
};
ISessionListener session_cb = {
.OnSessionOpened = OnSessionOpened,
.OnSessionClosed = OnSessionClosed,
.OnBytesReceived = OnBytesReceived,
};
int32_t ret = 0;
ret = RegNodeDeviceStateCb(pkgName, &node_cb);
printf("RegNodeDeviceStateCb ret %d \n", ret);
if (ret < 0) {
return -1;
}
if (GetLocalNodeDeviceInfo(pkgName, &local_node) != SOFTBUS_OK) {
printf("GetLocalNodeDeviceInfo failed!\n");
return -2;
}
ret = CreateSessionServer(pkgName, local_node.networkId, &session_cb);
if (ret != SOFTBUS_OK) {
return -3;
}
return 0;
}
7.dsoftbus_node()更新node信息
int dsoftbus_node(){
NodeBasicInfo* nodeinfo = NULL;
int32_t infoNum = 0;
if (GetAllNodeDeviceInfo(pkgName, &nodeinfo, &infoNum) != SOFTBUS_OK){
if (nodeinfo)
FreeNodeInfo(nodeinfo);
return -1;
}
printf("GetAllNodeDeviceInfo num %ld\n", infoNum);
for (int j = 0; j < infoNum; j++) {
pthread_mutex_lock(&mutex_session);
for (int i = 0; i < MAX_DEVICE_NUMBER; i++) {
if (strcmp(allSessionInfos[i].node.networkId, nodeinfo[j].networkId) == 0) {
printf("same session %s\n", allSessionInfos[i].node.networkId);
break;
}
if (allSessionInfos[i].session_id == -1) {
printf("add session[%d] %s\n", i, nodeinfo[j].networkId);
allSessionInfos[i].session_id = 0;
memcpy(&allSessionInfos[i].node, &nodeinfo[j], sizeof(NodeBasicInfo));
break;
}
}
pthread_mutex_unlock(&mutex_session);
}
FreeNodeInfo(nodeinfo);
return 0;
}
8.dsoftbus_connect()连接session
void dsoftbus_connect(){
static SessionAttribute session_attr = {
.dataType = TYPE_BYTES,
.linkTypeNum = 3,
.linkType = { LINK_TYPE_WIFI_WLAN_5G, LINK_TYPE_WIFI_WLAN_2G, LINK_TYPE_WIFI_P2P },
};
pthread_mutex_lock(&mutex_session);
for (int i = 0; i < MAX_DEVICE_NUMBER; i++) {
if (allSessionInfos[i].session_id == 0 && allSessionInfos[i].node.networkId[0] != 0) {
int32_t id = OpenSession(local_node.networkId, allSessionInfos[i].node.networkId, allSessionInfos[i].node.networkId, groupId, &session_attr);
printf("OpenSession [%d] %s id = %d\n", i, allSessionInfos[i].node.networkId, id);
if (id > 0) {
allSessionInfos[i].session_id = id;
allSessionInfos[i].opened = false;
}
}
}
pthread_mutex_unlock(&mutex_session);
}
9.dsoftbus_send()发送数据
void dsoftbus_send_thread(void *arg){
while(1)
{
osDelay(5000);
static int count = 0;
char buffer[30];
sprintf(buffer, "hello dsoftbus %d", count++);
pthread_mutex_lock(&mutex_session);
for (int i = 0; i < MAX_DEVICE_NUMBER; i++) {
if (allSessionInfos[i].session_id > 0 && allSessionInfos[i].opened) {
int32_t ret = SendBytes(allSessionInfos[i].session_id, buffer, strlen(buffer) + 1);
printf("SendBytes sessionid %d ret %d str: %s\n", allSessionInfos[i].session_id, ret, buffer);
}
}
pthread_mutex_unlock(&mutex_session);
}
}
int dsoftbus_send()
{
osThreadAttr_t attr;
attr.name = "send task";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = 65536;
attr.priority = 24;
if (osThreadNew(bus_send_thread, NULL, &attr) == NULL) {
printf("Falied to create bus_start!\n");
return -1;
}
return 0;
}
10.回调 接收数据回调
static void OnBytesReceived(int sessionId, const void* data, unsigned int len){
printf("<OnBytesReceived>CB: data=%s datalen=%u sessionId=%d\n", (char *)data, len, sessionId);
}
鸿蒙是如何让1套OS适配所有终端的?
这就要说到鸿蒙是一款 微内核操作系统
什么是微内核?
微内核的概念是由Richard Rashid在卡内基梅隆(Carnegie-Mellon)大学开发Mach操作系统时提出的。 微内核从原理上了来说很简单,就是把最不能去除的操作系统功能留在内核层,其他的东西统统送到外核甚至应用层去。
那么微内核是如何工作的呢?
微内核中定义了一种进程间通信的机制------消息。当应用程序请求相关服务时,会向微内核发送一条与此服务对应的消息,微内核再把这条消息发送给相关的服务进程,接着服务进程会完成相关的服务。 我们举一个应用程序读取一个文件的例子。首先,应用程序调用文件系统API,比如open()函数,请求打开一个文件。操作系统内核识别这是一个文件系统相关的请求,便将其转发给负责文件系统的服务进程。文件系统服务进程接收到打开文件的请求,根据文件路径在磁盘上查找对应的文件数据块,并将文件的元数据信息返回给内核。内核将文件元数据信息返回给应用程序,比如文件描述符、文件大小等。应用程序再次调用read()函数请求读取文件内容。内核将读取文件内容的请求转发给文件系统服务进程。文件系统服务进程根据文件描述符定位到文件数据块,将数据读取到内存缓冲区,并通过IPC机制将数据返回给内核。内核将读取到的文件数据返回给应用程序。
微内核的应用及优缺点
优点: 高可靠性和可扩展性:关键内核功能最小化,减少内核代码的复杂度和错误概率。各服务进程相互隔离,一个服务进程的故障不会影响整个系统。可以根据需求有选择地集成所需的服务模块,提高系统的可定制性。 高安全性: 内核与服务进程间的特权级隔离,提高了系统的安全性。可以有针对性地增加可信服务模块,满足关键系统的安全需求。 高实时性: 关键实时任务可直接在内核中运行,不受其他服务模块的影响。内核功能最小化,上下文切换开销较小。 良好的可移植性: 微内核结构清晰,便于移植到不同硬件平台。服务模块相对独立,便于跨平台移植。
缺点: 性能损耗:服务进程间的通信会带来一定的性能开销。部分功能从内核空间移到用户空间会影响系统性能。 设计复杂度:微内核设计需要解决进程间通信、资源管理等复杂问题。需要仔细权衡哪些功能放在内核中,哪些放在用户空间。
说到微内核,就不得不提到宏内核
宏内核是一种传统的内核结构,它将进程管理,内存管理等各项服务功能都放到内核中去。 Linux、安卓都是比较典型的宏内核结构。当今主流商用系统Windows、MacOSX都属于混合内核。 微内核架构模式实现了模块化解耦,不同设备的弹性部署。
结语
鸿蒙系统分布式架构能让你在使用某个APP软件的时候,比如看视频,可以把屏幕随意切换到电视、电脑、手机、平板、投影仪等任何一个设备的界面上。可以在手表手机等任意一台设备上操作所有的设备,岂不是很爽,对于比较懒的同学是很大的福音,例如作者本人
作者:洞窝-王有为
“本文正在参加华为鸿蒙有奖征文征文活动”