鸿蒙内核源码分析(Shell解析篇) | 应用窥视内核的窗口

系列篇从内核视角用一句话概括shell的底层实现为:两个任务,三个阶段。其本质是独立进程,因而划到进程管理模块。每次创建shell进程都会再创建两个任务。

  • 客户端任务(ShellEntry): 负责接受来自终端(控制台)敲入的一个个字符,字符按VT规范组装成一句句的命令。
  • 服务端任务(ShellTask): 对命令进行解析并执行,将结果输出到控制台。
    而按命令生命周期可分三个阶段.
  • 编辑: 鸿蒙在这个部分实现了一个简单的编辑器功能,处理控制台输入的每个字符,主要包括了对控制字符 例如 <ESC>,\t,\b,\n,\r,四个方向键0x41 ~ 0x44 的处理。
  • 解析: 对编辑后的字符串进行解析,解析出命令项和参数项,找到对应的命令项执行函数。
  • 执行: 命令可通过静态和动态两种方式注册到内核,解析出具体命令后在注册表中找到对应函数回调。将结果输出到控制台。

编辑部分由客户端任务完成,后两个部分由服务端任务完成,命令全局注册由内核完成。

  • 本篇主要说 服务端任务 和 解析/执行过程.
  • 客户端任务 和 编辑过程 已在 (Shell编辑篇) 中说明,请自行翻看.
总体过程
  • 第一步: 将支持的shell命令注册进全局链表,支持静态和动态两种方式,内容包括命令项,参数信息和回调函数.
  • 第二步: 由独立任务解析出用户输入的命令行,拆分出命令项和参数内容
  • 第三步: 通过命令项在全局链表中遍历找到已注册的回调函数,并执行.
结构体

鸿蒙对命令的注册用了三个结构体,个人感觉前两个可以合成一个,降低代码阅读难度.

STATIC CmdModInfo g_cmdInfo;//shell 命令模块信息,上面挂了所有的命令项(ls,cd ,cp ==)

typedef struct {//命令项
    CmdType cmdType;	//命令类型
		//CMD_TYPE_EX:不支持标准命令参数输入,会把用户填写的命令关键字屏蔽掉,例如:输入ls /ramfs,传入给注册函数的参数只有/ramfs,而ls命令关键字并不会被传入。
		//CMD_TYPE_STD:支持的标准命令参数输入,所有输入的字符都会通过命令解析后被传入。
    const CHAR *cmdKey;	//命令关键字,例如:ls 函数在Shell中访问的名称。
    UINT32 paraNum;		//调用的执行函数的入参最大个数,暂不支持。
    CmdCallBackFunc cmdHook;//命令执行函数地址,即命令实际执行函数。
} CmdItem;
typedef struct {	//命令节点
    LOS_DL_LIST list;	//双向链表
    CmdItem *cmd;	//命令项
} CmdItemNode;

/* global info for shell module */
typedef struct {//shell 模块的全局信息
    CmdItemNode cmdList;	//命令项节点
    UINT32 listNum;//节点数量
    UINT32 initMagicFlag;//初始魔法标签 0xABABABAB
    LosMux muxLock;	//操作链表互斥锁
    CmdVerifyTransID transIdHook;//暂不知何意
} CmdModInfo;

解读

  • CmdItem为注册的内容载体结构体,cmdHook为回调函数,是命令的真正执行体.
  • 通过双向链表CmdItemNode.list将所有命令穿起来
  • CmdModInfo记录命令数量和操作的互斥锁,shell的魔法数字为 0xABABABAB
第一步 | Shell 注册
  • 静态宏方式注册,链接时处理
    静态注册命令方式一般用在系统常用命令注册,鸿蒙已支持以下命令.
        arp           cat           cd            chgrp         chmod         chown         cp            cpup          
        date          dhclient      dmesg         dns           format        free          help          hwi           
        ifconfig      ipdebug       kill          log           ls            lsfd          memcheck      mkdir         
        mount         netstat       oom           partinfo      partition     ping          ping6         pwd           
        reset         rm            rmdir         sem           statfs        su            swtmr         sync          
        systeminfo    task          telnet        test          tftp          touch         umount        uname         
        watch         writeproc  
例如注册 `ls`命令
    SHELLCMD_ENTRY(ls_shellcmd,  CMD_TYPE_EX, "ls", XARGS,  (CMD_CBK_FUNC)osShellCmdLs)

需在链接选项中添加链接该新增命令项参数,具体在liteos_tables_ldflags.mk文件的LITEOS_TABLES_LDFLAGS项下添加-uls_shellcmd。至于SHELLCMD_ENTRY是如何实现的在链接阶段的注册,请自行翻看 (内联汇编篇) ,有详细说明实现细节.

  • 动态命令方式,运行时处理
    动态注册命令方式一般用在用户命令注册,具体实现代码如下:
    osCmdReg(CMD_TYPE_EX, "ls", XARGS,  (CMD_CBK_FUNC)osShellCmdLs)
    {
        // ....
        //5.正式创建命令,挂入链表
        return OsCmdItemCreate(cmdType, cmdKey, paraNum, cmdProc);//不存在就注册命令
    }
    //创建一个命令项,例如 chmod
    STATIC UINT32 OsCmdItemCreate(CmdType cmdType, const CHAR *cmdKey, UINT32 paraNum, CmdCallBackFunc cmdProc)
    {
        CmdItem *cmdItem = NULL;
        CmdItemNode *cmdItemNode = NULL;
        //1.构造命令节点过程
        cmdItem = (CmdItem *)LOS_MemAlloc(m_aucSysMem0, sizeof(CmdItem));
        if (cmdItem == NULL) {
            return OS_ERRNO_SHELL_CMDREG_MEMALLOC_ERROR;
        }
        (VOID)memset_s(cmdItem, sizeof(CmdItem), '\0', sizeof(CmdItem));

        cmdItemNode = (CmdItemNode *)LOS_MemAlloc(m_aucSysMem0, sizeof(CmdItemNode));
        if (cmdItemNode == NULL) {
            (VOID)LOS_MemFree(m_aucSysMem0, cmdItem);
            return OS_ERRNO_SHELL_CMDREG_MEMALLOC_ERROR;
        }
        (VOID)memset_s(cmdItemNode, sizeof(CmdItemNode), '\0', sizeof(CmdItemNode));
        cmdItemNode->cmd = cmdItem;			//命令项 
        cmdItemNode->cmd->cmdHook = cmdProc;//回调函数 osShellCmdLs
        cmdItemNode->cmd->paraNum = paraNum;//`777`,'/home'
        cmdItemNode->cmd->cmdType = cmdType;//关键字类型
        cmdItemNode->cmd->cmdKey = cmdKey;	//`chmod`
        //2.完成构造后挂入全局链表
        (VOID)LOS_MuxLock(&g_cmdInfo.muxLock, LOS_WAIT_FOREVER);
        OsCmdAscendingInsert(cmdItemNode);//按升序方式插入
        g_cmdInfo.listNum++;//命令总数增加
        (VOID)LOS_MuxUnlock(&g_cmdInfo.muxLock);

        return LOS_OK;
    }
第二步 解析 | ShellTask
//shell 服务端任务初始化,这个任务负责解析和执行命令
LITE_OS_SEC_TEXT_MINOR UINT32 ShellTaskInit(ShellCB *shellCB)
{
    CHAR *name = NULL;
    TSK_INIT_PARAM_S initParam = {0};
	//输入Shell命令的两种方式
    if (shellCB->consoleID == CONSOLE_SERIAL) {	//通过串口工具
        name = SERIAL_SHELL_TASK_NAME;
    } else if (shellCB->consoleID == CONSOLE_TELNET) {//通过远程工具
        name = TELNET_SHELL_TASK_NAME;
    } else {
        return LOS_NOK;
    }

    initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)ShellTask;//任务入口函数,主要是解析shell命令
    initParam.usTaskPrio   = 9; /* 9:shell task priority */
    initParam.auwArgs[0]   = (UINTPTR)shellCB;
    initParam.uwStackSize  = 0x3000;
    initParam.pcName       = name;
    initParam.uwResved     = LOS_TASK_STATUS_DETACHED;

    (VOID)LOS_EventInit(&shellCB->shellEvent);//初始化事件,以事件方式通知任务解析命令

    return LOS_TaskCreate(&shellCB->shellTaskHandle, &initParam);//创建任务
}
LITE_OS_SEC_TEXT_MINOR UINT32 ShellTask(UINTPTR param1,
                                        UINTPTR param2,
                                        UINTPTR param3,
                                        UINTPTR param4)
{
    UINT32 ret;
    ShellCB *shellCB = (ShellCB *)param1;
    (VOID)param2;
    (VOID)param3;
    (VOID)param4;

    while (1) {
        PRINTK("\nOHOS # ");//读取shell 输入事件 例如: cat weharmony.net 命令
        ret = LOS_EventRead(&shellCB->shellEvent,
                            0xFFF, LOS_WAITMODE_OR | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER);
        if (ret == SHELL_CMD_PARSE_EVENT) {//获得解析命令事件
            ShellCmdProcess(shellCB);//处理命令 
        } else if (ret == CONSOLE_SHELL_KEY_EVENT) {//退出shell事件
            break;
        }
    }
    OsShellKeyDeInit((CmdKeyLink *)shellCB->cmdKeyLink);//
    OsShellKeyDeInit((CmdKeyLink *)shellCB->cmdHistoryKeyLink);
    (VOID)LOS_EventDestroy(&shellCB->shellEvent);//注销事件
    (VOID)LOS_MemFree((VOID *)m_aucSysMem0, shellCB);//释放shell控制块
    return 0;
}

解读

  • 任务优先级和 客户端任务 一样同为 9

  • 指定内核栈大小为0x3000 = 12K ,因任务负责命令的解析和执行,所以需要更大的内核空间.

  • 任务的入口函数ShellTask,一个死循环在以LOS_WAIT_FOREVER方式死等事件发生.

    • SHELL_CMD_PARSE_EVENT 通知开始解析事件,该事件由 客户端任务ShellEntry检测到回车键时发出.
      STATIC VOID ShellNotify(ShellCB *shellCB)
      {
          (VOID)LOS_EventWrite(&shellCB->shellEvent, SHELL_CMD_PARSE_EVENT);
      }
*   `CONSOLE_SHELL_KEY_EVENT` 收到 `exit`命令时将发出该事件,退出`shell`回收资源       
  • 层层跟进ShellCmdProcess,解析出命令项和参数内容,最终跑到OsCmdExec中遍历 已注册的命令表,找出命令对应的函数完成回调.
   LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdExec(CmdParsed *cmdParsed, CHAR *cmdStr)
     {
         UINT32 ret;
         CmdCallBackFunc cmdHook = NULL;
         CmdItemNode *curCmdItem = NULL;
         UINT32 i;
         const CHAR *cmdKey = NULL;

         if ((cmdParsed == NULL) || (cmdStr == NULL) || (strlen(cmdStr) == 0)) {
             return (UINT32)OS_ERROR;
         }

         ret = OsCmdParse(cmdStr, cmdParsed);//解析出命令关键字,参数
         if (ret != LOS_OK) {
             goto OUT;
         }
         //遍历命令注册全局链表
         LOS_DL_LIST_FOR_EACH_ENTRY(curCmdItem, &(g_cmdInfo.cmdList.list), CmdItemNode, list) {
             cmdKey = curCmdItem->cmd->cmdKey;
             if ((cmdParsed->cmdType == curCmdItem->cmd->cmdType) &&
                 (strlen(cmdKey) == strlen(cmdParsed->cmdKeyword)) &&
                 (strncmp(cmdKey, (CHAR *)(cmdParsed->cmdKeyword), strlen(cmdKey)) == 0)) {//找到命令的回调函数 例如: ls <-> osShellCmdLs
                 cmdHook = curCmdItem->cmd->cmdHook;
                 break;
             }
         }

         ret = OS_ERROR;
         if (cmdHook != NULL) {//执行命令,即回调函数
             ret = (cmdHook)(cmdParsed->paramCnt, (const CHAR **)cmdParsed->paramArray);
         }

     OUT:
         for (i = 0; i < cmdParsed->paramCnt; i++) {//无效的命令要释放掉保存参数的内存
             if (cmdParsed->paramArray[i] != NULL) {
                 (VOID)LOS_MemFree(m_aucSysMem0, cmdParsed->paramArray[i]);
                 cmdParsed->paramArray[i] = NULL;
             }
         }

         return (UINT32)ret;
     }
第三步 | 执行

想知道有哪些系统shell命令,可以搜索关键词SHELLCMD_ENTRY拿到所有通过静态方式注册的命令.

其中有网络的,进程的,任务的,内存的 等等,此处列出几个常用的shell命令的实现.

ls 命令
SHELLCMD_ENTRY(ls_shellcmd, CMD_TYPE_EX, "ls", XARGS, (CmdCallBackFunc)osShellCmdLs);

/*******************************************************
命令功能
ls命令用来显示当前目录的内容。

命令格式
ls [path]

path为空时,显示当前目录的内容。
path为无效文件名时,显示失败,提示:
ls error: No such directory。
path为有效目录路径时,会显示对应目录下的内容。

使用指南
ls命令显示当前目录的内容。
ls可以显示文件的大小。
proc下ls无法统计文件大小,显示为0。

*******************************************************/
int osShellCmdLs(int argc, const char **argv)
{
  char *fullpath = NULL;
  const char *filename = NULL;
  int ret;
  char *shell_working_directory = OsShellGetWorkingDirtectory();//获取当前工作目录
  if (shell_working_directory == NULL)
    {
      return -1;
    }

  ERROR_OUT_IF(argc > 1, PRINTK("ls or ls [DIRECTORY]\n"), return -1);

  if (argc == 0)//木有参数时 -> #ls 
    {
      ls(shell_working_directory);//执行ls 当前工作目录
      return 0;
    }

  filename = argv[0];//有参数时 -> #ls ../harmony  or #ls /no such file or directory
  ret = vfs_normalize_path(shell_working_directory, filename, &fullpath);//获取全路径,注意这里带出来fullpath,而fullpath已经在内核空间
  ERROR_OUT_IF(ret < 0, set_err(-ret, "ls error"), return -1);

  ls(fullpath);//执行 ls 全路径
  free(fullpath);//释放全路径,为啥要释放,因为fullpath已经由内核空间分配

  return 0;
}
task 命令
SHELLCMD_ENTRY(task_shellcmd, CMD_TYPE_EX, "task", 1, (CmdCallBackFunc)OsShellCmdDumpTask);

LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdDumpTask(INT32 argc, const CHAR **argv)
{
    UINT32 flag = 0;
#ifdef LOSCFG_KERNEL_VM
    flag |= OS_PROCESS_MEM_INFO;
#endif

    if (argc >= 2) { /* 2: The task shell name restricts the parameters */
        goto TASK_HELP;
    }

    if (argc == 1) {
        if (strcmp("-a", argv[0]) == 0) {
            flag |= OS_PROCESS_INFO_ALL;
        } else if (strcmp("-i", argv[0]) == 0) {
            if (!OsShellShowTickRespo()) {
                return LOS_OK;
            }
            goto TASK_HELP;
        } else if (strcmp("-t", argv[0]) == 0) {
            if (!OsShellShowSchedParam()) {
                return LOS_OK;
            }
            goto TASK_HELP;
        } else {
            goto TASK_HELP;
        }
    }

    return OsShellCmdTskInfoGet(OS_ALL_TASK_MASK, NULL, flag);

TASK_HELP:
    PRINTK("Unknown option: %s\n", argv[0]);
    PRINTK("usage: task or task -a\n");
    return LOS_NOK;
}
cat 命令
SHELLCMD_ENTRY(cat_shellcmd, CMD_TYPE_EX, "cat", XARGS, (CmdCallBackFunc)osShellCmdCat);

/*****************************************************************
cat用于显示文本文件的内容。cat [pathname]
cat weharmony.txt
*****************************************************************/
int osShellCmdCat(int argc, const char **argv)
{
  char *fullpath = NULL;
  int ret;
  unsigned int ca_task;
  struct Vnode *vnode = NULL;
  TSK_INIT_PARAM_S init_param;
  char *shell_working_directory = OsShellGetWorkingDirtectory();//显示当前目录 pwd
  if (shell_working_directory == NULL)
    {
      return -1;
    }

  ERROR_OUT_IF(argc != 1, PRINTK("cat [FILE]\n"), return -1);

  ret = vfs_normalize_path(shell_working_directory, argv[0], &fullpath);//由相对路径获取绝对路径
  ERROR_OUT_IF(ret < 0, set_err(-ret, "cat error"), return -1);

  VnodeHold();
  ret = VnodeLookup(fullpath, &vnode, O_RDONLY);
    if (ret != LOS_OK)
      {
        set_errno(-ret);
        perror("cat error");
        VnodeDrop();
        free(fullpath);
        return -1;
      }
    if (vnode->type != VNODE_TYPE_REG)
      {
        set_errno(EINVAL);
        perror("cat error");
        VnodeDrop();
        free(fullpath);
        return -1;
      }
  VnodeDrop();
  (void)memset_s(&init_param, sizeof(init_param), 0, sizeof(TSK_INIT_PARAM_S));
  init_param.pfnTaskEntry = (TSK_ENTRY_FUNC)osShellCmdDoCatShow;
  init_param.usTaskPrio   = CAT_TASK_PRIORITY;	//优先级10
  init_param.auwArgs[0]   = (UINTPTR)fullpath;	//入口参数
  init_param.uwStackSize  = CAT_TASK_STACK_SIZE;//内核栈大小
  init_param.pcName       = "shellcmd_cat";	//任务名称
  init_param.uwResved     = LOS_TASK_STATUS_DETACHED | OS_TASK_FLAG_SPECIFIES_PROCESS;
  init_param.processID    = 2; /* 2: kProcess */ //内核任务

  ret = (int)LOS_TaskCreate(&ca_task, &init_param);//创建任务显示cat内容

  if (ret != LOS_OK)
    {
      free(fullpath);
    }

  return ret;
}

你能看明白这些命令的底层实现吗? 如果看明白了,可能会不由得发出 原来如此 的感叹!

鸿蒙全栈开发全新学习指南

也为了积极培养鸿蒙生态人才,让大家都能学习到鸿蒙开发最新的技术,针对一些在职人员、0基础小白、应届生/计算机专业、鸿蒙爱好者等人群,整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线【包含了大厂APP实战项目开发】

本路线共分为四个阶段:

第一阶段:鸿蒙初中级开发必备技能

第二阶段:鸿蒙南北双向高工技能基础:gitee.com/MNxiaona/733GH

第三阶段:应用开发中高级就业技术

第四阶段:全网首发-工业级南向设备开发就业技术:gitee.com/MNxiaona/733GH

《鸿蒙 (Harmony OS)开发学习手册》(共计892页)

如何快速入门?

1.基本概念
2.构建第一个ArkTS应用
3.……

开发基础知识:gitee.com/MNxiaona/733GH

1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……

基于ArkTS 开发

1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……

鸿蒙开发面试真题(含参考答案):gitee.com/MNxiaona/733GH

鸿蒙入门教学视频:

美团APP实战开发教学:gitee.com/MNxiaona/733GH

写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新学习资源,请移步前往小编:gitee.com/MNxiaona/733GH

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/613764.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

开源RAG框架汇总

前言 本文搜集了一些开源的基于LLM的RAG&#xff08;Retrieval-Augmented Generation&#xff09;框架&#xff0c;旨在吸纳业界最新的RAG应用方法与思路。如有错误或者意见可以提出&#xff0c;同时也欢迎大家把自己常用而这里未列出的框架贡献出来&#xff0c;感谢~ RAG应用…

Linux的有关权限的学习

1.认识权限在Linux中的表示 在Linux中&#xff0c;一切皆文件&#xff0c;而每个文件都会有其相对应的操作权限。那么&#xff0c;我们该怎么来认识他们呢&#xff1f; 首先我们可以看到&#xff0c;在每个test文件的前面都会有一个-rw-r--r--这个字符&#xff0c;而这个字符&…

MySQL数据库的安装和部署

1.数据库的相关介绍 关系型数据库管理系统&#xff1a;&#xff08;英文简称&#xff1a;RDBMS&#xff09; 为我们提供了一种存储数据的特定格式&#xff0c;所谓的数据格式就是表&#xff0c; 在数据库中一张表就称为是一种关系. 在关系型数据库中表由两部分组成&#xf…

【官方下载】Android 开发环境之 java 11 下载地址和下载操作步骤

作者介绍&#xff1a; 百度资深Android工程师T6&#xff0c;在百度任职7年半。 目前&#xff1a;成立赵小灰代码工作室&#xff0c;欢迎大家找我交流Android、微信小程序、鸿蒙项目。文章底部&#xff0c;csdn有为我插入微信的联络方式&#xff0c;欢迎大家联络我。 一&#x…

spsr 的恢复出错,导致 thumb 指令集的 it 条件运行指令运行异常,清晰的调试思路帮助快速解决问题

记一次调试过程 这是一个在 arm 架构上的 RTOS 上的调试过程。问题现象为使用 thumb 指令集的 libgcc 库的情况下&#xff0c;浮点运算随机出错。经过一番追踪调试&#xff0c;逐步缩小问题范围&#xff0c;最后定位问题&#xff0c;成功解决。 场景 在某款的国产 RTOS 上&a…

男士内裤买哪个牌子好?男士内裤选购攻略大盘点

很多男性对内裤都并不讲究&#xff0c;哪怕已经穿到千疮百孔也不愿意换新的。实际上男士内裤如果长时间不更换会导致变形&#xff0c;从而让舒适性、弹性缺失等等&#xff0c;更重要的是即使洗晒也仍然有细菌残留&#xff0c;有可能影响健康&#xff01; 也有不少男性朋友发现…

sql-labs通关详解(1-10)

1.less-1 1.判断类型 由此判断是字符型漏洞由单引号闭合。 2.判断 字段个数 http://192.168.190.145/sqli-labs/Less-1/?id1 order by 3-- 3.获取数据库名 -1 union select 1,2,database()-- 4.获取表名 -1 union select 1,2,group_concat(table_name) from information_…

Github 配置 SSH key

一、前言 问题描述 通过 ssh 的 url 使用 git 命令克隆 github 上私有项目出现 fatal: Could not read from remote repository. 本地仓库无法从远程仓库读取数据克隆失败 问题定位 一般是仓库 URL 错误或者权限问题这里排除 URL 错误&#xff0c;初步定位为访问权限问题 解决…

【计算机网络】计算机网络概述、计算机网络性能指标 习题1

0 1. 计算机网络可被理解为( )。 A.执行计算机数据处理的软件模块 B. 由自治的计算机互连起来的集合体 C.多个处理器通过共享内存实现的紧耦合系统 D. 用于共同完成一项任务的分布式系统 0 2.计算机网络最基本的功能是( )。 A.数据通信 B. 资源共享 C. 分布式处理 D. 信息综合…

F. Circle Perimeter

思路&#xff1a;线性时间复杂度就可以解决&#xff0c;不用二分&#xff0c;我们枚举横坐标&#xff0c;然后看当前横坐标情况下多少个纵坐标满足条件。 代码&#xff1a; void solve(){int r;cin >> r;int y r, ans 0;for(int x 0;x < r;x ){ //枚举横坐标x&am…

linux性能监控之slabtop

slabtop命令是以实时的方式显示内核slab缓冲区的细节信息&#xff0c;是linux自带的命令 [rootk8s-master ~]# slabtop --helpUsage:slabtop [options]Options:-d, --delay <secs> delay updates-o, --once only display once, then exit-s, --sort <char&…

K8S搭建

文章目录 K8S搭建配置要求 安装 Kuboard-Spray加载离线资源包规划并安装集群访问集群重启Kubernetes集群Worker节点不能启动许多Pod一直Crash或不能正常访问 containerd配置网络代理 常用的 kubectl 命令&#xff1a; K8S搭建 安装高可用的Kubernetes集群 配置要求 对于 Kub…

斯坦福李飞飞最新对话:AI不会对人类造成“灭绝性危机” | 最新快讯

美国斯坦福大学教授、美国国家工程院院士李飞飞&#xff08;来源&#xff1a;斯坦福大学账号&#xff09; 北京时间 5 月 10 日凌晨举行的 Bloomberg Tech 活动上&#xff0c;著名华人计算机科学家、美国斯坦福大学教授李飞飞&#xff08;Fei-Fei Li&#xff09;与彭博社 Emily…

视频编辑软件pitivi基本功之创建标题片段

视频编辑软件pitivi基本功之创建标题片段 台式机的系统是openSUSE-Leap-15.5-DVD-x86_64 一、素材来源 《视频编辑软件pitivi基本功之使用SSR录制电脑屏幕》 https://blog.csdn.net/weixin_42145772/article/details/138597608?spm1001.2014.3001.5502 根据上面文章的方法得…

【回溯 网格 状态压缩】52. N 皇后 II

本文涉及知识点 回溯 网格 状态压缩 LeetCode52. N 皇后 II n 皇后问题 研究的是如何将 n 个皇后放置在 n n 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。 给你一个整数 n &#xff0c;返回 n 皇后问题 不同的解决方案的数量。 示例 1&#xff1a; 输入&#x…

国内运营商选择爱立信,或因它的低频5G技术更先进,价格更便宜

国内某运营商将大笔5G设备订单交给爱立信&#xff0c;引发了掀然大波&#xff0c;影响仍在扩散&#xff0c;对此各方说什么原因都有&#xff0c;笔者认为爱立信此次斩获大单&#xff0c;可能在于它的低频5G设备更先进&#xff0c;价格更便宜&#xff0c;对于急于降低成本的国内…

window10下安装ubuntu系统以及docker使用

window10下安装ubuntu系统以及docker使用 1. 启用适用于Linux的Windwos子系统2.下载Linux内核更新包3.将 WSL 2 设置为默认版本4.安装Ubuntu<br />直接去Microsoft store里面直接搜索Ubuntu进行安装。5.可能出现的问题1.win10启动ubuntu报错 参考的对象类型不支持尝试的操…

学习网络需要认识的各种设备

网桥&#xff08;bridge&#xff09; 网桥工作在数据链路层&#xff0c;可以把多个局域网连接起来&#xff0c;组成一个更大的局域网 以太网中&#xff0c;数据链路层地址就是mac地址&#xff0c;网桥与集线器的区别就是&#xff0c;网桥会过滤mac&#xff0c;只有目的mac地址…

halcon 模板匹配

一、概述 模板匹配常用于定位和查找&#xff0c;有很多的方式&#xff0c;halcon 中就有灰度匹配 、形状匹配、变形匹配、缩放匹配等&#xff0c;其实最常用的还是两种第一个就是灰度匹配、还有就是形状匹配 二、金字塔概述 网上有很多关于金字塔的解释&#xff0c;我这里直…

住宅ip与数据中心ip代理的区别是什么

代理通常意味着“替代”。它是用户设备和目标服务器之间的中介&#xff0c;允许在不同的IP地址下上网。代理ip根据来源分类可分住宅ip与数据中心ip&#xff0c;二者之间区别是什么呢&#xff1f; 住宅ip是由互联网服务提供商(ISP)提供给家庭的IP地址。出于这个原因&#xff0c…