操作系统的调度基础

2023-10-29

操作系统的cpu调度

把内核线程当成内核中的一个进程去理解。

任务系统的三个核心特征是:权限分级、数据隔离和任务切换。以X86_64架构为例,权限分级通过CPU的多模式机制和分段机制实现,数据隔离通过分页机制实现,任务切换通过中断机制和任务机制(TR/TSS)实现。

用户态内核态: 在 CPU 的所有指令中,有些指令是非常危险的,如果错用,将导致系统崩溃,比如清内存、设置时钟等。如果允许所有的程序都可以使用这些指令,那么系统崩溃的概率将大大增加。所以,CPU 将指令分为特权指令和非特权指令,对于那些危险的指令,只允许操作系统及其相关模块使用,普通应用程序只能使用那些不会造成灾难的指令。比如 Intel 的 CPU 将特权等级分为 4 个级别:Ring0~Ring3。其实 Linux 系统只使用了 Ring0 和 Ring3 两个运行级别(Windows 系统也是一样的)。当进程运行在 Ring3 级别时被称为运行在用户态,而运行在 Ring0 级别时被称为运行在内核态。
在这里插入图片描述
陷入内核的代价: 用户态到内核态切换途径:系统调用 、中断 、异常。系统调用的切换流程:系统调用触发中断,进入中断处理程序。若中断时,进程在执行用户态的代码,该中断会引起CPU特权级从ring3级到ring0级的切换,CPU会进行堆栈的切换,CPU会从当前任务的TSS中取到内核栈的段选择符和偏移值;CPU首先会上下文保存到内核栈,把原用户态的堆栈指针ss和esp压入内核态堆栈,随后把标志寄存器eflags的内容和此次中断的返回位置cs,eip压入内核态堆栈。当中断处理函数结束后,将恢复内核栈中的数据,并继续处理被中断的进程。每个系统调用内核要进行许多工作,耗时开销大。

栈(stack): 栈又称堆栈, 是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进后出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。

用户级线程: 用户级线程是指有关线程的管理工作都是由应用程序完成,内核意识不到用户级线程的存在,也不会对这些用户级线程进行调度。如果某个进程创建了多个用户级线程,那么所有这些用户级线程仅有一个对应的内核线程,在用户级线程策略中,内核是以进程为单位进行调度的,不管进程内有多少线程,内核一次只把一个进程分配给一个处理器,因此一个进程中只有一个线程可以执行,所以只有一个对应的内核线程。

在这里插入图片描述

内核级线程: 内核级线程是指由内核管理、只运行在内核态、不受用户态上下文拖累的线程。其依赖于操作系统核心,由内核的内部需求进行创建和撤销。内核线程的线程表位于内核中,包括了线程控制块,一旦线程阻塞,内核会从当前或者其他进程中重现选择一个线程保证程序的执行。用户应用程序通过API和系统调用(system call)来访问内核级线程。

内核级线程和用户级线程的关系: 内核线程是由操作系统维护的线程对象。它是能够被处理器调度和执行的实际线程。通常,系统线程是具有权限设置,优先级等的重量级对象。内核线程调度器负责调度内核线程。用户线程必须与内核线程相关联的原因在于用户线程本身只是用户程序中的一堆数据。内核线程是系统中的真正线程,所以为了让用户线程进步,用户程序必须让其调度程序接受用户线程,然后在内核线程上运行它。用户线程和内核线程之间的映射不一定是一对一(1:1)映射;您可以拥有多个用户线程共享相同的内核线程(每次只运行一个用户线程),并且您可以拥有单个用户线程,该线程在不同的内核线程(1:n)映射之间进行旋转。 内核级线程驻留在内核空间,它们是内核对象。有了内核线程,每个用户线程被映射或绑定到一个内核线程。用户线程在其生命期内都会绑定到该内核线程。

进程和线程的概念关系:进程作为资源拥有的基本单位,线程作为cpu调度分配的基本单位基本不拥有资源,只拥有一些必不可少的资源,如:程序计数器,局部变量,少数状态参数,返回地址以及堆栈等,这些都是线程私有的,不共享。线程是进程的一部分,描述指令流执行状态,它是进程中指令执行流的最小单元,是CPU调度的基本单位。线程在进程⾥⾯专⻔负责执⾏指令,指令是从进程.text段映射⾥读出来的,然后在进程⾥堆栈上操作⼀些数据,线程处理数据的资源边界是在进程内的。线程的切换是cpu在不同任务的任务上下文间切换。操作系统对线程进行调度(时钟中断),引导cpu不间断的执行不同任务的指令,以达到在不同任务间切换的效果。进程是资源分配的基本单位,线程是运行调度的基本单位。进程和线程的分离是对任务抽象的更加成熟的结果,是对进程内部并发需求的实现。线程的切换只是指令的切换,而进程的切换还包括资源区的切换。

进程和线程在内核区别: 对于 Linux 来讲,所有的线程都当作进程来实现,因为没有单独为线程定义特定的调度算法,也没有单独为线程定义特定的数据结构(所有的线程或进程的核心数据结构都是 task_struct)。把内核线程当成内核中的一个进程去理解。

对于一个进程,相当于是它含有一个线程,就是它自身。对于多线程来说,原本的进程称为主线程,它们在一起组成一个线程组。

进程拥有自己的地址空间,所以每个进程都有自己的页表。而线程却没有,只能和其它线程共享某一个地址空间和同一份页表。这个区别的 根本原因 是,在进程/线程创建时,因是否拷贝当前进程的地址空间还是共享当前进程的地址空间,而使得指定的参数不同而导致的。具体地说,进程和线程的创建都是执行 clone 系统调用进行的。而 clone 系统调用会执行 do_fork 内核函数,而它则又会调用 copy_process 内核函数来完成。主要包括如下操作:在调用 copy_process 的过程中,会创建并拷贝当前进程的 task_stuct,同时还会创建属于子进程的 thread_info 结构以及内核栈。此后,会为创建好的 task_stuct 指定一个新的 pid(在 task_struct 结构体中)。然后根据传递给 clone 的参数标志,来选择拷贝还是共享打开的文件,文件系统信息,信号处理函数,进程地址空间等。这就是进程和线程不一样地方的本质所在。
在这里插入图片描述

多核: 内核空间实现为每个内核支持线程设置了一个线程控制快,内核是根据该控制快而感知某个线程是否存在,并加以控制。设置了内核支持线程的系统,其调度是以内核线程为单位进行的。如果是用户级线程,操作系统看不到,就没法分配资源,无法发挥多核的价值。其中核心级线程不是两个栈,而是两套栈。因为用户级线程只会在用户栈里跑,但是使用核心级线程的程序,既需要在用户层跑,也需要在内核里跑。用户级线程的切换,是两个栈之间的切换。核心级线程的切换不是两个栈,而是两套栈。因为核心级线程必须到内核态,在用户态使用用户栈,在内核态不也得调用函数,也得使用一个栈,既要在用户态又得在内核态跑,一个核心级线程要两个栈组成的一套栈。

cpu调度: 对于 Linux 来讲,所有的线程都当作进程来实现,因为没有单独为线程定义特定的调度算法,也没有单独为线程定义特定的数据结构(所有的线程或进程的核心数据结构都是 task_struct)。Linux系统 对线程和进程并不特别区分。线程仅仅被视为一个与其他线程共享某些资源的进程。每个线程都拥有唯一自己task_struct。内核调度的对象是根据task_struct结构体。进程之间不共享地址空间,而线程与创建它的进程是共享地址空间的。

内核线程池Pool模型:当从⽤户态代码进⼊系统态代码调⽤的时候会涉及到上下⽂切换,这是要付出⼀定的代价的。很显然系统线程去创建去调度是要付出这些代价的,所以很多时候系统线程成本会⾮常的⾼,当我们频繁的去创建系统线程销掉系统线程这种代价实在太⼤了。在这基础上往往会实现这样的模型。在⽤户态抽象很多个执⾏单位,我们把这些⽤户态线程映射到少量的系统线程上⾯去,然后建⽴类似于 Pool 这样的⼀个概念可以复⽤的。内核态的系统线程专⻔负责执⾏,⽽⽤户态的线程负责存储状态,⽐如说线程栈状态,所有线程执⾏的线程栈是⽤来保存当时执⾏线程状态的,还包含寄存器相关的信息、局部变量,这样的好处是我们把建成Pool以后就不需要频繁的创建系统线程,只需要⽤户态去创建各种各样我们所需的这种抽象的专⻔⽤来存储状态的这种⽤户态线程,我们可以创建很多个,当我们创建好当需要执⾏的时候,把它绑定到⼀个系统线程上⾯去,然后去执⾏执⾏完了以后可以把这个系统线程释放掉,系统线程回到Pool⾥⾯只需要把这个状态杀掉,我们不需要消灭这个系统线程。

PCB与TCB: 在早期的操作系统实现中并不存在线程的概念,与之对应的是进程。也就是说当时的操作系统粗暴的将一个任务整体的描述为一条执行线,操作系统以任务为单位进行资源分配,并以任务为单位进行运行调度。这样分配的结果便是,每次进行运行调度即进程切换时,也要同时切换资源的权限,造成非常大的开销。于是后来的操作系统将资源分配单位和任务调度单位分离开来,也就是我们现在所说的进程与线程。以进程为单位分配系统资源,以线程为单位进行任务调度。PCB中包含了资源分配信息和运行调度信息。其中:进程状态、CPU排班法为进行运行调度时的依据,CPU寄存器、程序计数器为运行调度时保存和恢复现场的依据,存储管理器、会计信息、输入输出状态则是对进程拥有的资源的描述。对于TCB来说,不同操作系统有着不同的实现,但大致都是仅包含了运行调度时所需的信息,如线程状态、调度算法、CPU寄存器、PC计数器等。**Linux的进程控制块为一个由结构task_struct所定义的数据结构可以理解为PCB,而没有TCB的概念。**在linux中,线程和进程共用了一种数据结构(task_struct)。也就是说,linux并没有为线程设计另外的数据结构。linux中的线程是由进程模拟的。所以,linux中没有真正意义上的线程,相当于“假”的线程。注:windows操作系统中,线程就是真正意义上的线程。每一个线程都有一个”tcb”,每一个进程则都有一个”pcb”,两者各有自己的数据结构来表示。PCB的组织方式为链表:同一状态的进程其PCB成一链表,多个状态对应多个不同的链表。进程控制块PCB的内容

  • 进程描述信息:

    进程标识符(process ID),唯一,通常是一个整数;

    进程名,通常基于可执行文件名(不唯一);

    用户标识符(user ID);进程组关系(process group)

  • 进程控制信息:

    当前状态;

    优先级(priority);

    代码执行入口地址;(代码加载到内存的哪个位置)

    程序的磁盘地址;

    运行统计信息(执行时间、页面调度(缺页);

    进程间同步和通信;阻塞原因

  • 资源占用信息:虚拟地址空间状况、进程页表指针、打开文件列表

  • CPU现场保护结构:寄存器值(通用、程序计数器PC、状态PSW(program status word),栈指针。

进程和线程切换的区别: 线程的切换只是指令的切换,而进程的切换还包括资源区的切换。进程切换:涉及PCB的修改。当运行的进程1要切换到进程2时,将当前CPU的状态用于更新进程1的PCB,即记录进程1运行的上下文。然后将进程2的PCB读入CPU,执行进程2。每个线程都需要创建一个自己的栈。在切换线程的时候需要切换栈。这就需要一个数据结构TCB(线程控制块)来存储栈的指针;每一个线程都有一个TCB,线程切换的时候实际上切换的是一个可以称之为线程控制块的结构TCB。里面保存所有将来用于恢复线程环境所必须的信息,包括所有的寄存器值,线程的状态等等
在这里插入图片描述

  • 当两个线程不是属于同一个进程,则切换的过程就跟进程上下文切换一样;
  • 当两个线程是属于同一个进程,因为虚拟内存是共享的,所以在切换时,虚拟内存这些资源就保持不动,只需要切换线程的私有数据、寄存器等不共享的数据

进程切换和系统调用的区别:

  • 系统调用是从用户态到内核态的转变,需要通过系统调用来完成。比如,当我们查看文件内容时,就需要多次系统调用来完成:首先调用 open() 打开文件,然后调用 read() 读取文件内容,并调用 write() 将内容写到标准输出,最后再调用 close() 关闭文件。
    在这个过程中就发生了 CPU 上下文切换,整个过程是这样的:
    系统调用的切换流程:系统调用触发中断,进入中断处理程序。若中断时,进程在执行用户态的代码,该中断会引起CPU特权级从ring3级到ring0级的切换,CPU会进行堆栈的切换,CPU会从当前任务的TSS中取到内核栈的段选择符和偏移值;CPU首先会上下文保存到内核栈,把原用户态的堆栈指针ss和esp压入内核态堆栈,随后把标志寄存器eflags的内容和此次中断的返回位置cs,eip压入内核态堆栈。当中断处理函数结束后,将恢复内核栈中的数据,并继续处理被中断的进程。每个系统调用内核要进行许多工作,耗时开销大。
    所以,一次系统调用的过程,其实是发生了两次 CPU 上下文切换。(用户态-内核态-用户态)。系统调用过程中,并不会涉及到虚拟内存等进程用户态的资源,也不会切换进程。这跟我们通常所说的进程上下文切换是不一样的:进程上下文切换,是指从一个进程切换到另一个进程运行;而系统调用过程中一直是同一个进程在运行。所以,系统调用过程通常称为特权模式切换,而不是上下文切换。系统调用属于同进程内的 CPU 上下文切换。
  • 进程是由内核来管理和调度的,进程的切换只能发生在内核态。所以,进程的上下文不仅包括了虚拟内存、栈、全局变量等用户空间的资源,还包括了内核堆栈、寄存器等内核空间的状态。简单来说是进程切换主要包括两部分工作: 切换全局页目录以加载一个新的地址空间、切换内核栈和硬件上下文,其中硬件上下文包括了内核执行新进程需要的全部信息,如CPU相关寄存器。

栈空间分配: 进程/线程的创建主要是由 clone 系统调用完成的。而 clone 系统调用的参数中有一个 void *child_stack,它就是用来指向所创建的进程/线程的堆栈指针。而在该进程/线程在用户态下是通过调用 pthread_create 库函数而陷入内核的。对于pthread_create 函数,它则会调用一个名为pthread_allocate_stack 的函数,专门用来为所创建的线程分配的栈空间(通过 mmap 系统调用)。然后再将这个栈空间的地址传递给 clone 系统调用。这也是为什么线程组中的每个线程都有自己的栈空间。

Linux中对进程和内核线程创建的几个系统调用发现, 创建时最终都会调用do_fork()函数,不同之处是传入的参数不同(clone_flags),最终结果就是进程有独立的地址空间和栈 ,而用户线程 可以自己制定用户栈,地址空间和父进程共享,内核线程则 只有和内核共享的一个栈,同一个地址空间。 不管是进程还是内核线程,do_fork最终会创建一个task_struct结构。

go协程调度器: Go调度器是Go runtime的一部分,且Go runtime已经内置于Go程序中。这意味着Go调度器运行在用户态,而不是内核态。当前Go调度器的实现不是抢占式,而是协作式的。协作式调度意味着调度器在做调度决策时,需要明确定义的用户态事件,这些事件发生在代码中的安全点。Go协作式调度器的出色之处就在于它看起来是抢占式的:你无法预测Go调度器将要执行的操作。这是因为协作调度器的决策权并不在开发者手中,而是在Go runtime上。把Go调度器看作是抢占式的,因为它的调度是不确定的,这是很重要的,并且这没什么大不了的。每一个Go程序都自带一个runtime,负责与OS进行交互,⽤户态只需要创建像⼤量的并发任务,中间通过调度器来实现这两个用户和内核上的绑定。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

操作系统的调度基础 的相关文章

  • Minikube 架构及启动流程剖析

    原文作者 wzqnls 编辑 夏天 对于要学习 Kubernetes 或者需要本地开发的开发人员来说 Minikube 是一个不错的选择 通过使用 Minikube 这个工具 我们可以非常快捷地在本地部署一套单节点的 Kubernetes
  • 线程和进程的区别(面试必备)

    参考文章 https www jianshu com p 2dc01727be45 线程与进程的区别通俗的解释 https www jianshu com p 8ad441510860 附加可参考文章 https baijiahao bai
  • 文件管理系统(操作系统)——9张思维导图

    文件管理系统 1 文件管理 1 1 一个文件的逻辑结构 比如一个文本txt文件 又或者Excel文件 在我们用户看来 它是长什么样的 这个就是逻辑结构 几个概念 逻辑结构 就是指在用户看来 单个文件内部的数据应该是如何组织起来的 物理结构
  • CentOS 7 关闭网络限制

    1 安装CentOS 7 3操作系统mini版本即可 2 设置关闭Selinux 编辑 etc selinux config vi etc selinux config SELINUX disabled 重启机器 查看selinux状态 s
  • 设备管理过程

    复杂度2 5 机密度2 5 最后更新2021 04 19 AIX中对设备会有如下五个操作 define aix下能看到设备的定义 但驱动程序并没有加载或初始化 该设备不可用 lsdev看到设备时defined 很多逻辑设备 vg lv等 只
  • Windows 添加永久静态路由

    route add p 10 10 0 0 mask 255 255 0 0 10 10 6 1 p 参数 p 即 persistent 的意思 p 表示将路由表项永久加入系统注册表
  • 红帽7.9部署telnet服务

    升级ssh 为预防万一提前配置telnet服务 安装软件包 yum install telnet server yum install xinetd xinetd加入开机自启 systemctl enable xinetd service
  • LWIP在STM32上的移植

    本文做记录摘抄 加上自己的体会 文章标题 STM32使用LWIP实现DHCP客户端 http www cnblogs com dengxiaojun p 4379545 html 该文章介绍了几点 LWIP源码的内容 关键点 1 inclu
  • 操作系统笔记六(文件管理)

    1 文件逻辑结构 1 1逻辑结构的文件类型 分类 有结构文件 例如 PNG文件 无结构文件 1 2顺序文件 1 3索引文件 2 辅存的存储空间分配 2 1分配方式 连续分配 直接分配连续的存储空间 链接分配 隐式链接 在盘块内指定下一个盘块
  • 自己动手写操作系统(一)

    本系列文章将一步步实现一个简单的操作系统 实验环境是在Linux系统下通过Bochs虚拟机运行我们自己写的操作系统 一 实验环境搭建 1 Ubuntu的安装 Windows用户可以选择在虚拟机中安装Ubuntu 具体安装教程可自行搜索 2
  • Windows运行常用命令(win+R)

    1 calc 启动计算器 2 notepad 打开记事本 3 write 写字板 4 mspaint 画图板 5 snippingtool 截图工具 支持无规则截图 6 mplayer2 简易widnows media player 7 S
  • 使用inet_ntop转换IPv6地址时在macOS和linux上的行为不一样

    下面这段python代码在macOS和linux时运行的结果是不同的 import socket ip socket inet pton socket AF INET6 1 2 3 0 5 6 7 8 print socket inet n
  • Windows驱动开发(一)第一个驱动程序

    首先我们需要了解 在操作系统中 是分两种权限的 一种是内核态 我们也称为0环 一种是用户态 称之为3环 而在我们的电脑中 驱动程序是运行在内核态的 这意味着和操作系统内核是在同一权限的 而普通的应用程序的权限是最低的 高权限谁不想拥有呢 因
  • 内存管理——分页分段

    一 分页存储管理 1 页面与页框 1 页面 将一个进程的逻辑地址空间分成若干个大小相等的片 称为页面或页 并为各页加以编号 2 页框 相应于页面 把内存空间分成和页面相同大小的若干个存储块 称为 物理 块或页框 frame 3 页内碎片 在
  • 操作系统常见面试题

    1 什么是进程 Process 和线程 Thread 有何区别 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动 进程是系统进行资源分配和调度的一个独立单位 线程是进程的一个实体 是CPU调度和分派的基本单位 它是比进程更小的能
  • java IO、NIO、AIO详解

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 一 IO流 同步 阻塞 二 NIO 同步 非阻塞 三 NIO2 异步 非阻塞 正文 回到顶部 概述 在我们学习Java的IO流之前 我们都要了解几个关键词 同步与异步 sy
  • gdb attach 进程调试

    gdb调试正在运行的进程 GDB可以对正在执行的程序进行调度 它允许开发人员中断程序 并查看其状态 之后还能让这个程序正常地继续执行 gdb attach xxxxx xxxxx为利用ps命令获得的子进程process
  • 使用ShellJS提升你的开发效率(一)

    Shelljs Unix shell commands for Node js Shelljs是Node js下的脚本语言解析器 具有丰富且强大的底层操作 Windows Linux OS X 权限 Shelljs本质就是基于node的一层
  • I/O设备模型

    I O设备模型 绝大部分的嵌入式系统都包括一些I O Input Outut 输入 输出 设备 例如仪器上的数据显示屏 工业设备上的串口通信 数据采集设备上用于保存数据的Flash或SD卡 以及网络设备的以太网接口等 I O设备模型框架 R
  • 八股文打卡day20——操作系统(3)

    面试题 线程同步的方式有哪些 我的回答 多线程同时访问和修改某个数据的话 会造成数据的不一致和冲突问题 所以就需要线程同步 线程同步的方式有 1 互斥锁 互斥锁就是 当一个资源被访问和操作时 会对这个资源加锁 把这个资源锁定 其他线程不能对

随机推荐

  • ubuntu学习笔记(慢慢补充)

    ubuntu中更新python环境笔记 前提 基本上安装的ubuntu系统都会自带python3或者其他编程的语言环境 一下操作只是让原有的软件进行升级 更新当前python版本和下载相应依赖 1 sudo apt get update s
  • 数据库服务器系统的 研发,数据库服务器系统的 研发

    数据库服务器系统的 研发 内容精选 换一换 云备份 Cloud Backup and Recovery 为云内的弹性云服务器 Elastic Cloud Server ECS 云耀云服务器 Hyper Elastic Cloud Serve
  • Linux usb设备固定端口号

    Linux usb设备固定端口号 一 sys bus usb devices 二 设备信息 三 固定usb设备名方法 一 sys bus usb devices 信息显示如下 1 0 1 0 1 表示 1 号总线 或者说 1 号 Root
  • Rancher部署

    使用helm方式安装 https blog csdn net zhoumengshun article details 108160704 参考地址 https blog csdn net weixin 47752736 article d
  • 机器学习之数学基础

    机器学习之数学基础 机器学习所需的数学知识 微积分 线性代数 概率论 最优化方法 微积分知识 导数与求导公式 一阶导数与函数的单调性 一元函数极值判定法则 高阶导数 二阶导数与函数的凹凸性 一元函数泰勒展开 偏导数与梯度 高阶偏导数 雅克比
  • android项目迁移到androidX:类映射(content*,multidex*)

    android support content 支持库类 AndroidX 类 android support content ContentPager androidx contentpager content ContentPager
  • ajax传回的数据做表格,Datatables ajax返回的数据顺序与表格中的数据顺序不一致...

    项目中Datatables是采用Ajax作为数据源的 当ajax返回数据后 我查看ajax返回的数据发现 ajax返回的数据顺序与datatables表格中显示的数据顺序不一致 请问如何才能这两者显示一致呢 下面是ajax返回的数据 dat
  • linux 系统对信号的处理,linux内核线程对信号的处理过程(转)

    linux中的线程分为用户线程和内核线程 用户线程是标准的线程 完全的自主性 完全的抢占性 但是内核线程就不那么好了 某种意义上没有用户线程那么清闲 这个怎么理解呢 用户线程的编写者只需要实现应用逻辑就可以 至于调度 信号处理等工作完全有内
  • Gitee上传代码保姆级教程(亲测有效)

    作为一名程序猿or程序媛 怎么能不会使用Gitee上传代码 协同开发呢 今天 一个小白保姆级Gitee上传代码教程他来啦 亲测有效 小伙伴们来trytry吧 前提 1 已经下载过Git Bash 如果还没有下载过 请移步至其他博主的博客下载
  • 嗯嗯

    编写一个程序 可以一直接收键盘字符 如果是小写字符就输出对应的大写字符 如果接收的是大写字符 就输出对应的小写字符 如果是数字不输出 由于键盘每一个符号在c语言中是使用asscii码实现 可以使用范围来判断具体键盘输入的内容 include
  • 【Liunx】Navicat连接ubuntu下mysql

    一 首先准备好 ubuntu虚拟机一台 xftp7 mysql5 7离线包 Navicat软件 二 启动ubuntu虚拟机在主目录下创建mysql文件夹 查询虚拟机ip地址 使用xftp7连接虚拟机上传mysql5 7安装包 创建mysql
  • 基于Numpy构建RNN模块并进行实例应用(附代码)

    文章目录 一 写在前面 二 RNN原理介绍说明 1 RNN架构说明 2 RNN的数学模型及代码 正向传播 输入层 隐藏层 正向传播 隐藏层 输出层 反向传播 输出层 隐藏层 反向传播 隐藏层 输入层 三 RNN在实例中的应用 1 实例问题说
  • 【QT】图形化页面设计

    可视化的图形化界面共有三种设计方式 一种是通过可视化来设计界面的方式 一种是代码化的设计方式 最后是混合上面两种的混合界面设计方式 目前我们只考虑通过Designer和代码来设计图形化页面的两种方式 目录 可视化图形界面设计 图形页面设计
  • 算法小白的自我总结

    2018年10月26号 觉得该把这段时间做一下总结了 大概包括心理变化方面 找工作方面吧 csdn为什么没有表情可以用 并且终于在上线新版之后变得没有那么多bug了 快捷键也能用了 界面看起来还可以 为什么把标志性的红色不见了 红色变成了蓝
  • 使用jquery对输入框内容设置自动校验,只允许数字的输入

    目的 对input输入框的内容进行校验 js的方法 keyup 对键盘的进行监控的事件 正则表达式 d g 原理 就是在输入框添加一个 触发事件 对输入框的内容进行判断 过程遇到问题 js和jquery获取值的方法 value是js获取值的
  • 2021-04-28 Mac上插入公式的三种方法

    文章目录 在线方案 自带的Pages更好用 KLatexformular 在线方案 很多网站可以在线编辑 然后下载图片 给一个我用的链接 https latex codecogs com legacy eqneditor editor ph
  • 整型数据在内存中的存储方式大解密

    提示 先赞后看 养成习惯 文章目录 前言 一 原码 反码 补码 二 体验 存 数据的过程 小小的总结一下 三 体验 取 数据的过程 什么是大小端 如何验证一个机器是大端还是小端的存储模式呢 为什么会有大小端之分呢 取 数据 整型数据范围 前
  • 时序预测

    时序预测 Matlab实现SO CNN GRU蛇群算法优化卷积门控循环单元时间序列预测 目录 时序预测 Matlab实现SO CNN GRU蛇群算法优化卷积门控循环单元时间序列预测 预测效果 基本介绍 程序设计 参考资料 预测效果 基本介绍
  • 获取application.yml文件中配置参数的两个方法

    application yml文件内容 第一种 适用于获取少量配置参数 Value man name private String name 第二种 适用于获取大批量配置参数 第一步 整合pom xml文件
  • 操作系统的调度基础

    操作系统的cpu调度 把内核线程当成内核中的一个进程去理解 任务系统的三个核心特征是 权限分级 数据隔离和任务切换 以X86 64架构为例 权限分级通过CPU的多模式机制和分段机制实现 数据隔离通过分页机制实现 任务切换通过中断机制和任务机