精华内容
下载资源
问答
  • 嵌入式软件架构
    2021-04-12 21:17:36

    嵌入式软件架构师
    Base上海/深圳
    岗位职责:
    1.收集并分析市场和产品需求,完成架构设计;
    2.制定相关技术演进的roadmap,以及实施计划;
    3.带领团队设计并开发复杂异构的操作系统以及多媒体系统解决方案,满足不同应用场景的需求;
    4.深入理解产品,参与产品的整个生命周期的开发过程,包括需求定义、设计、实现、测试、生产、售后等;
    5.制定和改善软件的开发流程;
    6.跟踪嵌入式领域最新的技术发展,对团队进行技术指导。
    任职要求:
    1.至少是EE,CE,CS或同等专业的硕士,至少6年以上的开发经验,以及1年以上架构师经验;
    2.深度参与至少1款产品的架构设计,对于设计简单、高复用、高扩展、高可靠、高性能、低功耗的架构有深入理解和体会;
    3.丰富的嵌入式软件开发经验,如:操作系统(RTOS、Linux、Android)、安全、媒体链路、GPU等;
    4.深入理解SoC架构,以及系统优化方法,如NEON、DSP、GPU等;
    5.具备较强的开发和编程实践能力,以及良好的质量意识;
    6.至少参与过一款产品的敏捷开发实践,如:Scrum、Kanban等;
    7.良好的沟通协调能力,以及较好的驱动力;
    8.良好的学习能力及团队领导力,喜欢挑战。

    更多相关内容
  • 嵌入式软件架构设计

    2019-03-31 10:32:52
    对于电机控制的数字信号处理器的嵌入式软件架构分析设计
  • 提起嵌入式软件设计,传统的印象是单片机,汇编,高度依赖硬件。传统的嵌入式软件开发者往往只关注实现功能本身,而忽视诸如代码复用,数据和界面分离,可测试性等因素。从而导致嵌入式软件的质量高度依赖开发者的...
  • 比较全面的阐述嵌入式系统软件架构设计的资料,pdf版本,文字版,完整无广告。 本课程是针对嵌入式软件开发的特点,讨论架构设计的思路和方法。试图给大家提供一种思想,启发大家的思维。框架,自动化代码生成和...
  • 嵌入式软件架构

    千次阅读 2022-02-19 16:19:27
    嵌入式软件架构嵌入式软件架构嵌入式软件架构三 1、本文通过学习嵌入式系统的分层思想结合自身工作中的经验分享以NB-IoT模块为例的分层思想,一般在系统设计中可将系统按照业务功能分为功能模块,也就是分为子...

    前言: 本文是通过学习韦东山老师的嵌入式开发框架系列课程第四课,主要说明各个任务、各个系统直接如何分层实现,让整个系统实现双向解耦,即纵向、横向解耦,这样实现的代码后期维护起来非常方便,代码可读性也很强,扩展性非常好。
    韦东山老师视频学习链接

    嵌入式软件架构一
    嵌入式软件架构二
    嵌入式软件架构三
    1、本文通过学习嵌入式系统的分层思想结合自身工作中的经验分享以NB-IoT模块为例的分层思想,一般在系统设计中可将系统按照业务功能分为功能模块,也就是分为子系统或者模块,再将模块进行横向分层,可分为驱动层、中间管理层、业务逻辑层
    2、驱动层主要实现板级操作,比如硬件初始化、数据收发的配置方法等。
    3、中间管理层主要实现此功能模块的常见业务,比如NB-IoT设备中间层需要提供被业务层调用的初始化,此初始化会调用驱动层的硬件初始化,这一层屏蔽了同一类模块不同品牌或者不同芯片厂家的差异,业务逻辑层不关心到底用的是什么型号的,就只知道我调用你提供的接口我能够实现我的业务。比如NB模组现在市面上有很多中信号,有移远的,有方的,不同厂家可能驱动不一样,那我们就实现不一样的驱动,具体最终使用了哪一个,就在中间管理层来调用。
    4、业务逻辑层主要调用中间管理层提供的标准的API来实现功能即可;
    5、这样将来如果业务有变动,那么只改动业务逻辑层,而中间层管理层及以下都不需要改变,若模组厂商更换了,需要给新的模组增加驱动,将新的驱动注册到中间管理层中,而中间管理层和业务逻辑层都不需要改变。这就是分层的好处。
    6、关于NB模组涉及到了数据收发,与串口驱动有数据交互,为了方便移植,屏蔽了MCU的差异,所以此时又引入了适配层,适配层主要的作用是承上启下,上面将命令封装成模组想要的AT指令,下面调用串口驱动进行数据收发。这样就完全解耦了,移植的时候只需要根据不同的芯片选择不同的串口驱动方法。
    7、适配层的头文件如下:

    #ifndef _MIDAT_H_
    #define _MIDAT_H_
    
    #define MAX_STR_LEN		60
    #define MAX_BUFF_LEN	60
    #define MAX_RSP_LINE	2
    
    #define AT_OK_RSP		"OK"
    #define AT_ERR_RSP		"ERROR"
    #define AT_ZERO_RSP		"0"
    #define AT_AUTO_RSP		"AUROCONNECT,TRUE"
    
    typedef enum
    {
    	AT_TEST_REQ = 0,		//AT测试请求
    	AT_READ_REQ,			//AT读请求
    	AT_SET_REQ,				//AT设置请求
    	AT_EXECUTE_REQ			//AT执行请求
    }AT_REQ_TYPE;
    
    typedef struct
    {
    	char data[MAX_STR_LEN];
    }RSP_LINE;
    
    typedef struct
    {
    	RSP_LINE Line[MAX_RSP_LINE];
    }AT_RSP_DATA;
    
    //AT模块系统初始化
    int MID_ATSysInit(INTU8 Chn,INT8U Bps);
    //AT模块发送扩展命令
    int MID_ATSendExtCmd(INT8U Chn,INT8U Type,char *pFun,char *pData,int Len);
    //AT基本格式命令
    int MID_ATSendBaseCmd(INT8U Chn,char *pFun,char *pData,int Len);
    int MID_ATRequstCmd(INT8U Chn,INT8U Type,char *pFun,char *pSnd,int SndLen,AT_RSP_DATA *pRsp,int Time);
    int MID_ATRecvCmd(INT8U Chn,AT_RSP_DATA *pRsp);
    
    
    
    #endif 
    

    8、驱动层的头文件如下:

    #ifndef __DRVNBIOT_H__
    #define __DRVNBIOT_H__
    
    //定义BC35端口
    
    #define BC35_PWR_EN_DIR		P1DIR
    #define BC35_PWR_EN_OUT		P1OUT
    #define BC35_PWR_EN_BIT		BIT1
    
    //定义BC35的操作方式
    #define BC35_PWR_SET_DIR	BC35_PWR_EN_DIR |= BC35_PWR_EN_BIT
    #define BC35_PWR_ON			BC35_PWR_EN_OUT |= BC35_PWR_EN_BIT
    #define BC35_PWR_OFF		BC35_PWR_EN_OUT &=~BC35_PWR_EN_BIT
    
    
    //NB电源开关控制
    int DRV_NBIOTPower_Switch(enPowerSwitch pFlag);
    //NB复位
    int DRV_NBIOTReset(void);
    
    int DRV_NBIOTSetProperty(UART_BPS Bps);
    //AT发送扩展格式命令
    int DRV_NBIOTSendExtCmd(INT8U Type,char *pFun,char *pData,int Len);
    //AT测试命令请求
    int DRV_NBIOTRequstCmd(INT8U Type,char *pFun,char *pSnd,int SndLen,AT_RSP_DATA *pRsp,int Time);
    //接收数据
    int DRV_NBIOTRecvCmd(AT_RSP_DATA *pRsp);
    //驱动系统初始化
    int DRV_NBIOTSysInit(INT8U UartChn);
    
    #endif
    

    若想获取完整的NB-IoT的驱动代码,请点此处下载。

    展开全文
  • 嵌入式系统软件架构设计
  • 嵌入式软件架构

    2014-08-12 13:36:06
    基于时间片 优先级 消息 状态机的软件架构 我的项目一直用的架构 不好你来骂我
  • 嵌入式软件架构的设计

    万次阅读 多人点赞 2019-02-18 22:00:35
    嵌入式软件架构的设计 大多数嵌入式程序员学习编程,都是从开发板的附带例程开始。之后工作也会继续参考那些例程,很多编程习惯、方式也会受之影响。 其实开发板式的编程方式与工作中实际需求的并不完全一致。 ...

    嵌入式软件架构的设计

    大多数嵌入式程序员学习编程,都是从开发板的附带例程开始。之后工作也会继续参考那些例程,很多编程习惯、方式也会受之影响。

    其实开发板式的编程方式与工作中实际需求的并不完全一致。

    开发板的通常卖给初学者,注重“即插即用”,兼容各种模块,讲究功能的全面而不讲究性能、效率、成本、功耗等。很多时候为了兼容各种型号IC或者显示屏之类,程序累赘,逻辑混乱。开发板的程序往往是一个人完成,不需要讲究多人合作,这也影响了其编程方式。

    实际工作中,开发一款产品,需要讲究成本(物料,开发,加工),稳定性,功耗(比如电池产品)。通常,由于项目开始的时候,往往没有明确的需求,或者在确认需求后却由于种种原因多次更改需求,为了更好的开发,编程方式更侧重于程序的移植性(需求变化可能导致更改MCU等),可读性(换人还能快速接手),稳健性。

    当一个项目变得复杂,代码量很大时,往往需要一个良好的软件架构。否则很容易造成程序逻辑混乱,顾此失彼,移植困难,灵活性差。

    一、分层

    对软件进行分层,容易实现高内聚低耦合。

    分层的原则有:1单向逐层调用;2针对接口编程;3依赖倒置;4封装变化。

    分层数目,太多会导致产生不必要的开销,太少又会导致系统分离不够,结构不合理。

    下图为安卓系统的软件层次体系

    二、三层架构

    回顾一下,软件开发流程一般为分为下面若干阶段:需求分析,概要设计,详细设计,编码,测试,交付验收,维护。

    这里必须明白一点,包含单片机开发的项目一般都不会是纯粹的软件项目,甚至单片机软件本身都不一定是项目最重要的一部分。此类项目一般还会包括机械结构设计,平面设计,交互设计等等。

    一个项目的生命周期,一般由四个主要阶段构成:概念阶段,定义阶段、开发阶段和结束阶段。

    嵌入式软件工程师,通常会在定义阶段开始参与,协助主管做项目可行性分析。立项之后,再作需求分析。然而问题往往出现在这里:需求不明确,或者需求随意更改。这里不要说什么职责,责任范围,问责之类,毕竟理论是一回事,实际又是一回事。比如老板空降一个特别需求,主管也只能往下扔,你倒是敢向老板问责?

    所以,为了更好地完成任务,一个灵活而合适的软件架构,是非常必须的。

    一般使用单片机(比如STM32)开发的项目,分层数目为3比较合适。从下到上,分别为硬件驱动层(底层)、模块功能层(中间层)、业务逻辑层(顶层)。

    硬件驱动层:包括MCU片内资源驱动代码与外部各类IC的底层驱动代码,MCU片内驱动代码与IC驱动代码最好也能各自保持独立。向上提供API接口。

    模块功能层:隔离顶层与底层,实现与提供顶层所需的API接口。

    业务逻辑层:具体业务逻辑代码,也可以说是应用层。

    构建工程文件时,为各层建立单独文件夹,而MCU库,操作系统代码,文件系统代码,USB库,GUI系统代码等等独立部件也要单独设立文件夹。这有利于需要时方便地更换或者删除、添加。

    在编程时,要遵循上面的几个分层原则。分层有时会导致性能下降,对性能要求高的关键地方,可灵活运用函数指针,内联,甚至函数别名减少开销。

    假设,一个项目原本只需要显示静态图片,后来需求更改,还需要播放视频。之后选择修改方案:更换MCU,使用更大外置存储器。

    那么,1.底层,我们只需要将原来的MCU相关代码与存储器IC驱动替换掉。2.中间层,添加视频播放相关API函数。

    这样原来的代码大多还能复用,节省不少时间。

    假如需求不变,只是更换一些功能IC(比如考虑成本,或者断货,或者新出的更好IC),甚至只需要更换硬件驱动层相关 IC文件即可。

    三、举例

    下面以一个实际项目为例做参考。

    某项目用到显示屏显示网络数据。以显示模块为例,解析3层架构的运用。假设显示屏驱动为st7789,MCU采用FSMC方式st7789,定时器pwm控制背光。

    下面只是说明显示模块部分。

    1.硬件驱动层(底层):两个c文件以及对应头文件:单片机内部资源驱动文件mcu_bsp_drv.c,st7789驱动文件lcd_drv.c 。

    mcu_bsp_drv.c,包括所有的各个功能模块所需要的MCU资源的初始化驱动代码,并且每个模块只用一个函数并且以_mcu_init结尾。这类函数一般只用一次,不要怕又臭又长,但必须要有详细的注释说明。显示模块初始化函数命名为lcd_mcu_init();

    lcd_drv.c,这实际上是st7789的驱动文件,为什么不命名为st7789.c呢?因为如果更换了驱动IC,也不需要修改中间层的头文件包含代码。对于显示模块,一般需要提供一下接口:初始化函数,画点函数,单色方块填充函数,数据填充函数,显示打开关闭函数,背光控制函数。命名方式为lcd_drv_xxx()。这些函数在lcd_drv.h中声明,为中间层显式提供API;

    2.模块功能层(中间层):lcd_api.c以及对应头文件

    中间层实现显示相关函数:初始化函数,背光控制函数,各种几何图形(直线,圆,方框等)绘制函数,各种控件(窗口,按钮等)绘制函数,假如使用了第三方GUI系统,这些就不需要自己实现了。

    3.业务逻辑层(顶层):这一层与具体业务有关,也是程序员最花时间与精力的一部分。如果业务复杂,还可以细化分层。

    展开全文
  • 嵌入式软件在需求规划、架构设计、变量定义、数据存储、显示界面设计、报警设计时,都可能会有多个同类的内容在系统运行时间的先后、存储空间的占用、显示区域的布局等方面相冲突。一旦冲突起来,比如两个变量的数值...
  • 浅谈嵌入式软件架构思想

    千次阅读 2019-09-23 17:36:41
    我从事嵌入式软件开发有6,7个年头,bsp,驱动,应用软件,android hall,framework等都有涉猎。平时除了关注嵌入式行业的发展,也多少对Web,后台服务端,分布式等方向的技术有一些关注。 近期有萌生换个行业...

     

    我从事嵌入式软件开发有6,7个年头,bsp,驱动,应用软件,android hall,framework等都有涉猎。平时除了关注嵌入式行业的发展,也多少对Web,后台服务端,分布式等方向的技术有一些关注。

     

    近期有萌生换个行业方向的想法,想做做后台服务器相关的开发,由于之前工作中并没有这方面的实际需求,只是自己平时关注,了解了些知识,比如:NIO,epoll,ngnix,zeromq,libevent,libuv,高并发,分布式,redis,python,tornado,django,涉猎比较杂,都了解个皮毛,不精。意外的是屡屡被互联网行业鄙视,面试机会都寥寥无几。

     

    此时我想到底是什么问题呢,难道嵌入式出身的已经这么不受待见了吗?想当初,嵌入式,驱动开发,可是趋之若鹜的行业(有点夸张,不过8,9年前嵌入式可是听着比做java web的要牛逼些哦)

     

    问题总是有原因的,我说下自己的理解:

     

    嵌入式是否真的高大上之为什么没有嵌入式软件架构师?

     

    打开各种招聘网站,搜索架构师,会出现各种系统架构师,web架构师,后台服务端架构师等等,但是唯独很难看到嵌入式软件架构师。嵌入式软件不需要架构吗,驱动不需要架构吗?答案是当然需要,不过为什么没有这方面的职位?

     

    我的看法:目前国内的嵌入式开发主要分为嵌入式底层开发和嵌入式应用开发,嵌入式的底层开发一般叫做驱动开发,或者bsp开发,有时也有称之为linux内核开发,名字听着都很高大上的感觉。

     

    这么高大上的名字为什么没有架构师呢:linux kernel的架构师是linus等一众linux kernel开发维护者,因为本身linux kernel或者操作系统就是一个通用的平台,解决通用的问题,linux开源届的大牛都已经制定好了架构规则,留给可发挥的地方并不多,大部分工作只需要按照规则框架填充就可以了,而且以目前国内大部分公司的业务需求,只是在做外围设备的集成,嵌入式平台的porting,搭建裁剪,业务需求完全不会超过kernel里提供的功能范围。导致没有什么新的架构需要开发人员去设计,实现。那嵌入式bsp开发人员都在做什么:除了调试多种多样的外设,替硬件擦屁股,就是解些稳定性的bug了(这里对具体工作不详细描述了,调试外设只会增加一些经验,增加广度,对提高深度贡献不大,只是按不会调试-》会调试-》调试的快这个路线发展,而解稳定性问题确实是需要一些积累经验)

     

    而嵌入式上的应用开发,一般业务逻辑比较简单,被很多人忽略,所以招聘方也会感觉没有什么必要找架构师级别的了。

     

    至此感觉嵌入式行业的确不需要架构师,被互联网行业的鄙视也没什么大惊小怪的。

     

    但的确是这样子的吗?对于嵌入式底层的开发,有能力对kernel,驱动架构提出架构层优化的,国内的开发人员应该不多,所以对于大部分普通人,还是不要“妄想”做Linux kernel的架构师了(当然我相信国人中一定存在有这个能力的大牛),发现,解决一些bug,到更靠谱些。

     

    那么对于嵌入式应用层的开发,我们真的不需要架构吗?

     

    以自己的实际经历讲述下曾经对一个嵌入式设备应用软件的架构设计和优化:

     

    我曾经接手过一个项目,项目采用单进程多线程的模型,项目中包括几个模块,以a, b, c, d,e代表。这个项目的业务逻辑决定这几个模块有不少关联。

     

    例如:最初的设计中a模块是一个状态监测模块,它会基于监测到的状态调用b,c模块的接口实现一些功能(多线程的好处就是直接调用很方便,所以开发人员大多这么干,简单粗暴),但是需求总是千变万化,加入一个f模块,f模块也需要对a模块监测的状态进行一个处理,按照之前的套路,完成这个功能分两步:1,在f模块提供个接口,2,在a模块中调用该接口。至此新需求已经“完美”的解决了。

     

    前面提到需求总是千变万化的,新的需求又来了,客户提出定制需求,需要加入另一个g模块,同样处理a模块监测的状态,但是该定制需求不需要刚刚加入的f模块,此时最简单粗暴的方式是,定义一个宏,区分该定制需求和之前的通用需求,build两个程序版本。这样的做法看似简单,但后面如果定制需求逐渐增多,维护这么多定制版本程序就是个噩梦,代码管理和通用性也会是很大的问题,同时代码中充斥着对不同宏定义的差异化处理,#ifdef xxx;do_something;#endif比较好的做法是加入设备型号版本的动态监测,用一个build程序版本动态支持所有的定制需求,这样减少了对不同build程序的维护。但是这种做法只解决build程序的版本维护工作,没有解决宏定义差异化处理的问题,只是会将之前的宏判断,改为动态设备版本号判断,如果这些差异化的判断只集中在一处进行,也不会引起大的复杂化的问题,但显然这个是不好保证,有可能这些差异化的处理会蔓延到整个项目的各个角落,这样项目维护起来就会变成一场噩梦。

     

    不需要什么高深的软件思想,大部人都会想到把差异化的部分提取出来,放在一个统一的地方集中管理,对差异化的修改只集中在这个统一管理的地方。

     

    通用做法就是采用callback设置钩子,然后在callback中定制差异化的需求,对callback的处理做差异化的配置,对应到上面例子,就是在a模块添加一个钩子,然后在系统初始化时,根据设备版本号的不同,差异化定制callback处理函数,同时要将这些定制callback处理函数放在同一地方处理,否则仍然分散在各个角落里就没有意义(前一种方式不放置钩子是无法将这些差异化配置放在一起的),这样处理带来的另外一个好处是,我们对功能性需求的改变,不会影响到a模块的处理,也就是我们添加功能,不需要修改a模块的代码了(前一种方式要修改a模块的调用流程),这样也就实现了一个模块的分离。

     

    至此第二种的方案的架构(其实也谈不上架构了)相比第一种方案已经有了不少提升,至少让开发人员稍微轻松了些,对于其他定制需求,开发人员之需要修改这个callback处理,关注差异化部分就可以了。

     

    软件是需要不断进化的,第二种方案是最优解吗,当然不是,还有优化空间吗?

     

    下面先跑个题,谈谈多线程/多进程模型的优缺点,主要谈多进程的优点了:

    教科书上的解释就不提了,首先我对大的项目是推崇多进程模型,无关性能,主要原因有:

     

    模块的解耦:很多开发人员维护开发的多线程模型项目应该都多少会存在下面的问题:跨模块间的直接调用,如果不相信,好,你的项目一定是分模块的吧,现在随机的删掉一个模块,build下看能build通过吗(只需要build不需要运行),我相信大部分情况下一定会遇到某个函数调用,某个全局变量找不到的情况,这种情况说明你的模块间存在强耦合了。由于多线程天然的优势,地址空间的相互可见,导致直接调用十分容易,很多经验尚浅的工程师,很容易就写出直接调用的简单粗暴的接口,如果遇到个static接口的函数,图方便也会把static去掉,直接拿过来用了。这样整个工程随着功能不断的添加,模块间的交叉越来越多,耦合越高。

     

    而我之所以推崇多进程的原因就是,多进程能从物理上隔绝了这种“方便”的通讯方式,导致在想实现一个模块交互时,会多思考下这个交互是必要的吗,如果是必要的,则会进一步思考接口定义是否简单明了(因为进程间的通讯相对会麻烦些,开发人员会本着能减少交互,明确接口的想法去仔细考虑接口,协议的定义,否则折腾的是自己了),这如同人生,如果一直顺风顺水,人们可能不会想太多,思考太多,而如果道路上有些坎坷,则会有另一种感悟吧。

     

    所以我的想法是多进程的模型会逼迫你去更多的思考想程序的设计,物理上减少模块的耦合。

     

    抽象通用组件,分离通用功能和业务逻辑功能:当把一个多线程模型修改为多进程模型的过程中,经常会发现有些接口代码重复的出现在多个进程模块中,因为之前接口函数是在一个进程空间,大家都可以直接调用的,比如接口A被模块a,b调用,模块a,b分离为两个独立的进程后,接口A需要在a,b中分别实现了,无需解释,重复代码这个在软件工程中是大忌,必须消除。做法也很简单,将这些被多个模块调用的接口分离处理做成lib,供其他模块调用,当你完成这部分工作后,你发现了什么,是不是剥离的接口,可以作为整个项目的通用组件存在了,完美的情况下,lib下的代码是通用基础组件,各个模块中是独立的业务处理模块。

     

    方便定位问题:多线程模型中当又一个线程异常退出,会导致整个进程退出,当然通过一些crash信息,可以定位是那个线程死掉,但如果这些线程模块是由多个小组,人员维护,当整个进程崩溃掉后,如何判断由那个小组解决,会是一个大的问题,而且有时还会出现的现象是挂在一个线程,但其实是另外一个线程模块引起的(耦合的祸端),遇到这种情况,难免出现小组间的扯皮,推诿。(自信的工程师都认为我的代码没有问题)

     

    而如果采用多进程的模型,好吧,你的服务进程挂了,你自己找原因吧,没什么可争辩的了。

     

    方便性能测试:多线程种单个线程的资源占用不是很好查看(至少有些嵌入式系统没有完善的命令),当整个进程资源消耗很高时,如何判断定位时那个模块线程的问题,同3一样难以抉择,而如果是多进程的模型,谁的进程占了好多资源,谁就去查下吧,其实这个还是个颗粒度的问题,同样的系统,划分成多个进程,单个进程的复杂度一定比只有一个进程的复杂度低的多,复杂度降低,也就更容易定位查找各种问题。

     

    分布式部署:互联网行业一直强调的分布式,云啊什么的,嵌入式行业就很苦逼了,貌似不需要什么分布式吧,其实也对,大部分情况下,嵌入式采用单芯片,独立运行,分布式遇到的很少。但如果万一那天你在一个设备中,将本来一个芯片完成的功能分散到两个芯片中处理呢,多进程的扩展就容易的多了。

     

    这只是举个特殊的例子,其实嵌入式设备就是个分布式的行业,只是一开始就已经实现分离了,而不是从集中到分布式的路线发展起来的。

     

    方便公司的代码权限隔离:其实我鄙视这种做法,公司要相信自己的员工,但鉴于诚信在中国已经。。。。,做些隔离也无可厚非了。

     

    多线程模型下,前面讲到如果去除一个模块,你可能都不能build了,那么是要把所有代码暴露给所有的工程师吗,显然不能,所以各个模块只能提供库的形式了,不过我觉得将通用功能接口组织成通用库是正常的做法,而如果把和业务相关的模块也提供成库,就有点。。。。

     

    至此在补充一下,以上所有的优点,其实都不是很关键的点,都不能够让多进程有绝对的优势压倒多线程模型,只是从个人的角度觉得,多进程模型更能强迫工程师思考解决一些问题。(而这些问题有经验的工程师无论什么模型都会思考的)

     

    上面说了这么多,该考虑下把之前项目的例子改成多进程模型,否则就只是纸上谈兵了,下面开始:

    首当其冲的问题就是:选择多进程的通讯方式,多线程间的直接调用是不能用了,那么如何选择多进程的通讯方式呢?

     

    linux下提供很多ipc方式,此处不一一列举,对于非大数据量的控制,通讯消息的传递,比较好的方式是采用socket,本机上更多采用unix socket方式,(这种方式有什么好处?当你有需要把单一系统做成分布式系统时,优势就明显了)

     

    但是仅仅采用socket来实现前面例子的功能,同样会存在一些问题:

    还是前面的例子,首先说明前面我们优化后的第二种方案在多进程模型已经不能在继续使用了,原因比较简单,应该不需要解释。。。

     

    简单的做法即基于方案一,把直接调用改为socket通信(定义好通信协议即可),但是熟悉socket开发的工程师都清楚,开始socket通信要先进行一些前期的工作(主要就是连接,将两个模块关联起来),所以前面的例子会变成这个样子,模块a要和模块b,c建立连接,如果加入f模块,模块a还要和f模块建立连接。这样情况在心里画一张连接图就会发现好像我们织了一张蜘蛛网,节点间的关系错综复杂,而且和方案一一样,我们添加一个和a关联的模块,就要修改模块a的代码,而且这种情况比多线程模型还有繁琐复杂的多了。这种做法绝对是个噩梦。

     

    好吧如何解决,我想很多人一定想到了采用总线分发的方式。了解android系统开发的会想到binder,了解openwrt的会想到ubus,了解桌面会想到dbus,互联网行业的开发者一定也知道redis里提供的sub/pub模块。

     

    上面的binder,ubus等原理很简单,就是建立一个消息中心,构建一个转发路由模型,所有其他模块之间不直接交互,而是采用消息中心转发,路由,而如何决定路由规则,则采用订阅/发布的观察者模式来进行规则的定义。(嵌入式开发或者c语言开发者,经常会误以为设计模式是和面向对象语言关联的,是面向对象语言独有,虽然有很多大牛做了这方面的普及,但鉴于有些开发者的信息渠道比较闭塞,导致这种想法仍然十分盛行)

     

    基于这个模型,我们上面例子的需求就很好解决了,加入一个消息中心模块,所有需要通信的模块只同该消息中心模块连接,然后订阅自己感兴趣的事件,当事件发生时,只需要进行相应的处理就可以了。

     

    这样上面的模块b,c订阅模块a的事件,当模块a检测到某事件时,发布该事件,该事件先到达消息中心,在由消息中心转发给模块b,c,而对于新加入的模块f,也只需要订阅该模块,而不需要在修改到模块a的代码,使功能的扩展十分方便。

     

    同时对于前面提到的定制化开发同样得到了简化,如果定制化版本需要加入模块g,这样只需要定制化版本中将模块g作为一个独立进程启动,然后订阅模块a的事件即可,而定制版本和通用版的区别就在于是否启动模块g的进程,从而实现了软件工程的一个目标:功能的添加如同搭积木一样,只需要把一个模块插入(启动)或拔出(不启动)即可,功能的改变只局限在一个或某几个模块间,对主体框架不会有任何影响。

     

    以上大概描述了对一个项目需求逐步优化的过程,例子看似是基于嵌入式项目,但貌似对软件工程同样适用。

     

    来到互联网行业:

    查看下各大网站架构师对本网站技术架构变革分享的文章,首先提到的一般都是,基于业务将之前的一个应用服务器功能拆分,更加细化(比如电商对登录,注册,交易,商品,卖家等业务服务的拆分),然后将拆分出来的服务部署在多台服务器上,来提供并发。这里是否有些耳熟,和前面讲到的多线程到多进程的划分是否有相似呢。

     

    拆分后同样遇到通信的问题,此时很多消息中间件应运而生,比如阿里的duboo,简单了解下这些中间件的原理,无外乎订阅发布,RPC等机制,可以说大同小异,而难点在于协议的制定和性能处理的提升。

     

    在对照下互联网行业的负载均衡方案,仿佛那个负载均衡的前端也像一个消息中心了。

     

    上面说了这么多,只是想说明一个问题,软件的设计是相通的,基于的思想是相同的,虽然嵌入式行业的业务逻辑相对比较简单,但其实在仔细思考后,仍然会有很多架构上的改进,设计。

     

    但是让我感到悲哀的是,有些嵌入式开发者,鉴于业务逻辑的简单,感觉采用一些不那么好的处理方式也能解决问题,不去思考如何去优化,改进。比如上面例子的方案一,如果在定制需求不多的情况下,维护起来也没太大问题,即使定制需求多了,再招些初级程序员也能维护的过来,一个人一套代码负责一个项目的公司也不是不存在。

    同样互联网行业和嵌入式行业也不应该存在一个不可以逾越的高墙,我们更应该关注的是通用的软件工程思想。 

     

    免责声明:本文系网络转载,版权归原作者所有。如涉及作品版权问题,请与我联系,将根据您提供的版权证明材料确认版权并删除内容。

    展开全文
  • 近公司新招了一个做嵌入式软件开发开发的童鞋,该童鞋是从上海的某一个上市公司出来的,因为我们这边人手不够,因此把他安排了去负责一个新产品的研发,前期让他负责加速度计、NB-IOT、舵机、外置Flash的功能测试,...
  • 嵌入式软件架构设计之分层设计

    千次阅读 2020-01-15 18:00:47
    在招聘网站搜索架构师,会出现各种系统架构师:web架构师,后台服务端架构师等等,但是唯独很难看到嵌入式软件架构师。嵌入式软件不需要架构吗,驱动不需要架构吗? 答案当然 是 需要,不过为什么没有这方面的职位?...
  • 近公司新招了一个做嵌入式软件开发开发的童鞋,该童鞋是从上海的某一个上市公司出来的,因为我们这边人手不够,因此把他安排了去负责一个新产品的研发,前期让他负责加速度计、NB-IOT、舵机、外置Flash的功能测试,...
  • 【架构】嵌入式软件架构设计 模块化 & 分层设计

    千次阅读 多人点赞 2020-01-22 23:08:25
    起因 继前一篇介绍了一些别人家的代码架构之后,其实最近实践了一下,还是有些感悟。又参考了一些文档,觉得还是要记录一下,最近整理代码的心得。...随便上百度搜了一张嵌入式软件架构图为例...
  • 要做到嵌入式应用的代码逻辑清晰,且避免重复的造轮子,没有好的应用架构怎么行。如果没有好的架构,移植将会是一件很痛苦的事情。如果没有好的架构,复用是最大的难题,没法更大限度的复用原有的代码。如果没有好的...
  • 嵌入式软件架构

    2022-02-21 17:11:38
    嵌入式软件架构嵌入式软件架构嵌入式软件架构嵌入式软件架构四 1. RTOS的内核组成部分 以RT-Thread内核为主介绍RTOS内核的组成; 内核是操作系统最基础最重要的部分,内核处于硬件层之上。 RT-Thread内核...
  • 第三部分是关于嵌入式软件的介绍,包括设备驱动、操作系统及中间件和应用软件;第四部分介绍了嵌入式系统的设计与开发。此外,书中还包括大量图和计算机代码,帮助读者理解嵌入式系统的理论知识。
  • 改进的嵌入式软件架构及其应用层开发模式.pdf
  • #资源达人分享计划#
  • 基于此,提到简单嵌入式系统的软件架构,我脑海中立马浮现这样的画面: 看到这张图,不同的人,可能会有不同的感受:有的高手能一眼看破,能马上进行万千补充、引申;有的会心领神会,从而期待后面的内容;而有的,...
  • 下面文档系本人开发的流媒体数字会议系统中控机的软件架构,有写的不好的地方,欢迎拍砖 1 .引言 1.1编写目的和使用范围 1.1.1 编写目的 本文档用来确定Nios的软件架构,以便帮助软件工程师更好的完成中控机的业务...
  • 嵌入式为什么没有嵌入式软件架构师?

    千次阅读 多人点赞 2018-07-02 15:13:13
    我从事嵌入式软件开发有6,7个年头,bsp、驱动、应用软件、android hall、framework等都有涉猎。平时除了关注嵌入式行业的发展,也多少对Web、后台服务端、分布式等方向的技术有一些关注。 近期有萌生换个行...
  • 此文章适用于开发经验丰富,想在架构上提高自己的嵌入式开发工程师。这篇文章能从一定的高度上审视嵌入式的总体软件架构

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 72,824
精华内容 29,129
关键字:

嵌入式 软件架构