当前位置:首页 > 嵌入式培训 > 嵌入式学习 > 讲师博文 > SylixOS热插拔概述

SylixOS热插拔概述 时间:2018-09-28      来源:未知

SylixOS热插拔概述

1. 热插拔系统简介

1.1 热插拔系统

    热插拔设备指支持带电操作的一类设备,允许用户不关闭系统、不切断电源情况下取出或更换设备。热插拔系统用于管理系统中所有热插拔设备的插入、拔出状态,从而能够让系统内部自动完成此类设备的创建、删除工作而无需用户手动处理。同时,热插拔系统还会收集热插拔相关信息,供应用程序使用。SylixOS 中有一个名称为"t_hotplug"的内核线程,设备的热插拔状态通过事件的方式报告给该线程。系统中还有一个名为"/dev/hotplug"的虚拟设备,它负责收集相关热插拔消息,应用程序可通过读取"/dev/hotplug"设备,获得自己关心的热插拔消息。

1.2 实现原理

    在 SylixOS 中,可以使用如下两种方法获得热插拔事件:

    1.中断产生,例如"mini2440"开发板上SD卡热插拔操作,当SD卡插入或者拔出时会触发引脚中断,中断服务程序中会根据读取的引脚状态,产生相应的热插拔事件,将需要处理的事件加入到热插拔工作处理队列,等待内核线程处理。

    2. 轮询检测,当有些热插拔设备不产生中断(没有插拔中断功能的设备),则需要轮询检测某些事件标志。设备驱动程序需要将检测函数和参数注册到"hotplug"循环检测链表中,"t_hotplug"内核线程会定时调用检测函数,轮询检测函数会产生相应事件,等待内核线程处理。

    当设备热插拔操作结束时,会产生一条热插拔消息存入缓存区,应用层程序可以通过读取虚拟设备"/dev/hotplug"(热插拔设备驱动创建),从缓存区中获取热插拔消息。

2 读取热插拔消息

    前文提到,热插拔事件产生后会产生热插拔消息,存放在"/dev/hotplug"设备的缓存区中,则应用层可以对"/dev/hotplug"设备进行读取,获得应用层需要的热插拔消息。由于"/dev/hotplug"设备是字符设备,所以应用层可以对设备进行open、read、write、ioctl、close等操作,获得应用层所需的热插拔消息。

2.1 获取热插拔消息实例

    SylixOS 中定义了当前常见的热插拔设备消息,如 USB、SD卡、PCI等,用户也可以自定义添加。此外,还有网卡的连接与断开等与热插拔行为相似的消息。

    下面举例说明如何获取网卡热插拔消息(本例程序是在mini2440开发板上测试运行),测试代码代码清单2-1所示。 

代码清单 2-1

[cpp] view plain copy print?

1. #include <stdio.h>  

2. #include <string.h>  

3.

4. #define      MSG_LEN_MAX                (534)  

5.

6. int main (int  argc, char  *argv[])  

7. {  

8.     UINT8   pucMsgBuff[MSG_LEN_MAX];  

9.     INT     iFd;  

10.     INT32   iMsgType;  

11.     BOOL    bInsert;  

12.     ssize_t sstReadLen;  

13.

14.     CHAR   *pcDevName = NULL;  

15.     UINT8  *pucArg    = NULL;  

16.     UINT8  *pucTemp   = NULL;  

17.

18.

19.     iFd = open("/dev/hotplug", O_RDONLY);                             /*  打开hotplug虚拟设备         */  

20.     if (iFd < 0) {  

21.         fprintf(stderr, "open /dev/hotplug failed.\n");  

22.         return (-1);  

23.     }  

24.

25.     ioctl(iFd, LW_HOTPLUG_FIOSETMSG, LW_HOTPLUG_MSG_NETLINK_CHANGE);  /* ioctl 设置关心网卡热插拔事件 */  

26.     while (1) {  

27.         sstReadLen = read(iFd, pucMsgBuff, MSG_LEN_MAX);              /* 读取热插拔消息               */  

28.         if (sstReadLen < 0) {  

29.             fprintf(stderr, "read hotplug message error.\n");  

30.             close(iFd);  

31.             return (-1);  

32.         }  

33.         if (sstReadLen < 5) {  

34.             continue;  

35.         }  

36.

37.         /* 

38.          * 解析热插拔消息 

39.          */  

40.         pucTemp   = pucMsgBuff;  

41.         iMsgType  = (pucTemp[0] << 24) | (pucTemp[1] << 16) | (pucTemp[2] << 8) | (pucTemp[3]);  

42.         pucTemp  += 4;  

43.         bInsert   = *pucTemp ? TRUE : FALSE;  

44.         pucTemp  += 1;  

45.         pcDevName = (CHAR *) pucTemp;  

46.         pucArg    = pucTemp + strlen(pcDevName) + 1;  

47.

48.         printf("get new hotplug message >>\n"                         /*  打印热插拔消息             */  

49.                 " message type: %d\n"  

50.                 "device status: %s\n"  

51.                 " device name: %s\n"  

52.                 " arg0: 0x%01x%01x%01x%01x\n"  

53.                 " arg1: 0x%01x%01x%01x%01x\n"  

54.                 " arg2: 0x%01x%01x%01x%01x\n"  

55.                 " arg3: 0x%01x%01x%01x%01x\n", iMsgType,  

56.                 bInsert ? "insert" : "remove", pcDevName, pucArg[0], pucArg[1],  

57.                 pucArg[2], pucArg[3], pucArg[4], pucArg[5], pucArg[6],  

58.                 pucArg[7], pucArg[8], pucArg[9], pucArg[10], pucArg[11],  

59.                 pucArg[12], pucArg[13], pucArg[14], pucArg[15]);  

60.     }  

61.

62.     close(iFd);  

63.

64.     return (0);  

65. }  

    如代码清单2-1所示,程序实现了应用层读取网卡热插拔消息的功能,在开发板上运行该程序,当发生网卡热插拔操作时,会得到网卡热插拔消息,实验现象。

    通过分析代码清单2-1所示代码,用户在读取设备热插拔消息时应注意以下几点:

    1.以只读方式打开"/dev/hotplug"设备,SylixOS中热插拔消息在热插拔设备创建时产生,并且写入到设备中缓存区中。

    2.代码清单2-1中程序通过ioctl函数实现单独监听网卡热插拔消息的功能,应用程序可以根据需要设置ioctl函数中的参数来获取对应的消息。默认情况下是读取所有类型热插拔消息。

    3.代码清单2-1中read函数实现读取网卡热插拔消息的功能,读取消息后对获得的热插拔消息进行解析,然后输出打印。SylixOS中对热插拔消息格式进行特殊规定,格式分析参照2.2节。

2.2 热插拔消息格式

    由2.1节中读取网卡热插拔消息实例可知,在SylixOS中热插拔消息有规定的格式。下面对SylixOS热插拔消息格式进行分析。

消息的前4个字节标识了消息的类型。SylixOS中已经定义了USB键盘、USB鼠标、SD存储卡、SDIO无线网卡等热插拔类型。在实际的硬件平台上,设备驱动也可以定义自己的热插拔消息类型。

    第5个字节为设备状态,0表示拔出,1表示插入。

     从第 6 个字节开始,表示设备的名称,其内容为一个以'\0'结束的字符串,应用程序应该以此为结束符得到完整的名称。该名称为一个设备的完整路径名称, 如"/dev/ttyUSB0"、"/media/sdcard0"等。由于SylixOS中,一个完整路径名称的大长度为512,加上结束字符'\0',因此,dev name字段的大长度为513。

    紧跟着设备名称('\0'字符结尾)的是 4 个可用于灵活扩展的参数,均为4字节长度。这4个参数可适应不同设备消息的特殊处理。SylixOS未规定每个参数的具体用法和存储格式(大端或小端),完全由设备驱动定义。

    综上论述,一个热插拔消息的大长度为:4 + 1 + 513 + 4 + 4 + 4 + 4 = 534字节。

3 热插拔消息产生

3.1 网卡热插拔消息

     前文已经介绍了应用层如何获取热插拔消息,本章介绍SylixOS热插拔消息的产生流程。SylixOS中,热插拔消息在热插拔事件产生时产生,由热插拔设备驱动实现。

    下面以网卡热插拔为例,介绍网卡热插拔消息产生流程,。

在对网口进行必要的初始化后,将循环检测函数dm9000_watchdog注册到循环检测链表中,检测函数会根据网卡状态产生不同的热插拔消息,然后将热插拔消息存入缓存区。

3.2 模拟热插拔实现

    下面通过信号模拟热插拔事件,用信号SIGALRM模拟设备插入,用信号SIGUSR1模拟设备拔出。示例代码清单3-1所示:

代码清单3-1

[cpp] view plain copy print?

1. #define __SYLIXOS_KERNEL  

2. #include <SylixOS.h>  

3. #include <stdio.h>  

4. #include <string.h>  

5. #include <signal.h>  

6. #include <pthread.h>  

7. #include <unistd.h>  

8.

9. static char      *msg = "Dev";  

10.

11. void send_event (void  *arg)  

12. {  

13.     int signum = (int)arg;  

14.

15.     if (signum == SIGALRM) {  

16.         API_HotplugEventMessage(LW_HOTPLUG_MSG_ALL, 1, msg, 0, 0, 0, 0);  

17.     } else if (signum == SIGUSR1){  

18.         API_HotplugEventMessage(LW_HOTPLUG_MSG_ALL, 0, msg, 0, 0, 0, 0);  

19.     }  

20. }  

21.

22. void pullout_handler (int  signum)  

23. {  

24.     API_HotplugEvent((VOIDFUNCPTR)send_event, (void *)signum, 0, 0, 0, 0, 0);  

25. }  

26.

27. void insert_handler (int  signum)  

28. {  

29.     API_HotplugEvent((VOIDFUNCPTR)send_event, (void *)signum, 0, 0, 0, 0, 0);  

30. }  

31.

32. int main (int argc, char *argv[])  

33. {  

34.     int   i;  

35.

36.     if (signal(SIGALRM, insert_handler) == SIG_ERR) {  

37.         fprintf(stderr, "Install signal handler failed.\n");  

38.         return -1;  

39.     }  

40.     if (signal(SIGUSR1, pullout_handler) == SIG_ERR) {  

41.         fprintf(stderr, "Install signal handler failed.\n");  

42.         return -1;  

43.     }  

44.

45.     for (i = 0; i < 8; ++i) {  

46.         alarm(2);  

47.         pause();  

48.         kill(getpid(), SIGUSR1);  

49.     }  

50.

51.     return  0;  

52. }  

       本例利用信号模拟热插拔事件,运行2.1节中程序(注释掉ioctl函数,获取所有类型的热插拔消息),再执行代码清单3-1所示程序。

4 小结

     本文档介绍了SylixOS下热插拔系统实现原理,以网卡热插拔为例,分析热插拔消息产生流程。后通过信号模拟热插拔事件,打印出模拟的热插拔消息。

上一篇:OpenVPN 服务器搭建

下一篇:yocto编译总结

热点文章推荐
华清学员就业榜单
高薪学员经验分享
热点新闻推荐
前台专线:010-82525158 企业培训洽谈专线:010-82525379 院校合作洽谈专线:010-82525379 Copyright © 2004-2022 北京华清远见科技集团有限公司 版权所有 ,京ICP备16055225号-5京公海网安备11010802025203号

回到顶部