华为机试题 :和为 K 的子数组个数
2026/10/11 18:30:38
该项目是基于Linux嵌入式系统的智能电源监控设备,核心实现数据采集→内部通信→本地显示→远程上报全流程,以下结合代码拆解核心技术模块的基础原理与项目拓展实现。
项目核心技术工具/框架:
线程邮箱是生产者-消费者模型的经典实现,基于「环形队列 + 互斥锁 + 条件变量」解决多线程间的数据安全传递问题:
// 消息类型枚举(适配不同采集数据)typedefenum{MSG_METER_DATA=1,// 电表数据(电压/电流)MSG_TEMP_DATA,// 温度数据MSG_ALARM,// 报警数据MSG_NET_STATE// 网络状态}msg_type_t;// 通用消息体:兼容多类型数据typedefstruct{msg_type_ttype;// 消息类型time_ttimestamp;// 时间戳union{// 联合类型:节省内存,仅存储一种数据struct{floatvoltage;floatcurrent;}meter;// 电表struct{floattemperature;}temp;// 温度struct{intlevel;}alarm;// 报警struct{intonline;}net;// 网络}data;}message_t;#defineMAILBOX_SIZE64// 队列容量(固定大小,适配嵌入式内存限制)staticmessage_tmailbox[MAILBOX_SIZE];// 队列缓冲区staticinthead=0,tail=0,count=0;// 头指针(出队)、尾指针(入队)、元素计数staticpthread_mutex_tmtx;// 互斥锁staticpthread_cond_tnot_empty;// 队列非空条件(消费者等待)staticpthread_cond_tnot_full;// 队列非满条件(生产者等待)// 生产者:发送消息(如电表/温度采集线程调用)intmailbox_send(constmessage_t*msg){pthread_mutex_lock(&mtx);// 队列满则阻塞,直到有空闲空间while(count==MAILBOX_SIZE){pthread_cond_wait(¬_full,&mtx);}// 消息入队memcpy(&mailbox[tail],msg,sizeof(message_t));tail=(tail+1)%MAILBOX_SIZE;count++;// 唤醒等待的消费者pthread_cond_signal(¬_empty);pthread_mutex_unlock(&mtx);return0;}// 消费者:接收消息(调度线程调用)intmailbox_recv(message_t*msg){pthread_mutex_lock(&mtx);// 队列空则阻塞,直到有消息while(count==0){pthread_cond_wait(¬_empty,&mtx);}// 消息出队memcpy(msg,&mailbox[head],sizeof(message_t));head=(head+1)%MAILBOX_SIZE;count--;// 唤醒等待的生产者pthread_cond_signal(¬_full);pthread_mutex_unlock(&mtx);return0;}meter_task(模拟电压/电流采集)、temp_task(模拟温度采集),定时生产消息并发送到邮箱;dispatcher_task,持续从邮箱接收消息,处理滤波、报警逻辑,更新全局系统状态。mailbox_send_timeout),避免线程永久阻塞;MAILBOX_SIZE,通过动态内存分配实现队列扩容;嵌入式系统中多线程异步通信(如传感器采集、数据处理、设备控制线程间的解耦),相比管道/消息队列,更轻量、无内核态切换开销。
FrameBuffer(帧缓冲)是Linux内核提供的图形硬件抽象层,将显示设备(LCD/屏幕)抽象为一段可直接读写的内存区域:
mmap将显存映射到用户空间,无需操作硬件寄存器;void*pmem;// 显存映射后的用户空间指针structfb_var_screeninfovinf;// 屏幕参数(分辨率、位深)intinit_fb(char*devname){// 1. 打开帧缓冲设备(如/dev/fb0)intfd=open(devname,O_RDWR);// 2. 获取屏幕参数(分辨率、位深)ioctl(fd,FBIOGET_VSCREENINFO,&vinf);// 3. 映射显存到用户空间size_tlen=vinf.xres_virtual*vinf.yres_virtual*vinf.bits_per_pixel/8;pmem=mmap(NULL,len,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);returnfd;}draw_point(适配RGB888/RGB565格式);draw_rectangle(矩形)、draw_circle(圆形)、draw_h_line(水平线);draw_bmp(BMP图片显示)、draw_utf8_str(UTF-8中文显示,结合字模库);fb_task线程实时绘制设备状态(温度、电压、电流),报警时“ALARM”文字闪烁。// 绘制温度数据(报警时红色,正常时绿色)snprintf(buf,sizeof(buf),"TEMP: %.1f C",g_state.temperature);draw_utf8_str(&utf8_info,50,120,buf,g_state.temp_alarm?0x00FF0000:0x0000FF00,0);// 报警状态闪烁if(alarm_any){if(alarm_blink_on()){draw_utf8_str(&utf8_info,50,320,"STATUS: ALARM",0x00FF0000,0);}}else{draw_utf8_str(&utf8_info,50,320,"STATUS: NORMAL",0x0000FF00,0);}vinf.xres/vinf.yres动态调整绘制坐标,适配不同屏幕。MQTT(Message Queuing Telemetry Transport)是轻量级发布/订阅协议,基于TCP/IP,专为低带宽、高延迟、不可靠网络设计(物联网场景):
// MQTT服务器配置(阿里云IoT平台)#defineMQTT_ADDRESS"tcp://183.230.40.96:1883"#definePRODUCT_ID"Uherm6f889"#defineDEVICE_NAME"power_box"// 客户端初始化intmqtt_client_init(void){MQTTClient_create(&client,MQTT_ADDRESS,CLIENT_ID,MQTTCLIENT_PERSISTENCE_NONE,NULL);// 设置回调(连接丢失、消息到达、投递完成)MQTTClient_setCallbacks(client,NULL,connlost,msgarrvd,delivered);// 连接服务器(设置用户名/密码、保活时间)MQTTClient_connect(client,&conn_opts);// 订阅主题(接收平台回复)MQTTClient_subscribe(client,sub_topic,MQTT_QOS);return0;}// 发布设备状态(电压/电流/温度/报警)intmqtt_client_publish_state(constsystem_state_t*st){// 封装JSON格式Payloadsnprintf(payload,sizeof(payload),"{\"id\":\"%d\",\"version\":\"1.0\",\"params\":{""\"voltage\":{\"value\":%.1f,\"time\":%lld},""\"temperature\":{\"value\":%.1f,\"time\":%lld},""\"temp_alarm\":{\"value\":%s,\"time\":%lld}""}}",msg_id++,st->voltage,ts_ms,st->temperature,ts_ms,st->temp_alarm?"true":"false",ts_ms);// 发布消息intrc=MQTTClient_publishMessage(client,pub_topic,&msg,NULL);// 发布失败(断网):写入SQLite缓存if(rc!=MQTTCLIENT_SUCCESS){mqtt_cache_db_push(payload);mqtt_connected=0;return-1;}return0;}// SQLite缓存重连补发(mqtt_sqlite_cache.c)staticvoidmqtt_cache_flush_sqlite(void){charpayload[MQTT_PAYLOAD_MAX];while(1){// 从缓存取出最早消息intret=mqtt_cache_db_pop(payload,sizeof(payload));if(ret!=0)break;// 补发消息MQTTClient_publishMessage(client,pub_topic,&msg,&token);}}intmqtt_reconnect(void){// 重新连接服务器intrc=MQTTClient_connect(client,&conn_opts);if(rc!=MQTTCLIENT_SUCCESS)return-1;// 重连后补发缓存消息mqtt_cache_flush_sqlite();return0;}基于SQLite3实现消息本地持久化:
mqtt_cache_db_push将消息写入数据库,自动清理超过1000条的旧数据;mqtt_cache_flush_sqlite逐条取出缓存消息补发,保证消息不丢失。mqtts://(MQTT over TLS),防止数据窃听/篡改;项目对接阿里云IoT平台(主题格式:$sys/{PRODUCT_ID}/{DEVICE_NAME}/thing/property/post),可无缝拓展到华为云、腾讯云IoT平台,仅需修改主题格式和认证参数。
该项目是嵌入式物联网设备的典型落地案例,技术选型充分适配嵌入式系统“资源有限、低功耗、高可靠”的特点: