Linux之进程
一.冯诺依曼体系
在计算机中,CPU(中央处理器)是不直接跟外部设备直接进行通信的,因为CPU处理速度太快了,而设备的数据读取和输入有太慢,而是CPU以及外设直接跟存储器(内存)打交道,外部设备将数据输入进内存中,然后CPU从内存中读取数据,运算完数据再将数据放回内存,然后输出设备就从内存中读取数据,这一个体系的好处就是可以很好的利用了CPU的高速运算的优势
二.操作系统
2.1什么是操作系统
操作系统就是一个软件,它管理计算机的所有的软硬件资源,包括进程管理,内存管理,文件管理,驱动管理
2.2.什么是管理
计算机软件体系
像我们用过的cout函数就是会贯穿这整一个软件体系。
在上面那个图中,操作系统相当于大脑,而驱动程序就相当于四肢,硬件设备就相当于武器,为了很好的管理四肢,就需要用到先描述再组织的方法,就是说大脑先要知道每个肢体的具体属性,然后将他们以结构体的形式描述出来,最后将每个肢体再通过链表的方式组织起来,方便查找管理。
2.3操作系统如何向上一层提供基本功能呢
OS是不信任任何用户的,那么OS就通过系统调用接口来给用户提供基本功能,这样子就可以防止恶意用户对于操作系统的破坏
2.4系统调用接口与库函数的关系
上下级关系!
库函数一定是在系统调用之上的,将系统调用进行封装,然后供用户去使用!
三.进程的概念
3.1什么是进程(笼统认识)
在书本中,加载到内存中的程序,就叫做进程。
而我们上面有说过操作系统管理的理念是先描述再组织,由于在操作系统中有大量的进程,那么按照先描述再管理的理念,如果描述进程呢?Linux中采用的是PCB(进程控制块)来描述进程
PCB又是什么呢?
task_struct里面有什么属性字段?
进程是怎么看的?
程序运行起来之后,在linux中使用命令ps axj | head -l && ps axj | grep "目标文件" 来查看运行中的进程
曾经我们所有的启动程序的过程,本质都是在系统上面创建进程
那么程序和进程有什么区别呢?
在我们打开磁盘上的可执行文件的时候,那么可执行程序就会被加载到内存当中,然后操作系统为了管理这一段在内存中的程序,就会生成一个PCB(进程控制块)来管理它,所以说,从操作系统的角度,我们知道进程就相当于程序文件内容+与进程相关的数据结构
在上面这个图中,绿色的小框框表示进程代码+数据,红色的小框框表示包含了进程内部所有属性的进程控制块,各个进程控制块会以链表的方式连接在一起,这样子操作系统就可以通过先描述再组织的方式来管理各个进程了,而操作系统想要管理进程只需要管理进程地址控制块,就可以达到管理进程的效果,所以说有了进程控制块,所有的进程管理任务与进程对应的程序毫无关系!!!,与进程对应的内核创建的该进程的PCB强相关!
进程和程序的区别:进程 = 程序 + 操作系统维护进程的相关数据结构!
3.2 PCB的内部构成
标识符:
获取进程pid的方法:系统调用:getpid(),getppid(),其中getppid()是获取父进程的pid。
tips:两种方式杀掉进程:1.ctrl + c,2. kill -9 进程pid
状态:
包括进程结束时候的返回值,退出码,如main函数的return 0,exit(0);还包括进程运行时候的运行状态,等待状态,死亡状态,阻塞状态,挂起状态
优先级:
因为CPU资源是有限的,而进程控制块的数量却有很多,所以CPU想要运行不同的进程,就会有先后顺序,那么就会排队,就会有优先级问题
I/O状态信息:
这里的I/O是指进程打开了文件,然后从设备/文件中读数据,然后向设备/文件中写数据
记账信息:
在操作系统中,有个调度模块,它可以较为均衡的调度每个进程获取CPU资源,保证每个进程都可以被执行,该记账信息就包括了该进程占用的所有的软硬件资源的总和,这样子调度模块就根据这个记账信息来均衡的调度每个进程获取CPU资源
3.3 如何理解上下文数据:
在CPU中,有很多的寄存器,里面存放着正在运行的进程的临时数据;在操作系统中,有着很多进程,每一个进程都需要占用CPU中的寄存器资源来执行自己的程序代码,并且进程的代码可能不是很短的时间就能运行完毕,如果,有一个进程的执行时间很久,并且CPU一直在运行它,那么其他进程的程序和代码就不能运行,这样子就很不公平,
所以说,操作系统规定了每个进程单词运行的时间片,比如10ms,如果某个进程在CPU中运行的时间超过10ms,就会暂定该进程的运行,然后将该进程的运行数据从CPU寄存器中拷贝下来放入到PCB中,然后将该PCB放到运行队列的尾部,让它重新排队,因此我们用户感受到的是多个进程是在同时运行的,这个本质就是CPU的快速切换PCB完成的
由于CPU中的寄存器只有一套,如果进程1占用了CPU的寄存器,然后时间片一过,CPU切换了另外的进程,当CPU再次切换运行进程1的时候,由于没有保存它之前的上下文数据,那么就不能恢复出它的上下文数据,它的临时运行数据就会丢失,所以说CPU在对进程进行切换的过程a中,就需要保存上下文,还要恢复上下文
有了保存上下文和恢复上下文,那么进程就可以在CPU不断切换进程的过程中,保证继续执行上次被切换之前的程序,并且保证上次运行过程中产生的临时数据不会丢失
所以说这里说的上下文数据就是进程在运行的过程中,在CPU寄存器中产生的与进程强相关的临时数据
tips:另外一个查看进程的方法:ls /proc
每创建一个进程,都会在这个/proc目录下创建一个以该进程pid命名的文件夹,这个文件夹中包含了该进程运行中的属性,我们打开该文件夹,发现这个进程有一个exe属性,它表示当前进程在执行哪个文件,还有一个cwd属性表示当前工作路径,这里的当前工作路径就解释了为什么在代码中可以直接找到并使用当前工作目录下的文件
四.子进程
4.1创建子进程
系统调用接口: pid_t fork(void)
在执行这段代码的时候,我们发现,有两个进程 ,执行了同一段代码
上图可以看出进程28787的父进程是28786,而进程28786的父进程是26555
这里的26555是什么呢?
是bash进程:
就相当于bash创建了进程28786,然后进程28786又创建了进程28787
tips:如何在不退出vim的情况下,查看man手册?在命令行输入!man xxx 即可,同理,在命令行输入!make 就可以编译程序,在命令行输入!./xxxx 就可以运行程序
4.2 如何理解fork创建子进程?
1.在Linux中创建进程又三种方式:1. ./xxx执行可执行程序,2. 命令行执行命令 3. fork()
在操作系统角度,上面的创建进程的方式,没有差别
2. 当我们调用fork()创建子进程的时候,那么系统中就多了个进程,就相当于多了一个描述进程相关的内核数据解雇还有进程的代码和数据,这个子进程的代码和数据继承自父进程的代码和数据,它的内核数据结构也会以父进程作为模板,这就解释了为什么上面执行的代码会重复执行两次,因为子进程继承了父进程的代码,
所以说,子进程和父进程代码和数据是共享的 ,不过代码是不可以修改的,数据是可以修改的,但是我们知道,进程之间具有独立性,那如果子进程修改了数据,会影响父进程的数据嘛?答案是不会,因为操作系统通过写诗拷贝的方法来保证进程间数据的独立性
tips:什么是写时拷贝?
进程1和进程2共享数据a,他们在内存中共享同一块地址空间,当进程1想要修改a的时候,操作系统会重新在内存中开辟一个新的空间存放修改过后的a的值,然后进程1中a的值指向这个地址,这样子就可以解决创建进程时,造成的空间浪费问题。
3.fork()的返回值
当我们调用下面这段代码的时候,我们发现
结果有两个不同的返回值,说明父进程返回了子进程的pid,而子进程返回了0;
1.如何理解有两个返回值呢?
当调用fork函数,到达return语句之前,说明子进程已经被创建出来了,此时父进程和子进程共同去执行return语句,就会发生写时拷贝,造成返回值不同
2.如何理解两个返回值的设置
因为父进程跟子进程的数量关系是一对多的,就是父进程可以有多个子进程,所以就给父进程返回了子进程的pid,而子进程只有一个父进程,通过调用getppid即可获得父进程的pid
我们创建子进程,难度就是为了让父子进程做一样的事情嘛,不是的,这样子没有意义,所以我们结合fork返回值,通过if else分流,让父子进程做不一样的事情
输出结果:
在上面,我们可以看到,子进程和父进程在做不一样的事情
五.进程的状态
进程的状态信息在哪里呢?
在task_struct(PCB)中
进程状态的意义:方便操作系统快速判断进程,完成特定的功能,比如调度,例如,当进程处于挂起阻塞状态时,操作系统就不会调度这个进程;它的本质是一种分类
5.1 R状态
R状态是什么?
R状态是运行态,进程处于该状态不一定占用CPU资源
R状态的意义:
在操作系统中,有一个运行队列,里面存放着进程的控制块(PCB),CPU从这个队列中读取PCB,来运行每一个进程,而处于这个队列中的进程都是处于R状态,就是运行状态
R状态验证:
调用
5.2 S状态和D状态T状态
当我们想要完成某种任务的时候,任务条件不具备,需要进程进行某种等待时,就需要S和D状态,比如,进程想要从网卡,磁盘,显示器等外设读取数据的时候,但是这些外设还没有就绪,那么进程就会进入等待状态,在这个等待过程中,该进程不会被调度,直到外设准备就绪,该进程就会从等待队列中剥离出来,然后状态修改为R状态,被放入运行队列中等待CPU处理
所谓的进程,在运行的时候,有可能因为运行需要,可以会在不同的队列里!!!在不同的队列里,所处的状态是不一样的!
tips:当进程在等待CPU资源的时候,他处在运行队列中,当进程等待外设资源时,它处于等待队列中
我们把,从运行状态的task_struct(run_queue),放到等待队列中,就叫做挂起等待(阻塞),从等待队列,放到运行队列,被CPU调度就叫做唤醒进程!!
S状态:可中断睡眠状态,就是说该进程处于该抓状态时可以随时被终止
D状态:深度睡眠状态,如果该进程处于该状态时不可以被终止,就比如,进程要从磁盘中写数据时,进程等待磁盘响应,这个等待过程中,为了防止进程被操作系统杀掉,就变为D状态。
T状态:暂停状态,进程处于这个状态所有的数据都暂停更新了
S状态验证:
由于CPU的处理速度远大于显示器的读写速度,所以进程的大部分时间都处于S状态
T状态验证:
通过Kill命令发送stop信号来验证T状态
tips:状态后面带+号,说明该进程是前台进程,可以通过ctrl + c杀掉进程,但是在进程运行期间,不能输入命令行, 状态后面不带+号,说明该进程是后台进程,不可以通过ctrl + c杀掉进程,可以通过Kill -9 pid杀掉,在进程运行期间,可以输入命令行,
5.3X状态和Z状态
X状态:称为死亡状态,进程处于该状态,就会回收进程资源,包括进程相关的内核数据结构以及代码和数据
Z状态:称为僵尸状态,进程在死亡之前,操作系统会将进程的退出信息写入到PCB中,等待父进程或操作系统回收,这一过程称之为僵尸状态
为什么会有僵尸进程呢?因为操作系统或是父进程需要知道子进程是因为什么原因结束进程的,如果没有僵尸状态,那么进程因何而死就无从得知。
如果大量的僵尸进程不回收,就会造成内存泄漏问题
验证僵尸进程:
代码:
程序正常运行的时候:状态为S:
发出杀掉进程的命令:
进程状态变为Z:
TIPS:在子进程运行期间,父进程挂掉了,那么子进程就被称为孤儿进程,他的退出信息将由操作系统来回收
六.进程优先级
一.什么是进程优先级
优先级是什么?谁先做什么,谁后做什么?优先级本质是分配资源的一种方式
为什么会有优先级
因为资源太少,每个进程都需要获得资源,那就需要排队,所以就有了各种队列,所以就有了优先级来决定哪个进程先获得资源,哪个进程要后获得资源
tips:
程序转后台运行:
在执行程序后面加&
程序转前台运行:命令行输入fg
查看进程优先级命令:ps -al
上面的PRI和NI组合就是进程优先级,PRI的值越小,优先级越高,越容易获得某种资源
tip: UID表示的是谁启动了这个程序,就相当于我的用户名在操作系统的编号
PRI和NI的关系:
二.调整优先级
通过Top命令来调整优先级
更改NI值为10
显示优先级结果,这里的PRI = 80 + 10
如果设置更改NI值为5
显示优先级结果,这里的PRI = 80 + 5
为什么上面更改NI值为10后,新的PRI = 90,而后面在该基础上更改NI值为5,却变成了85呢?
因为PRI(new) = PRI(old) + NI,这里的PRI(old)一般情况下是等于80的,不会变。NI值得变化范围在-20到19
为什么NI值要是一个相对比较小得范围呢?
因为优先级再怎么设置,也只能是一种相对得优先级,不能出现绝对的优先级,不然就会有进程一直处在最高优先级,一直占用着资源,造成严重的进程”饥饿问题“,如果进程的优先级修改范围过大,也会导致某些优先级低的进程可以快速的抢先分配到资源,导致另外那些苦苦等待很久的进程就分配不到资源,也会造成严重的进程”饥饿问题“。
在操作系统中,有一个调度器器,它通过进程优先级,会较为均衡的让每个资源都享受到CPU资源
三.其他概念
进程具有独立性,各个进程之间的运行互不干扰
并行:两个进程分别在两个CPU上运行,真正意义上的多进程同时运行的情况
并发:多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发
四.环境变量
4.1环境变量的概念和操作
为何运行自己的文件,需要带./xxx,但是运行系统的命令就不用带路径了呢?
因为环境变量!!PATH
因为我们系统在执行命令的时候会去系统的环境变量PATH路径种去查找可执行文件的路径
那这样子我就可以将该执行程序的路径添加到环境变量PATH中,实现像运行系统的命令一样运行我们自己的程序
如何将特定路径设置到环境变量中:
命令行:export PATH = $PATH:(当前文件路径)
查找环境变量命令:
echo $PATH;
echo $HOME
echo $ SHELL
查看所有的环境变量的数据:env
系统存在大量的属性变量来保证当前系统的正常运行,这些属性变量就是环境变量,其中有的环境变量是帮助我们查命令的,有的是保存当前路径的
4.2 和环境变量相关的命令
本地变量:只在本次会话中生效的环境变量,直接在命令行中输入:变量名=xxx;
验证set:
export可将本将本地变量变为环境变量:export 本地变量
main函数的输入参数有两个,分别是argc和argv,其中一个是表示argv,表示命令行传入了多少个字符串,另一个是argv,他表示命令行传入的具体字符串是什么
有了这个argc和argv,那么我们就可以通过命令行传入参数的方式来达到控制程序执行不一样的功能的目的
同时我们也可以在代码中通过参数env来获取环境变量:
还可以通过getenv()在代码中获取环境变量
环境变量是可以被子进程继承的:
我们知道通过命令行启动的应用程序,它的父进程是bash,那子进程的环境变量就继承自bash,而bash又从操作系统中读取环境变量。
我们将本地变量设置为环境变量,然后在代码中读取该环境变量来证实这一点:
当前的理解:环境变量具有“全局属性”,影响整个“用户”系统的本质是:环境变量可以被子进程继承下去
五.程序地址空间
5.1什么是地址空间:
C/C++程序地址空间:
这个程序地址空间是内存嘛
根本就不是内存,那他是什么呢?
验证程序地址空间:
我们通过下面的代码让父子进程读取同一份数据,然后子进程在运行过程中更改数据,发生写时拷贝,但是数据的地址却没有变化
如果C/C++打印出来的地址是物理内存的地址,这种现象是不可能存在的!我们在这里使用的地址不是物理地址,我们称之为虚拟地址,我们称这个程序地址空间为进程地址空间。
什么是进程地址空间:
每个进程都有一个地址空间,都认为自己在独占物理内存,由于系统中有大量的进程,那么就有大量的地址空间,OS为了管理这些地址空间,那么就会采用先描述再组织的方式来管理它们,在内核中,地址空间是一个数据结构,里面存放着具体的地址空间的变量
地址空间数据结构:
虽然里面只有start 和 end,但是每个进程都认为mm_struct代表整个内存,且所有的地址为0x000000..000~0xFFFFFFF...FFF,每个进程都认为地址空间的划分是按照4GB空间划分的,这样子每个进程都可以按照相同的方式去看待内存,都认为自己独占内存。在地址空间上进行区域划分是,对应的线性位置我们称为虚拟地址,在LInux中虚拟地址等价于线性地址
但是实际的数据和代码都是在物理内存保存的,那么操作系统是如何通过虚拟地址找到这些数据的呢?
通过页表!!这个页表是由操作系统给每个进程维护的一张表,这张表的左侧是虚拟地址,右侧是物理地址,它的核心工作是将虚拟地址转换为物理地址,它就是一张映射表,或是一张哈希表,进而再去访问代码和数据
tips:MMU是内存管理单元,在CPU内部集成,用来查页表
地址空间+页面就代表了操作系统在管理,在监督进程对内存的读写操作,比如我们定义的const变量,为什么就不能修改呢?因为在页表中,对于这个变量所对应的物理内存,该进程只有读权限,而没有写权限,当进程想要通过虚拟地址来改变物理内存中的该值时,将不被允许
当进程要向内存申请空间的时候,进程不一定立马读写这个空间,在操作系统角度,如果空间立马给进程,但是进程又没有立马读写,就意味着整个系统就会一部分空间,本来可以给别人立马使用的,现在却被你闲置着。所以说操作系统就会给进程设计一套基于缺页中断进行物理内存申请的机制,具体的操作是当进程向内存申请空间时,操作系统不会立马给进程开辟相应的物理内存空间,而是在地址空间中的相应字段增加数值范围,当进程要读写该段内存空间的时候,操作系统就会通过页表映射的方式为进程开辟相应的内存空间。因此操作系统做的内存申请动作对于进程来说是不透明的
当CPU调度到该进程执行程序的时候,CPU就会从main函数开始执行程序,但是有个问题,每个进程都有main函数,如果没有相同的main函数入口地址,那CPU就不知道从何处开始执行程序,所以说操作系统通过虚拟地址给cpu提供程序的入口地址,然后该虚拟地址再通过页表,映射到真实的物理内存中,找到真正的main函数入口地址,这样子就保证了CPU可以从相同的main函数地址去执行程序!!同样的,在虚拟地址空间中,每个部分都有自己的虚拟地址,然后映射到物理内存中,这样子在CPU看来,进程统一使用4GB空间,而且每个空间区域的相对位置是比较确定的!
为什么需要地址空间?
1. 通过添加一层软件层,完成有效的对进程操作内存进行风险管理(权限管理),本质目的是为了,保护物理内存以及各个进程的数据安全!
2.将内存申请和内存使用的概念在时间上划分清楚,通过虚拟地址空间,来屏蔽底层申请内存的过程,达到进程读写内存和OS进行内存管理操作,进行软作上面的分离!
3.站在CPU和应用层的角度,进程统一可以看作统一使用4GB空间,而且每个空间区域的相对位置,是比较确定的
为什么需要页表这个东西呢?
加了这个页表映射的中间层,是非常利于操作系统对进程的内存操作进行管理的,可以很好的判断进程对于内存中数据的操作是否合理,是否安全,假设现在有操作系统中有三个进程,如果进程可以直接去访问物理内存,那么不同的进程就可以去访问其他进程的数据和代码,造成数据安全问题。
写时拷贝:
子进程在被创建出来的时候,父进程的数据和代码也会被子进程继承,此时当子进程修改数据时,发生写时拷贝,然后子进程和父进程拥有了各自的不同的数据,但是我们通过下面的代码知道,数据的地址没有发生改变,这是为什么呢?
因为子进程在被创建出来的时候, 会继承父进程的大部分进程数据,包括进程地址空间,也就是说此时在虚拟地址空间和物理内存中,子进程的数据地址和父进程的数据地址是一样的,当子进程的数据发生改变的时候,子进程通过虚拟地址空间中的虚拟地址通过找到数据的物理内存地址,然后在内存中开辟新的空间,将新值放置在空间中,最后通过页表将虚拟地址和新的物理内存地址见了映射关系,这样子就完成了写时拷贝
命令行参数和环境变量在虚拟地址空间中的位置:在栈的上面。
相关文章:
Linux之进程
一.冯诺依曼体系 在计算机中,CPU(中央处理器)是不直接跟外部设备直接进行通信的,因为CPU处理速度太快了,而设备的数据读取和输入有太慢,而是CPU以及外设直接跟存储器(内存)打交道&am…...
结构体——“C”
各位CSDN的uu们你们好呀,今天,小雅兰的内容是结构体噢,之前我们在初始C语言中其实就已经学习过了结构体的知识,但是不是很全面,这次,我们也只是稍微详细一点,敬请期待小雅兰之后的博客ÿ…...
CCNP350-401学习笔记(51-100题)
51、Which statement about a fabric access point is true?A. It is in local mode and must be connected directly to the fabric edge switch. B. It is in local mode and must be connected directly to the fabric border node C. It is in FlexConnect mode and must …...
C语言学习_DAY_4_判断语句if_else和分支语句switch_case【C语言学习笔记】
高质量博主,点个关注不迷路🌸🌸🌸! 目录 1.案例引入 2.if判断语句的语法与注意事项 3.switch多分支语句的语法与注意事项 前言: 书接上回,我们已经学习了所有的数据类型、运算符,并且可以书写…...
实验07 赫夫曼编码及综合2022(带程序填空)
A. 【程序填空】赫夫曼编码题目描述给定n个叶子的权值,根据这些权值构造huffman树,并输出huffman编码参考课本第6.6节的算法6.12,注意算法中数组访问是从位置1开始赫夫曼构建中,默认左孩子权值不大于右孩子权值如果遇到两个孩子权…...
分布式 CAP BASE理论
文章目录CAP简介不是所谓的“3 选 2”CAP 实际应用案例BASE简介BASE 理论的核心思想总结CAP 简介 在理论计算机科学中,CAP 定理(CAP theorem)指出对于一个分布式系统来说,当设计读写操作时,只能同时满足以下三点中的…...
三调地类筛选器,Arcgis地类筛选
三调地类在使用是,需要分类统计,这个可以用于筛选; 标准地类筛选 农用地: DLBM IN(0303,0304,0306,0402,0101,0102,0103,0201,0201K,0202,0202K,0203,0203K,0204,0204K,0301,0301K,0302,0302K,0305,0307,0307K,0401,0403,0403K…...
华为OD机试 - 密室逃生游戏(Python)
密室逃生游戏 题目 小强增在参加《密室逃生》游戏,当前关卡要求找到符合给定 密码 K(升序的不重复小写字母组成) 的箱子, 并给出箱子编号,箱子编号为 1~N 。 每个箱子中都有一个 字符串 s ,字符串由大写字母、小写字母、数字、标点符号、空格组成, 需要在这些字符串中…...
白话C#之委托
一、什么是委托? 书本上是这样来定义委托的: 委托是一种动态调用方法的类型,属于引用型。委托是对方法的抽象和封装。委托对象实质上代表了方法的引用(即内存地址)。委托通常是委托某个方法来实现具体的功能。当我们调…...
jsp高校教职工管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目
一、源码特点 jsp 高校教职工管理系统 是一套完善的web设计系统,对理解JSP java编程开发语言有帮助mvc模式 serlvetdaobean方式开发,系统具有完整的源代码和数据库,系统主要采用B/S模式 开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#…...
2023年数学建模美赛A题(A drought stricken plant communities)分析与编程
2023年数学建模美赛A题(A drought stricken plant communities)分析与编程 2023年数学建模美赛D题(Prioritizing the UN Sustainability Goals)分析与编程 特别提示: 1 本文介绍2023年美赛题目,进行深入分析…...
Delphi 中自定义鼠标指针图像
Dephi中的鼠标指针是可以自由定义的,如果是使用系统提供的图标,那么直接通过可视控件的Cursor属性赋值就可以。例如设置Form的鼠标为 crHourGlass 沙漏:Form1.Cursor : crHourGlass;也可以在设计期(IDE环境中)直接更改…...
【计算机网络】物理层
文章目录物理层的基本概念传输媒体同轴电缆双绞线光纤电力线电磁波红外线可见光传输方式串行传输和并行传输同步传输和异步传输单工,半双工以及全双工通信编码与调制常用编码不归零编码归零编码曼彻斯特编码差分曼彻斯特编码基本调制混合调制信道的极限容量奈氏准…...
华为OD机试 - 最少停车数(Python)
最少停车数 题目 特定大小的停车场 数组cars表示 其中1表示有车0表示没车 车辆大小不一,小车占一个车位(长度1) 货车占两个车位(长度2) 卡车占三个车位(长度3) 统计停车场最少可以停多少辆车 返回具体的数目 输入 整型字符串数组cars 其中1表示有车0表示没车 数组长度 <…...
面试题-前端开发JavaScript篇上(答案超详细)
文章目录 闭包说一下类的创建和继承如何解决异步回调地狱说说前端中的事件流如何让事件先冒泡后捕获说一下事件委托说一下图片的懒加载和预加载mouseover 和 mouseenter 的区别JS 的 new 操作符做了哪些事改变函数内部 this 指针的指向函数(bind,apply,call 的区别)JS 的各种…...
【计算机网络】运输层
文章目录运输层概述运输层端口号、复用与分用的概念UDP和TCP的对比TCP的流量控制TCP的拥塞控制TCP超时重传时间的选择TCP可靠传输的实现TCP的运输连接管理TCP的连接建立(3次握手)TCP的连接释放(4次挥手)TCP报文段的首部格式运输层概述 这里我们对运输层进行概述,之…...
20222023华为OD机试 - 基站维修工程师(Python)
基站维修工程师 题目 小王是一名基站维护工程师,负责某区域的基站维护。 某地方有 n 个基站( 1<n<10 ),已知各基站之间的距离 s( 0<s<500 ), 并且基站 x 到基站 y 的距离,与基站 y 到 基站 x 的距离并不一定会相同。 小王从基站 1 出发,途经每个基站 1 …...
21. 合并两个有序链表
题目链接:解题思路:遍历,双指针:因为两个链表有序,所以只需要依次比较两个元素的大小,然后添加到新的链表中即可first指针指向第一个链表l1,second指针指向第二个链表l2,answer保存合…...
产品经理知识体系:5.如何做好产品数据分析?
数据分析 思考 笔记 数据分析 思路 基于用户路径:用户的活动路径,操作流程等行为数据。 基于产品节点:转化率、占比 分析类型 先定性:先抛出问题、提出假设 再定量:数据验证问题、验证假设 先定性、再定量、最后得…...
详解垃圾回收算法,优缺点是什么?|金三银四系列
本文详细介绍了在 JVM 中如何判断哪些对象是需要回收的,以及不同的垃圾回收算法以及优缺点。点击上方“后端开发技术”,选择“设为星标” ,优质资源及时送达上篇文章详细介绍了 JVM 的结构以及其内存结构,需要阅读请移步。本文主要…...
Android 虚拟 A/B 详解(七) SnapshotManager 之标识文件
本文为洛奇看世界(guyongqiangx)原创,转载请注明出处。 原文链接:https://blog.csdn.net/guyongqiangx/article/details/129098176 Android 虚拟 A/B 分区《Android 虚拟 A/B 分区》系列,更新中,文章列表: Android 虚拟 A/B 详解(一) 参考资料推荐Android 虚拟 A/B 详解(二…...
LA@生成子空间@范数@衡量矩阵大小@正交化
文章目录线性组合与线性方程组生成子空间范数LpL^pLp范数向量点积用范数表示ref衡量矩阵大小特殊类型矩阵和向量对角阵向量长度性质单位向量向量单位化(正规化)正交向量正交正交向量组标准正交基正交化(schmidt)正交矩阵矩阵是正交矩阵的充要条件对称矩阵正交相似概念区分&…...
MT2012_竹鼠的白色季节
竹鼠的白色季节 #include<bits/stdc.h> #include<algorithm> using namespace std;/*思路:从小到大排序,然后依次往后遍历即可*/ int main( ) {int n,d;cin>>n>>d; int tmp;vector<int>nums;for(int i0;i<n;i){cin&…...
MySQL是什么?它有什么优势?
随着时间的推移,开源数据库在中低端应用中逐渐流行起来,占据了很大的市场份额。开源数据库具有免费使用、配置简单、稳定性好、性能优良等特点,而 MySQL 数据库正是开源数据库中的杰出代表。 开源全称为“开放源代码”。很多人认为开源软件最…...
基础篇—CSS padding(填充\内边距)解析
CSS padding(填充) CSS padding(填充)是一个简写属性,定义元素边框与元素内容之间的空间,即上下左右的内边距。 属性说明padding使用简写属性设置在一个声明中的所有填充属性padding-bottom设置元素的底部填充padding-left设置元素的左部填充padding-right设置元素的右部…...
二进制枚举
一、左移:用来将一个数的各二进制位全部左移n位,低位以0补充,高位越界后舍弃。n左移1位,n<<1,相当于2*n1左移n位,1<<n,相当于2^n二、右移:将一个数的各二进制位右移N位&…...
2|数据挖掘|聚类分析|k-means/k-均值算法
k-means算法k-means算法,也被称为k-平均或k-均值,是一种得到最广泛应用的聚类算法。算法首先随机选择k个对象,每个对象初始地代表了一个簇的平均值或中心。对剩余的每个对象根据其与各个簇中心的距离,将它赋给最近的簇。然后重新计…...
使用和制作动、静态库
文章目录什么是库?静态库打包方式使用方式生成并执行可执行程序粗暴方式优化方式动态库不一样的.o文件打包方式使用方式生成可执行程序运行可执行程序无法运行时的解决方案动静态库与动静态链接什么是库? 从一开始的helloworld,到现在熟练使…...
【Java基础】023 -- 集合进阶(List、Set、泛型、树)
目录 一、集合的体系结构 1、单列集合(Collection) 二、Collection集合 1、Collection常见方法 ①、代码实现: ②、contains方法重写equals方法示例:(idea可自动重写) 2、Collection的遍历方式(…...
面试题整理01-集合详解
文章目录前言一、集合的整体结构单列集合接口:双列集合接口:二、单列集合详解1.List接口1.1 ArrayList集合特点:扩容:添加元素遍历1.2 LinkedList集合特点:添加元素:2.Set接口2.1 HashSet集合特点ÿ…...
wordpress伪静态化/网络营销的推广方式
Oracle 的 XML 实现?Oracle 已经通过的 XML DB 组件实现了 XML,该组件是企业版和标准版的标准特性。通过数据库配置助手 (DBCA) 或者运行一个目录脚本 catqm.sql,可以轻松安装 Oracle XML DB。XML DB 产品提供本文讨论的所有特性。要验证是否…...
商务网站设计实训总结/seo优化的网站
JS 网页打印解决方案参考文章: (1)JS 网页打印解决方案 (2)https://www.cnblogs.com/sunrunzhi/p/5310020.html 备忘一下。...
做落地页的网站/怎么制作一个简单的网页
♣题目部分在Oracle中,基表COL_USAGE$的作用是什么?♣答案部分从Oracle 9i开始引入了SYS.COL_USAGE$表用来跟踪列的使用情况,该功能通过隐含参数“_COLUMN_TRACKING_LEVEL”来控制。若隐含参数“_COLUMN_TRACKING_LEVEL”的值为0则取消该功能…...
软件工程的八个步骤/网站seo具体怎么做
ESP8266 Arduino开发之路(2)— 连接到无线WiFi路由器 一、前言 ESP8266可以通过WiFi连接到无线路由器,这种方式和手机通过WiFi连接无线路由器的模式是相同的,我们称该模式为无线终端模式(Wireless Station),即STA工作…...
园区建设网站的方案/长沙网络推广小公司
<div> <span class"try"></span> </div> 给try附上vertical-align可以设置它自己所处的位置 不是给div设!!转载于:https://www.cnblogs.com/cjy1993/p/3935604.html...
华为云怎么做网站/百度公司推广电话
1.查看Centos当前ip地址(局域网内),命令:ip addr 2.进入网络配置目录:cd /etc/sysconfig/network-scripts 3.查看所有配置文件:ls #列出文件 4.辨别使用的网卡文件,一般文件名以ifcfg-开头,末尾有(随机)数字…...