Linux进程概念
Linux进程概念
- 前言
- 冯诺依曼体系
- 操作系统
- 设计操作系统的目的
- 如何理解OS是一款搞“管理”的软件?
- 系统调用和库函数的概念
- 进程的概念
- 描述进程
- 组织进程
- 查看进程
- fork()
前言
本篇博客主要介绍一些:冯诺依曼体系、OS的理解、进程的一些概念;
冯诺依曼体系
我们常见的计算机,比如笔记本;以及我们不常见的服务器等等,大部分都遵循冯诺依曼体系;
截至目前,我们所认识的计算机,都是有一个个的硬件组件组成
输入单元: 包括键盘, 鼠标,扫描仪, 写板等
中央处理器(CPU): 含有运算器和控制器等
输出单元: 显示器,打印机等
关于冯诺依曼,必须强调几点:
1、这里的存储器指的是内存
2、不考虑缓存情况,这里的CPU能且只能对内存进行读写,不能访问外设(输入或输出设备);
那么这里为什么CPU只能从内存进行读取呢?
①、除了冯诺依曼体系结构决定;
②、早期计算机是没有内存的,主要使用为早期的CPU读写速度与磁盘的读写速度相差不大,CPU能够及时的从磁盘读取和写入数据;但是随着科技的进步,CPU是越来越快了,快到磁盘的读写速度已经远远更不上CPU了,这就会造成CPU存在大量的空闲时间来等待数据从磁盘被读取进来,然后才开始处理,这是对于CPU性能的极大浪费!!!!为了解决这个问题,科学家们就创建了一个内存,内存的创建就是为了适应CPU与磁盘读写速度不匹配的问题,现在CPU只需要在内存里面取数据就可以了,因为内存的速度能缓解CPU的读写速度(虽然还是没有CPU快),同时在磁盘的数据,也不会再被直接加载到CPU,而是先加载进内存;当然随着科技的进步,内存也渐渐的不能满足CPU的要求了,于是科学家们,又在内存之上加入了:高速缓存、寄存器等存储结构以此来满足CPU的读写速度;
因此我们日常生活中双击的本质: 就是将存在与磁盘的内容加载进内存;
3、外设(输入或输出设备)要输入或者输出数据,也只能写入内存或者从内存中读取。
4、一句话,所有设备都只能直接和内存打交道、
下面我们站在硬件角度(不考虑软件、网络)来观察一下数据是怎么在计算机中流动的,以此来更加深刻的理解冯诺依曼体系;(以我们登上qq向好友发送信息为例)
操作系统
任何计算机系统都包含一个基本的程序集合,称为操作系统(OS)。笼统的理解,操作系统包括:内核(进程管理、内存管理、文件管理、驱动管理)、其他程序(驱动程序、Shell、函数库等等);
目前主流的操作系统有:Windows、Unix、Linux、Mac OS等;
设计操作系统的目的
1、管理所有的软硬件资源;
2、为用户程序提供良好(安全的、高效的、功能丰富的、稳定的)的运行环境;
如何理解OS是一款搞“管理”的软件?
首先什么是管理?
管理的本质是什么?
举个简单例子:
就比如说学校有:校长、辅导员、学生;(不考虑其他角色,只考虑这三种);
在大学我们一年到头可能都见不到校长几次,但是他却能把我们管的很好;
这是为什么?
就比如学校要举办一个运动会,校长决定好了时间地点,然后就把这项决策下达给了辅导员,辅导员再来转达给我们,我们最后就会去执行校长下达的决策,最后这个运动会就会被漂亮的办起来;
在这里校长处于管理者的位置,管理者所做的工作就是进行决策!
而辅导员是去传达校长的决策的,因为学校很大,不可能让校长单独去对每个学生传达;
你看在这段期间,校长似乎都没有与我们进行任何交流,我们就把运动会办了起来;校长是如何做到的?
主要是因为校长手里掌握着我们学校的面积。比如:操作有多少个、每个操场多大、我们学校总共有多少学生等等;根据这些信息,校长就能做出在哪里举办、什么时候举办运动会的决策;说白了,校长就是在对一些数据做“管理”;
我们在举一个例子来理解管理:
就比如我们学校要选一个学生去参加物理竞赛,作为校长我怎么知道该选那个学生去呢?当然是选物理成绩最高的学生去啊,于是校长在一堆学生信息中筛选出了物理成绩最高的小王,于是他做出了让小王代替我校去参加物理竞赛的决策,然后他把这个决策下达给辅导员,然后辅导员找到小王,让小王去执行校长所作的决策;
我们知道,校长与学生是不见面的(很少见面),那么他是如何拿到学生信息的呢?
答案是通过辅导员,辅导员是直接与学生接触的,校长下发一个学生信息格式,让辅导员们按格式统计这些学生信息、最后在上交给校长;校长不就拿到这些信息了吗,有了这些信息不就可以知道各个学生的情况了吗?该选谁去参加比赛不久一目了然了;
所以,管理的本质就是:管理者对被管理的数据进行处理;
在上面的角色中,学生是被管理者、校长是管理者、辅导员是直接与管理者与被管理者接触的角色,可以理解为帮助提高管理者工作效率的;
那么对应过来,与我们操作系统有什么关系呢?
上文我们说了,OS是一款搞管理的软件;
那么OS对应的就是校长;
硬件对应的就是学生;
驱动程序对应的是辅导员;
管理者与被管理者是不需要直接接触的!!!
上面的例子对比过来就是:驱动程序去统计各个硬件的基本信息、和工作情况等数据,然后上报给OS,OS也自然会接受这些数据,然后将这些数据利用相关的数据结构保存(组织)起来,然后到时候需要哪个硬件进行工作或停止工作,只需要在该数据结构中找到对应硬件的信息,并对这些信息进行处理,就行了,然后将处理过后的结果下达给驱动程序,驱动程序在下达给硬件,硬件就开始执行OS所作出的决策;当然如果那个硬件不能正常工作了,驱动程序也会检测出来然后上报给OS,让OS及时向用户做出反应,这样OS不需要与硬件直接进行接触,也就能把硬件管理好了;
总结:
OS管理硬件:
1、先将各个硬件的基本信息描述起来,利用struct;
2、组织起来,用链表或其他数据结构;
六字真言:先描述,再组织;
系统调用和库函数的概念
1、在开发角度,操作系统对外会表现为一个整体,但是会暴露自己的部分接口,供上层开发使用,这部分由操作系统提供的接口,叫做系统调用。
为什么会存在系统调用?
因为OS不相信我们,但是又要为我们提供良好的服务;这种矛盾关系就好似我们与银行的关系,我们去银行存钱,银行是让我们自己亲自将钱放进银行的金库,然后在登个记吗?当然不是,银行是不会这么做的,因为银行压根不会相信我们,但是银行又要为我们提供良好的服务,为此银行开了一个个小窗口去办理业务,我们只需要将我们的需求通过小窗口告诉银行,我们的业务就会被办理,OS也是这样,为了给我们提供良好的服务,也会提供这样的“小窗口”,专业一点就叫做系统调用,在Linux环境下系统调用本质上就是C语言的函数接口,因为Linux本身就是用C语言写的;
系统调用这个设计可谓是一石二鸟,即保证了OS自身的安全,又为我们提供了良好的服务;
但是我们想要使用这个服务是有代价的,就比如一个一个不识字的人、或者对于银行业务系统完全不了解的人去银行办理业务,就算窗口服务再方便,也无法为这些人提供良好的服务,这时为了帮助这些人顺利完成业务,银行一般都会设置一些大堂经理来专门为这些人“一条龙”服务;对于我们普通程序员来书也是一样的,如果直接让我们去操作系统调用,可能需要我们去提前熟悉一些操作系统相关的知识,这对于我们的开发效率来说比较低,为此一些大佬程序员,在基于这些系统调用的基础上又开发了一些类似于:图形化界面、命令行解释器等Shell工具,(这些工具伴随着操作系统的加载就一并被加载进入了内存)这些工具极大的提升了我们的开发效率;
实际上我们在日常的编程语言学习中也是经常的使用系统调用,比如最常见的printf、scanf函数的实现一定是调用了输入输出的系统调用;
2、系统调用在使用上,功能比较基础,对用户的要求相对也比较高,所以,有心的开发者可以对部分系统调用进行适度封装,从而形成库,有了库,就很有利于更上层用户或者开发者进行二次开发。
进程的概念
在学习进程之前呢,我们可以先尝试者根据上面的六字真言解释一下OS是如何管理进程的;
很简单,先把进程这个东西所拥有的属性给抽象出来(这里我们可以把进程类比于一个学生,现在我们要将学生的基本信息抽象出来);然后呢利用合理的数据结构将这些属性组织起来;到时候OS对于进程的管理,就变成了对于进程数据信息的管理;
一般的进程的概念被理解为:进程是指在系统中正在运行的一个应用程序。
这样的专业术语对于我们初学者来说并不能很好的理解什么是进程;
下面我们来介绍一个比较好理解的进程的定义:
首先我们如果想要执行我们的程序的话,首先要把我们的数据从外设加载进内存,然后被CPU执行;
可是我们不能随意乱加载进内存啊,我们得让操作系统知道加载进内存的程序的基本信息吧,这样的话才好让OS开展工作(发挥管理的作业);
为此对于加载进内存的每一个程序,OS都会对其进行统计和编号,并把这些信息统计起来存入对应的节点中;只有完成这一步才能将这个程序叫做进程!!
为此,我们总结一下进程的概念:进程=内核关于当前程序的信息+当前程序的代码和数据;
描述进程
上面我们说了,每个被加载进内存的程序的信息,都会被OS统计起来,其中统计这些被加载进内存的程序的信息的节点,被称为PCB(process control block),Linux环境下PCB具体表现为:task_struct结构体;
task_struct是Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包含着进程的信息;
其中结构体里面包含的信息有:
标示符: 描述本进程的唯一标示符,用来区别其他进程。
状态: 任务状态,退出代码,退出信号等。
优先级: 相对于其他进程的优先级。
程序计数器: 程序中即将被执行的下一条指令的地址。
内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
上下文数据: 进程执行时处理器的寄存器中的数据.
I/ O状态信息: 包括显示的I/O请求,分配给进程的I/ O设备和被进程使用的文件列表。
记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
其他信息
组织进程
所有运行在系统里的进程都以task_struct链表的形式存在内核里;
查看进程
要想查看一个进程的基本信息,我们可以利用命令
ps -axj
列出当前系统所用进程信息;
现在我们可以先写一小段代码来看看进程:
测试代码:
#include<stdio.h> #include<unistd.h>int main(){while(1){printf("这是一个进程\n");sleep(1);}return 0;}
利用命令ps -axj | head -1 && ps -axj | grep "process"
,获取表头和带有process的关键字的进程:
这其中PID就相当于这个进程的学号,每个进程都是唯一的,我们可以看到我们的进程的的PID是22475;
当然我们也可以去系统文件夹下(/proc)寻找当前进程的文件夹:
proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为访问系统内核数据的操作提供接口。
ll /proc | grep "22475"
筛选出pid为22475的进程的文件:
在此文件夹下有很多我们不认识的文件;
当我们想要结束掉某个进程时,我们可以利用快捷键:Ctrl+c;
或者利用命令:kill -9 pid
当这个进程被杀掉过后对应的proc目录下也会同步删除这个进程的信息:
下面我们测试一下看看:
系统表示没有找到对应文件夹;
下面我们来写一个可以自动获取自己pid的程序:
为此我们需要使用一个系统调用:
getpid(),注意这是系统调用,是OS提供给我们的,不是C语言库函数!
用之前我们先来了解一下:
测试代码:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{while(1){printf("这是一个进程,我的pid是:%d\n",getpid());sleep(1);}return 0;
}
我们利用ps命令验证一下:
我们发现利用ps查到的和getpid获取的pid是一致的;
fork()
接着我们介绍一些新的概念;
PPID:当前进程的父进程的PID;
这个我们也可以利用系统调用接口getppid获取;
测试代码:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{while(1){printf("这是一个进程,我的pid是:%d,我的父进程的pid是(ppid):%d\n",getpid(),getppid());sleep(1);}return 0;
}
我们多次重新运行该进程:
我们可以发现,在多次重复运行同一个进程,该进程每次对应的pid是变化的;
这很好理解嘛,每个进程的pid都是OS分配的,不可能每次进来都给你分配相同的pid,就好比,你第一次考上了A大学,学校给你分配了个学号1234,但是你决定去复读,但是第二年又考上了A大学,A大学同样给你分配学号,只不过这次就不是1234,而是4321;OS给进程分配PID也是如此;
但是我们却发现,尽管每次进程的pid不一样,但是该进程的ppid是一样的,也就是说该进程每次进来都是同一个进程的“儿子”;
接下来我们来通过ps命令查一下,pid为21186是谁?
是bash,就是命令行解释器或者说Shell!!!
我们在讲解Shell运行原理的时候讲解过Shell的一个作用就是:执行命令的时候可以创建子进程来执行
同时Shell本身也是一个程序,只是在加载操作系统的时候一起被加载进内存了;
也就是说当我们输入命令./process
shell获取到该命令,然后对该命令向OS进行解释:shell告诉OS,用户想要运行这个程序,你赶紧登记一下这个程序的信息,并且给这块程序开一个进程;
名义上是shell向OS申请的进程来运行加载进来的程序,因此我们把Shell称为一切从命令行进来的程序的父进程!
这里我们需要注意Shell是没有能力创建进程的,创建进程的实际操作是又OS完成的!Shell只是向OS申请;
好,既然Shell也是一个进程,那我们能不能把shell也杀掉?
当然可以,只不过杀掉过后,我们的所输入命令OS就不认识了,OS自然也就无法做出任何反应;
下面我们来实际操作一下:
我们可以看到,我们直接被踢出了Linux服务器!
如果要恢复Shell的话,重新登陆xShell就行了;
总结一下上面:
1、Shell本质上也是一个进程;
2、从Shell启动的程序都将变成进程,而该进程对应的父进程就是Shell
3、Shell可以向OS申请创建子进程
接着我们继续下一个话题,既然Shell可以创建子进程,那么我们能不能在自己的程序里面也创建子进程?就是不是利用从Shell进入的方式创建子进程;
当然可以,OS为我们提供了一个接口fork:
fork简介:
对于其返回值的介绍就是:如果进程创建成功,则给父进程返回其创建的子进程的pid,给其子进程创建的子进程返回0;进程创建失败返回-1;
看起来怪怪的,我们先用用看看;
测试代码:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{printf("AAAAAAAAAAAAAAAAAAAAA\n");fork();printf("BBBBBBBBBBBBBBBBBBBBB\n");return 0;
}
这似乎与我们之前学的C语言有些出入,为什么会打印两次B?
那么一定是printf(“BBBBBBBBBBBB\n”);被执行了两次;
为此我们可以先简单理解:
接下来我们来验证不同的进程下,所执行的代码:
测试代码:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{pid_t ret= fork();if(ret>0){//这是父进程while(1){printf("我是父进程,我的pid是:%d,我的ppid是:%d,ret=%d,&ret=%p\n",getpid(),getppid(),ret,&ret);sleep(1);}}else if(ret==0){//这是子进程while(1){printf("我是子进程,我的pid是:%d,我的ppid是:%d,ret=%d,&ret=%p\n",getpid(),getppid(),ret,&ret);sleep(1);}}else{printf("创建失败\n");}return 0;
}
通过父进程的pid和子进程的ppid,我们可以确定父子连个进程执行了不同的代码;
其中父进程的ret接收到的的确是子进程的pid,子进程ret接受到的也的确是0;
但是为我们可能会疑惑为什么ret能取出来两个不同的值,明明父子进程中ret的地址都是一样的;
难不成fork能返回两个值?
当然不是;
我们可以先从一下几个问题入手,简单了解一下fork原理:
1、fork函数做了什么?
这不废话吗,当然是进行分流,创建子进程啊,我们首先知道当再一个函数中我们执行到return语句的时候,是不是就代表着该函数的主题功能已经完成了?也就是说我们当前的子进程已经创建好了,我们返回return只是想向调用该函数的主体报告完成结果;也就是说,从fork中return语句开始执行流就已经开始进行分流了;那么对于父进程来说return自然返回的是子进程的pid,对于子进程来说return自然返回的是0;
2、fork如何看待–代码和数据?
首先我们得有个常识性意识:我们再关闭微信这个进程的时候是不影响我画图这个进程的,同理我关闭Eage浏览器这个进程也是不会影响我CCtalk这个进程的,换而言之兄弟进程之间都是互相独立,互不影响的,父子进程之间也是如此!!!;
为此我们可以测试:
我们可以看到当前进程既有父进程,又有子进程;
现在我杀掉子进程:
我们可以看到当前只有父进程并且还运行的好好的;
我们杀掉父进程也是可以的,只不过此时子进程因为没了父亲,被叫做 “孤儿进程”;我们后面会讲解这个进程;
fork是在PCB链表后面在增加一个pcb节点,并以继承父进程的方式来填充该新pcb节点,当然也不是全部继承,子进程的pcb也有自己的隐私,比如pid;但是在代码和数据方面刚开始时与父进程共享同一块;不是我们想象在内存空间中再拷贝一份一摸一样的数据:
既然是共享同一块数据,那么父子进程是如何实现独立互不影响?
代码:代码被编译完毕一直都是只读的,父子进程各读各的代码片段,互不影响可以实现独立,这个好理解;
数据:既然要实现独立,就不能从原始空间读取数据并进行修改,必需是两个独立的空间,为此当某一个进程里的执行流尝试修改数据数据的时候,OS会自动给我们当前的数据进行写时拷贝;
什么时写时拷贝?
就是当OS检测到子进程有写的操作的时候,OS才会给子进程分配相应的物理空间;
我们回到开始的问题:为什么ret能取出来两个不同的值,明明父子进程中ret的地址都是一样的?
ret在接受fork的值时候就已经创建好子进程了,执行流就已经开始分流了,然后再将fork的返回值写入ret中,触发了“写时保护”,实际fork是对两个互不相干的内存空间中的ret进行写入,自然从不同的进程中取出ret来时值是不一样的,但是地址是一样的结果!因为我们使用的虚拟地址!
我们平常写的C/C++代码中用到的内存地址也是虚拟内存地址!!
相关文章:
Linux进程概念
Linux进程概念前言冯诺依曼体系操作系统设计操作系统的目的如何理解OS是一款搞“管理”的软件?系统调用和库函数的概念进程的概念描述进程组织进程查看进程fork()前言 本篇博客主要介绍一些:冯诺依曼体系、OS的理解、进程的一些概…...
算法设计与分析
两个例子:调度问题与投资问题 例1:调度问题 问题 有 n 项任务,每项任务加工时间已知.从 0时刻开始陆续安排到一台机器上加工. 每个任务的完成时间是从 0 时刻到任务加工截止的时间. 求: 总完成时间(所有任务完成时间之和)最短…...
C++ 基础
命名空间 在 C/C 中,变量、函数和类都是大量存在的,这些变量、函数和类的名称将都存在全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace 关键字的…...
[golang gin框架] 2.Gin HTML模板渲染以及模板语法,自定义模板函数,静态文件服务
一.Gin HTML 模板渲染全部模板放在一个目录里面的配置方法首先在项目根目录新建 templates 文件夹,然后在文件夹中新建 对应的index.html<!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta http…...
数据仓库层Repository(CrudRepository、PagingAndSortingRepository、JpaRepository)
什么是数据仓库层Repository? 数据仓库接口的作用:Repository原意指的是仓库,即数据仓库的意思。Repository居于业务层和数据层之间,将两者隔离开来,在它的内部封装了数据查询和存储的逻辑。 Repository接口ÿ…...
大数据技术架构(组件)33——Spark:Spark SQL--Join Type
2.2.2、Join Type2.2.2.1、Broadcast Hash Join (Not Shuffled)就是常说的MapJoin,join操作在map端进行的。场景:join的其中一张表要很小,可以放到Driver或者Executor端的内存中。原理:1、将小表的数据广播到所有的Executor端,利用collect算子…...
Linux: bash起后台进程引发的僵尸进程
1. 前言 限于作者能力水平,本文可能存在谬误,因此而给读者带来的损失,作者不做任何承诺。 2. 案例 原来的故事是 这样 的,感兴趣的读者可以直接前往。我从中截取了一段重现故事中问题的代码(对原代码做了小小调整&a…...
网络安全攻防中,Rock-ON自动化的多功能网络侦查工具,Burpsuite被动扫描流量转发
网络安全攻防中,Rock-ON自动化的多功能网络侦查工具,Burpsuite被动扫描流量转发。 #################### 免责声明:工具本身并无好坏,希望大家以遵守《网络安全法》相关法律为前提来使用该工具,支持研究学习ÿ…...
电子技术——共模抑制
电子技术——共模抑制 我们在之前学习过,无论是MOS还是BJT的差分输入对,共模信号并不会改变漏极电流的大小,因此我们说差分输入对共模信号无响应。但是实际上由于各种客观非理想因素,例如电流源有限阻抗等,此时共模是影…...
对KMP简单的理解
声明:下边的例子均表示下标从1开始的数组 ne数组的定义: next[i] 就是使子串 s[1…i] 有最长相等前后缀的前缀的最后一位的下标。ne[i]也可以表示相等子串的长度 准备执行jne[j]时, 表示当前s[i]!p[j1] , 如果ne[j]1 ,那么下…...
Hibernate不是过时了么?SpringDataJpa又是什么?和Mybatis有什么区别?
一、前言 ps: 大三下学期,拿到了一份实习。进入公司后发现用到的技术栈有Spring Data Jpa\Hibernate,但对于持久层框架我只接触了Mybatis\Mybatis-Plus,所以就来学习一下Spring Data Jpa。 1.回顾MyBatis 来自官方文档的介绍:MyBatis 是一款…...
数学建模拓展内容:卡方检验和Fisher精确性检验(附有SPSS使用步骤)
卡方检验和Fisher精确性检验卡方拟合度检验卡方独立性检验卡方检验的前提假设Fisher精确性检验卡方拟合度检验 卡方拟合度检验概要:卡方拟合度检验也被称为单因素卡方检验,用于检验一个分类变量的预期频率和观察到的频率之间是否存在显著差异。 卡方拟…...
【Python学习笔记之七大数据类型】
Python数据类型:Number数字、Boolean布尔值、String字符串、list列表、tuple元组、set集合、dictionary字典 int整数 a1 print(a,type(a))float浮点数 b1.1 print(b,type(b))complex复数 c100.5j print(c,type(c))bool布尔值:True、False,true和false并非Python…...
Android系统之onFirstRef自动调用原理
前言:抽丝剥茧探究onFirstRef究竟为何在初始化sp<xxx>第一个调用?1.onFirstRef调用位置<1>.system/core/libutils/RefBase.cpp#include <utils/RefBase.h>//1.初始化强指针 void RefBase::incStrong(const void* id) const {weakref_i…...
ipv6上网配置
一般现在的宽带都已经支持ipv6了,但是需要一些配置才能真正用上ipv6。记录一下配置过程。 当前测试环境为移动宽带,光猫下面接了一个路由器,家里所有的设备都挂到这个路由器下面的。 1. 光猫改桥接 光猫在使用路由模式下,ipv6无…...
python实现聚类技术—复杂网络社团检测 附完整代码
实验内容 某跆拳道俱乐部数据由 34 个节点组成,由于管理上的分歧,俱乐部要分解成两个社团。 该实验的任务即:要求我们在给定的复杂网络上检测出两个社团。 分析与设计 实验思路分析如下: 聚类算法通常可以描述为用相似度来衡量两个数据的远近,搜索可能的划分方案,使得目标…...
如何判断两架飞机在汇聚飞行?(如何计算两架飞机的航向夹角?)内含程序源码
ok,在开始一切之前,让我先猜一猜,你是不是想百度“二维平面下如何计算两个移动物体的航向夹角?”如果是,那就请继续往下看。 首先,我们要明确一个概念:航向角≠航向夹角!࿰…...
Scipy稀疏矩阵bsr_array
文章目录基本原理初始化内置方法基本原理 bsr,即Block Sparse Row,bsr_array即块稀疏行矩阵,顾名思义就是将稀疏矩阵分割成一个个非0的子块,然后对这些子块进行存储。通过输入维度,可以创建一个空的bsr数组࿰…...
LeetCode笔记:Weekly Contest 332
LeetCode笔记:Weekly Contest 332 1. 题目一 1. 解题思路2. 代码实现 2. 题目二 1. 解题思路2. 代码实现 3. 题目三 1. 解题思路2. 代码实现 4. 题目四 1. 解题思路2. 代码实现 比赛链接:https://leetcode.com/contest/weekly-contest-332/ 1. 题目一…...
autox.js在vscode(win7)与雷神模拟器上的开发环境配置
目录 下载autox.js 安装autox.js? 在电脑上搭建autox.js开发环境 安装vscode 安装autox.js插件 雷神模拟器连接vscode 设置雷神模拟器IP 设置autox.js应用IP地址等 下载autox.js 大体来说,就是一个运行在Android平台上的JavaScript 运行环境 和…...
创建阿里云物联网平台
创建阿里云物联网平台 对云平台设备创建过程做记录,懒得再看视频 文章参考视频:https://www.bilibili.com/video/BV1jP4y1E7TJ?p26&vd_source50694678ae937a743c59db6b5ff46c31 阿里云:https://www.aliyun.com 1.物联网平…...
【链式二叉树】数据结构链式二叉树的(万字详解)
前言: 在上一篇博客中,我们已经详解学习了堆的基本知识,今天带大家进入的是二叉树的另外一种存储方式----“链式二叉树”的学习,主要用到的就是“递归思想”!! 本文目录1.链式二叉树的实现1.1前置说明1.2结…...
Koa2篇-简单介绍及使用
一.简介koa2是基于 Node.js 平台的下一代 web 开发框架, 致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 可以避免异步嵌套. express中间件是异步回调,Koa2原生支持async/await二.async/awaitconst { rejects } require("assert"); const { resolve } req…...
Linux ALSA 之十一:ALSA ASOC Path 完整路径追踪
ALSA ASOC Path 完整路径追踪一、ASoc Path 简介二、ASoc Path 完整路径2.1 tinymix 设置2.2 完整路径 route一、ASoc Path 简介 如前面小节所描述,ASoc 中 Machine Driver 是 platform driver 和 codec driver 的粘合剂,audio path 离不开 FE/BE/DAI l…...
【Spring Cloud总结】1、服务提供者与服务消费者快速上手
目录 文件结构 代码 1、api 1.1实体类(Dept ) 1.2数据库 2、provider 2.1 DeptController 2.2 DeptDao 2.3 DeptService 2.4 DeptServiceImpl 2.5 application.yml 3、consumer 3.1 ConfigBean 3.2 DeptConsumerController 测试 1.启动…...
若依项目学习之登录生成验证码
若依项目学习之登录生成验证码 使用DefaultKaptcha生成验证码 /*** 验证码配置* * author ruoyi*/ Configuration public class CaptchaConfig {/*** 生成字符类型的验证码**/Bean(name "captchaProducer")public DefaultKaptcha getKaptchaBean(){DefaultKaptcha…...
计算机网络5:数据在两台计算机之间是怎样传输的?
数据在两台计算机之间的传输总的来说包括了封装和解封两个过程 封装(5层协议) 以传送一张图片为例 **应用层:**将jpg格式的图片数据转化成计算机可以识别的0101的二进制的比特流 **传输层:**将应用层传输下来的数据进行分段&…...
就现在!为元宇宙和Web3对互联网的改造做准备!
欢迎来到Hubbleverse 🌍 关注我们 关注宇宙新鲜事 📌 预计阅读时长:8分钟 本文仅代表作者个人观点,不代表平台意见,不构成投资建议。 如今,互联网是各种不同的网站、应用程序和平台的集合。由于彼此分离…...
【mysql数据库】
目录SQL数据库分页聚合函数表跟表之间的关联关系SQL中怎么将行转成列SQL注入将一张表的部分数据更新到另一张表WHERE和HAVING的区别索引索引分类如何创建及保存MySQL的索引?怎么判断要不要加索引?索引设计原理只要创建了索引,就一定会走索引吗…...
【测试开发】web 自动化测试 --- selenium4
目录1. 什么是自动化为什么要做自动化2. 为什么选择selenium作为我使用的web自动化工具3. 什么是驱动?驱动的工作原理是什么5. 第一个自动化程序演示6. selenium基本语法6.1 定位元素的方法6.2 操作页面元素6.3 等待6.4 信息打印获取当前页面句柄,窗口切…...
空调维修技术支持东莞网站建设/腾讯新闻潍坊疫情
文章目录前言一:测试步骤1.授权2.信息收集3.扫描4.利用5.提权(shell环境、桌面环境、最高权限)6.灭迹7.留后门8.渗透测试报告二、具体流程1.scanport扫描445端口2.利用IPC$: 进行破解:NTscan3.相关命令行4.制作5.植入&…...
做营销型网站 推广的好处/百度旗下产品
阅读本文大概需要 6.8 分钟。Linux 系统大家一定不陌生,学习工作中肯定会和 Linux 打交道。不过谈及 Linux,给人的第一印象可能就是黑乎乎的命令行,乱七八糟的文件夹,甚至安装软件都不知道是怎么安装上去的。其实这些都是用惯了 W…...
网站制作多少钱400/企业培训体系搭建
众包测试 什么是众包测试? 众包测试使用的是众多专家测试人员进行手动测试。测试人员旨在发现错误、记录可重现的步骤并提供错误报告。 众包测试有什么好处? 与内部 QA 相比,众包测试是一种具有成本效益的选择。 由于可用的测试人员数量众…...
工程信息网站谁做/百度新闻客户端
Introduction 参考链接:2014斯坦福大学机器学习视频 本篇是针对当凭直觉做完一个Baseline以后,如何提高现有的识别率?依然凭直觉有以下几种方法: 1、增加训练数据集 2、挑选出更少的特征 3、增加其他特征 4、增加多项式x1*x2 5、减少…...
wordpress++分页/宁波超值关键词优化
一个无锁消息队列引发的血案(四)——月:RingQueue(上) 自旋锁 - shines77 - 博客园 #ifndef _RINGQUEUE_ #define _RINGQUEUE_#include <stdbool.h> #include <stdio.h> #include <string.h>// 队列包含的信息 typedef str…...
网站建设免费模板/百度推广助手官方下载
Service Service 是一个组件,用来执行长时间的后台操作,不提供用户界面。 另一个应用组件可以启动一个Service,它将持续地在后台运行,即便是用户转移到另一个应用它也不会停止。 另外,Service可以和另一个组件绑定&…...