您的位置:首页 > 健康 > 美食 > 电商平台开发系统_有没有网站免费的_宣传推广方案_成都百度提升优化

电商平台开发系统_有没有网站免费的_宣传推广方案_成都百度提升优化

2025/4/2 10:20:09 来源:https://blog.csdn.net/weixin_43275558/article/details/146486861  浏览:    关键词:电商平台开发系统_有没有网站免费的_宣传推广方案_成都百度提升优化
电商平台开发系统_有没有网站免费的_宣传推广方案_成都百度提升优化

1、select接口简介

1.1 select接口使用用例

  select 是操作系统多路 I/O 复用技术实现的方式之一。

  select 函数允许程序监视多个文件描述符,等待所监视的一个或者多个文件描述符变为“准备好”的状态。所谓的”准备好“状态是指:文件描述符不再是阻塞状态,可以用于某类 IO 操作了,包括可读,可写,发生异常三种。

  select 在应用中使用的例子如下段代码所示。

#include <stdio.h>
#include <sys/select.h>int main (int argc, char *argv[])
{fd_set fdset;int ret;struct timeval timeout;char ch;timeout.tv_sec = 10;timeout.tv_usec = 0;for (;;) {FD_ZERO(&fdset);FD_SET(STDIN_FILENO, &fdset);ret = select(STDIN_FILENO + 1, &fdset, NULL, NULL, &timeout);if (ret <= 0) {break;} else if (FD_ISSET(STDIN_FILENO, &fdset)) {read(STDIN_FILENO, &ch, 1);if (ch == '\n') {continue;}fprintf(stdout, "input char: %c\n", ch);if (ch == 'q') {break;}}}return (0);
}

1.2 select函数原型分析

LW_API INT   select(INT                  iWidth, fd_set              *pfdsetRead,fd_set              *pfdsetWrite,fd_set              *pfdsetExcept,struct timeval      *ptmvalTO);
  • iWidth 为设置的文件集中,最大的文件号 + 1;
  • pfdsetRead 为关心的可读文件集;
  • pfdsetWrite 为关心的可写文件集;
  • pfdsetExcept 为关心的异常文件集;
  • ptmvalTO 为等待超时时间,LW_NULL 表示永远等待;
  • 返回值:正常返回等待到的文件数量,错误返回 PX_ERROR。

2、select 实现

2.1 内核中 select 实现

select 函数具体实现如下,主体可以分为 3 个部分:

  • 检查读文件集、写文件集、异常文件集,调用 ioctl 的 FIOSELECT 命令
  • 调用 API_SemaphoreBPend 接口进行阻塞
  • 被唤醒后,调用 ioctl 的 FIOUNSELECT 命令
LW_API  
INT     pselect (INT                     iWidth, fd_set                 *pfdsetRead,fd_set                 *pfdsetWrite,fd_set                 *pfdsetExcept,const struct timespec  *ptmspecTO,const sigset_t         *sigsetMask)
{......if (pfdsetRead) {                                                   /*  检查读文件集                */selwunNode.SELWUN_seltypType = SELREAD;if (__selDoIoctls(&pselctx->SELCTX_fdsetOrigReadFds, pfdsetRead, iWidth, FIOSELECT, &selwunNode, LW_TRUE)) {                      /*  遇到错误,立即退出           */iIsOk = PX_ERROR;}}....../*  开始等待,这里是 select 阻塞的根源。 一般会在驱动的中断处理函数中调用 wakeup_node ,去释放这个二进制信号量   */ulError = API_SemaphoreBPend(pselctx->SELCTX_hSembWakeup,ulWaitTime);                            /*  开始等待                    */if (pfdsetRead) {                                                   /*  检查读文件集                */selwunNode.SELWUN_seltypType = SELREAD;if (__selDoIoctls(&pselctx->SELCTX_fdsetOrigReadFds, pfdsetRead, iWidth, FIOUNSELECT, &selwunNode, LW_FALSE)) {                     /*  如果存在节点,删除节点       */iIsOk = PX_ERROR;}}......
}

  select 操作的一个重要数据结构,就是 “唤醒节点” ——LW_SEL_WAKEUPNODE

  select 函数允许程序监视多个文件描述符,这里的每一个文件描述符,对应一个“唤醒节点”。唤醒节点中一个重要的变量就是 SELWUN_hThreadId 线程 ID,记录了创建该等待节点的线程句柄(其实就是调用 select 接口的线程)。该数据结构通过 ioctl 接口,传递到设备文件描述符对应的设备驱动中,由设备驱动去维护、管理该唤醒节点。

/*********************************************************************************************************等待节点类型
*********************************************************************************************************/typedef enum {SELREAD,                                                            /*  读阻塞                      */SELWRITE,                                                           /*  写阻塞                      */SELEXCEPT                                                           /*  异常阻塞                    */
} LW_SEL_TYPE;/*********************************************************************************************************等待链表节点.
*********************************************************************************************************/typedef struct {LW_LIST_LINE            SELWUN_lineManage;                          /*  管理链表                   */UINT32                  SELWUN_uiFlags;LW_OBJECT_HANDLE        SELWUN_hThreadId;                           /*  创建节点的线程句柄          */INT                     SELWUN_iFd;                                 /*  链接点的文件描述符          */LW_SEL_TYPE             SELWUN_seltypType;                          /*  等待类型                   */
} LW_SEL_WAKEUPNODE;
typedef LW_SEL_WAKEUPNODE  *PLW_SEL_WAKEUPNODE;    

2.2 设备驱动的 ioctl 实现

  SylixOS 的 select 接口实现中,系统会调用到每一个 fd 对应的设备驱动的 ioctl 接口,并会调用到如下表所示的两个命令:

命令说明
FIOSELECT添加 SEL_WAKE_NODE 节点
FIOUNSELECT移除 SEL_WAKE_NODE 节点

  驱动中 ioctl 的 FIOSELECT 实现,通常会调用 SEL_WAKE_NODE_ADD 接口,向设备驱动中添加一个“唤醒节点”(也可以把它理解成“等待节点”)。以 gpio 驱动为例:

static INT  _gpiofdSelect (PLW_GPIOFD_FILE  pgpiofdfil, PLW_SEL_WAKEUPNODE   pselwunNode)
{......SEL_WAKE_NODE_ADD(&pgpiofdfil->GF_selwulist, pselwunNode);......
}static INT  _gpiofdUnselect (PLW_GPIOFD_FILE  pgpiofdfil, PLW_SEL_WAKEUPNODE   pselwunNode)
{......SEL_WAKE_NODE_DELETE(&pgpiofdfil->GF_selwulist, pselwunNode);......
}static INT  _gpiofdIoctl (PLW_GPIOFD_FILE pgpiofdfil, INT             iRequest, LONG            lArg)
{......switch (iRequest) {......case FIOSELECT:pselwunNode = (PLW_SEL_WAKEUPNODE)lArg;return  (_gpiofdSelect(pgpiofdfil, pselwunNode));case FIOUNSELECT:pselwunNode = (PLW_SEL_WAKEUPNODE)lArg;return  (_gpiofdUnselect(pgpiofdfil, pselwunNode));}......
}

节点的组织形式如下:

  • 设备驱动相关结构体中,会维护一个指针,指向唤醒节点链表(这个链表由设备驱动去维护)
  • 链表节点的添加,是调用SEL_WAKE_NODE_ADD 函数完成的

在这里插入图片描述

2.3 阻塞与唤醒实现

阻塞
  select 本身是一个阻塞函数。通过调用二进制信号量 API_SemaphoreBPend,实现阻塞操作。

注意,这里的二进制信号量,实际上是一个同步信号量。在调用 pend 之前,pselect 会首先调用 ioctl,传递 FIOSELECT 参数。此接口中会判断 当前 是否满足 select 的唤醒条件,若满足则先调用 post,以使之后调用的 pend 不会被阻塞; 若 当前 不满足 select 的唤醒条件,则会进入阻塞状态,等待设备驱动主动去唤醒

唤醒
  通常是由 select 所监听的文件描述符集对应的设备驱动去唤醒。还是以 gpio 驱动为例,当一个 gpio 中断(电平触发、边沿触发)产生时,就会告诉操作系统,该 gpio 的状态“可读”,通过调用 SEL_WAKE_UP_ALL 接口实现唤醒操作。该接口底层实现,实际上就是调用 API_SemaphoreBPost

LW_API  
VOID    API_SelWakeup (PLW_SEL_WAKEUPNODE   pselwunNode)
{
....../*  根据唤醒节点中保存的线程 ID,获取线程 TCB 结构  */usIndex = _ObjectGetIndex(pselwunNode->SELWUN_hThreadId);ptcb = __GET_TCB_FROM_INDEX(usIndex);if (!ptcb || !ptcb->TCB_pselctxContext) {                           /*  线程不存在                  */return;}/*  设置唤醒节点的 READY 属性 */LW_SELWUN_SET_READY(pselwunNode);/*  根据 TCB,找到需要唤醒的句柄 SELCTX_hSembWakeup  */pselctxContext = ptcb->TCB_pselctxContext;API_SemaphoreBPost(pselctxContext->SELCTX_hSembWakeup);             /*  提前激活即将等待线程        */
}static irqreturn_t  _gpiofdIsr (PLW_GPIOFD_FILE pgpiofdfil)
{
......SEL_WAKE_UP_ALL(&pgpiofdfil->GF_selwulist, SELREAD);
......
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com