VM虚拟机网络配置

Bridged(桥接模式)

桥接模式相当于虚拟机和主机在同一个真实网段,VMWare充当一个集线器功能(一根网线连到主机相连的路由器上),所以如果电脑换了内网,静态分配的ip要更改。图如下:

img

NAT(网络地址转换模式)

NAT模式和桥接模式一样可以上网,只不过,虚拟机会虚拟出一个内网,主机和虚拟机都在这个虚拟的局域网中。NAT中VMWare相当于交换机(产生一个局域网,在这个局域网中分别给主机和虚拟机分配ip地址)

img

步骤:

1.设置VMVare的默认网关(相当于我们设置路由器):
编辑->虚拟网络编辑器->更改设置->选中VM8>点击NAT设置,设置默认网关为192.168.182.2。

img)img

2.设置主机ip地址,点击VMnet8,设置ip地址为192.168.182.1,网关为上面设置的网关。

img

img

3.设置linux虚拟机上的网络配置,界面化同上。

IP配置

未安装系统

img

已安装系统

ifcfg-ens33原文件如下,此时为NAT模式下的DHCP

img

改为静态IP:

如果是NAT要去虚拟网络编辑器中查看NAT设置中的网关IP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
cd  /etc/sysconfig/network-scripts/     //进入到网络适配器文件夹中
mv ifcfg-ethXXX ifcfg-eth0 //名字改为ifcfg-eth0
vi ifcfg-eth0 //编辑文件

TYPE=Ethernet
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_PEERDNS=yes
IPV6_PEERROUTES=yes
IPV6_FAILURE_FATAL=no
NAME=eth0
#UUID(Universally Unique Identifier)是系统层面的全局唯一标识符号,Mac地址以及IP地址是网络层面的标识号;
#两台不同的Linux系统拥有相同的UUID并不影响系统的使用以及系统之间的通信;
#可以通过命令uuidgen ens33生成新的uuid#和DEVICE一样也可以不写,DEVICE="ens33"可以不写,但一定不要写DEVICE="eth0"
UUID=ae0965e7-22b9-45aa-8ec9-3f0a20a85d11

ONBOOT=yes #开启自动启用网络连接,这个一定要改
IPADDR=192.168.182.3 #设置IP地址
NETMASK=255.255.225.0 #设置子网掩码
GATEWAY=192.168.182.2 #设置网关
DNS1=61.147.37.1 #设置主DNS
DNS2=8.8.8.8 #设置备DNS
BOOTPROTO=static #启用静态IP地址 ,默认为dhcp

:wq! #保存退出

service network restart #重启网络,本文环境为centos7

ping www.baidu.com #测试网络是否正常

ip addr #查看IP地址

复制代码

改BOOTPROTO和NAME,新增IP网关DNS等配置

img

测试下OK

img

failed to start lsb:bring up/down networking

ip addr查看mac地址( link/ether后面的为mac地址),然后在ifcfg-eth0中配置

1
2
3
4
vi /etc/sysconfig/network-scripts/ifcfg-eth0  #修改配置文件

#添加如下配置,这里要写上你的MAC地址
HWADDR=00:0c:bd:05:4e:cc

然后关闭NetworkManager

1
2
3
4
5
6
systemctl stop NetworkManager
systemctl disable NetworkManager

#重启计算机(推荐)
#systemctl restart network.service
#service network restart

ping通局域网但是ping不通外网

去掉配置NETWORK=yes即可,不知道为啥CentOS7.8加上去之后只能ping的通同一网段的,其他网段的和外网都ping不通。

下载ifconfig

ping通网络之后可以下载ifconfig命令

1
2
yum provides ifconfig    #查看哪个包提供了ifconfig命令,显示net-tools
yum install net-tools #安装提供ifconfig的包

Host-Only(仅主机模式)

主机模式和NAT模式很相似,只不过不能上网,相当于VMware虚拟一个局域网,但是这个局域网没有连互联网。

img

虚拟机安装好后用xshell直接拖拽传递文件的话要执行以下命令

1
yum install lrzsz

Vim快捷键

光标移动(Cursor Movement)

命令 作用(解释)
h,j,k,l h表示往左,j表示往下,k表示往右,l表示往上
Ctrl+f 上一页
Ctrl+b 下一页
w, e, W, E 跳到单词的后面,小写包括标点
b, B 以单词为单位往前跳动光标,小写包含标点
O 开启新的一行
^ 一行的开始
$ 一行的结尾
gg 文档的第一行
[N]G 文档的第N行或者最后一行

插入模式(Insert Mode)

命令 作用(解释)
i 插入到光标前面
I 插入到行的开始位置
a 插入到光标的后面
A 插入到行的最后位置
o, O 新开一行
Esc 关闭插入模式

编辑(Editing)

命令 作用(解释)
r 在插入模式替换光标所在的一个字符
J 合并下一行到上一行
s 删除光标所在的一个字符, 光标还在当行
S 删除光标所在的一行,光标还在当行,不同于dd
u 撤销上一步操作
ctrl+r 恢复上一步操作
. 重复最后一个命令
~ 变换为大写
[N]>> 一行或N行往右移动一个tab
[N]<< 一行或N行往左移动一个tab

撤销:u

恢复撤销:Ctrl + r

关闭(Exiting)

命令 作用(解释)
:w 保存
:wq, :x 保存并关闭
:q 关闭(已保存)
:q! 强制关闭

搜索(Search)

命令 作用(解释)
/pattern 搜索(非插入模式)
?pattern 往后搜索
n 光标到达搜索结果的前一个目标
N 光标到达搜索结果的后一个目标

视觉模式(Visual Mode)

命令 作用(解释)
v 选中一个或多个字符
V 选中一行

剪切和复制(Cut and Paste)

命令 作用(解释)
dd 删除一行
dw 删除一个单词
x 删除后一个字符
X 删除前一个字符
D 删除一行最后一个字符
[N]yy 复制一行或者N行
yw 复制一个单词
p 粘贴

窗口操作

命令 作用(解释)
:split 水平方向分割出一个窗口
:vsplit 垂直方向分割出一个窗口
:close 关闭窗口
Ctrl+W 切换窗口, h到左边窗口,j到下方窗口,k到上方窗口,l到右边窗口

多文件切换

  1. 通过vim打开多个文件(可以通过ctags或者cscope)
  2. “:ls”查看当前打开的buffer(文件)
  3. “:b num”切换文件(其中num为buffer list中的编号)
  4. Ctrl+ww——依次向后切换到下一个窗格中
  5. bn
  6. bp

区域选择操作

v 进入字符可视化模式(移动一次选择一个字符)
V 进入行可视化模式
ctrl-V 进入块可视化模式
ctrl-Q
gv 选中前一次可视化模式时选择的文本
o 光标移动到选中文本的另一结尾
O 光标移动到选中文本的另一角落

补充操作:配合% (各种括号前后跳转),行内跳转:fa(到下一个为a的字符上),t(到某个字符前的字符)。大写的F、T是向反方向查找,命令有各种组合:

  • fa → 从当前光标位置到下一个为a的字符处,你也可以fs到下一个为s的字符。
  • t, → 从当前光标位置到逗号前的第一个字符。逗号可以变成其它字符。
  • 3fa → 在当前行查找从当前光标位置起第三个出现的a。
  • FT → 和 ft 一样,只不过是相反方向。
  • img
  • 还有一个很有用的命令是 dt" → 删除所有的内容,直到遇到双引号—— "。

最强操作:**<action>a<object>** <action>i<object>

在visual 模式下,这些命令很强大,其命令格式为

1
<action>a<object>` 和 `<action>i<object>
  • action可以是任何的命令,如 d (删除), y (拷贝), v (可以视模式选择)。
  • object 可能是: w 一个单词, W 一个以空格为分隔的单词, s 一个句字, p 一个段落。也可以是一个特别的字符:"、 '、 )、 }、 ]。

假设你有一个字符串 (map (+) ("foo")).而光标键在第一个 o的位置。

复制代码

1
2
3
4
5
6
vi" → 会选择 foo
va" → 会选择 "foo"
vi) → 会选择 "foo"
va) → 会选择("foo")
v2i) → 会选择 map (+) ("foo")
v2a) → 会选择 (map (+) ("foo"))

复制代码

区域选择后可以进行哪些操作:

  1. 针对高亮显示的文本块,我们可以用命令~进行大小写转换。
  2. 用命令>增加缩进,或用命令<减少缩进。
  3. 我们还可以利用可视化模式,来合并多行文本。J命令可以将高亮显示的文本内容合并为一行,同时以空格来分隔各行。如果不希望在行间插入空格,那么可以使用gJ命令。
  4. 加注释,或者前、后加字符, I(大写i)– [ESC] → I是插入,插入“–”,按ESC键来为每一行生效
  5. 使用g?命令,可以使用rot 13算法来加密高亮显示的文本。针对同一个文本再次执行加密命令,就可以进行文本解密。

在可视化模式下,按下:键就可以对选定范围进行操作。例如:我们先在可视化模式下选中文本,然后执行:write block.txt命令,就可以将文本块写入另一文件中。选择多行,

然后执行:sort命令,则可以对选中的文本进行排序。

在vim下打开终端

注意:仅在vim8.1下可用
使用方法:

1
:term

打开默认的终端
如果是linux,或者使用wsl,

1
:term bash

Ctrl+W/Ctrl+N 将终端设置成normal模式

Vue-elementUI的使用

引入

安装

1
npm install element-plus --save

完整引入

1
2
3
4
5
6
7
8
import { createApp } from 'vue'
import ElementPlus from 'element-plus';
import 'element-plus/lib/theme-chalk/index.css';
import App from './App.vue';

const app = createApp(App)
app.use(ElementPlus)
app.mount('#app')

按需引入

借助 babel-plugin-import,我们可以只引入需要的组件,以达到减小项目体积的目的。

首先,安装 babel-plugin-import:

1
$ npm install babel-plugin-import -D

………..

linux&,nohup和screen的比较

&

首先,linux进程是区分前台进程和后台进程的。
通常,在终端输入的命令执行的前台进程模式。如果一个命令要执行好久,就会阻塞住终端好久,不能进行其他工作,所以,我们可以把执行花费时间很长的任务使用后台进程模式运行,我们就可以在同一终端干其他事!、

以前台进程模式运行

通常使用的方式

1
[root@localhost cdnjs]# find / -name xml &

以后台进程模式运行

1
[root@localhost cdnjs]# find / -name xml &

这样,这个查找程序就会在后台运行。它运行的同时不影响你干别的事情。
在后台运行时,找到符合的文件,还是会在终端中输出。

查看后台任务

1
2
[root@localhost cdnjs]# jobs
[1]+ 已停止 find / -name xml

切换前台/后台模式

前台切后台

在运行命令后,有的时候忘记了在命令之后加上‘&’符号,又不愿意停下此命令重新改写。这是可以按[ctrl+z],把当前程序切入后台。
但是要注意此时在后台的这个程序是处于 Stopped 状态
要继续执行的话,先使用jobs命令找出当前任务的jobId,然后按如下操作

1
[root@localhost cdnjs]#bg 1

后台切回前台

先使用jobs命令找出当前任务的jobId,然后按如下操作

1
[root@localhost cdnjs]#fg 1

nohup

不管是前台进程还是后台进程,在终端关闭的时候,linux会发出终端关闭信号,让在终端中运行的进程结束。
但是,我们可能会有这样的需求:
在linux进行下载很久的任务,但是终端关闭的时候,我们是不希望下载被终止的。所以,可以采用nohup命令的方式,让程序运行的时候,忽略掉终端关闭的信号。
格式为:

1
nohup 执行程序的命令

tip

如果想让一个程序在后台运行,只要在执行命令的末尾加上一个&符号就可以了。但是这种方式不是很保险,有些程序当你登出终端后它就会停止。那么如何让一个程序真正永远在后台执行呢。答案就是使用 nohup和&组合使用
格式为:

1
nohup 执行程序的命令 &

screen

nohup和&的缺点是,如果你要在一个shell会话里面执行多个命令和脚本,那么要每个命令和脚本都要加nohup和&非常麻烦,所以才有了screen。

1
screen [-AmRvx -ls -wipe][-d <作业名称>][-h <行数>][-r <作业名称>][-s <shell>][-S <作业名称>]
1
2
3
4
5
6
7
8
9
10
11
12
-A 					   		   将所有的视窗都调整为目前终端机的大小。
-d<作业名称>   将指定的screen作业离线。
-h<行数>   指定视窗的缓冲区行数。
-m   即使目前已在作业中的screen作业,仍强制建立新的screen作业。
-r<作业名称>   恢复离线的screen作业。
-R   先试图恢复离线的作业。若找不到离线的作业,即建立新的screen作业。
-s<shell>  指定建立新视窗时,所要执行的shell。
-S<作业名称>   指定screen作业的名称。
-v   显示版本信息。
-x   恢复之前离线的screen作业。
-ls或--list   显示目前所有的screen作业。
-wipe   检查目前所有的screen作业,并删除已经无法使用的screen作业。

1、常用命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
screen -ls              # 查看所有screen
screen -S <screen-name> # 创建screen,并命名
ctr + A, D # 快捷键,退出当前screen
screen -r <screen-name> # 进入screen
screen -X quit # 删除screen,但没有指定会话
screen -X -S [session you want to kill] quit #删除screen,指定会话
screen -wipe # 清除dead screens

screen -S yourname # 新建一个叫yourname的session
screen -ls # 列出当前所有的session
screen -r yourname # 回到yourname这个session
screen -d yourname # 远程detach某个session # detach快捷键 ctrl a + d
screen -d -r yourname # 结束当前session并回到yourname这个session
screen -S yourname -X quit # 删除叫yourname的session

2、快捷键

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 默认的 command key 是 ctrl+a
escape `` #指定command key 为 `,并指定在按下 ` 后再按 `,相当于之前 C-a a 的效果
C-a ? #列出当前可用快捷键及其对应的命令
C-a : #进入命令输入模式,之后可输入并执行screen中的命令,比如quit强制关闭当前screen,比如split分屏
C-a d #使当前session处于Detached状态
C-a :quit #关闭当前会话
C-a c #新建窗口
C-a K #强制关闭当前窗口
C-a \" #显示当前会话的窗口列表,用j、k上下移动光标选择窗口,或直接用0-9选择窗口
C-a \' #输入窗口序号或title,选择指定窗口
C-a 0-9 #选择指定窗口
C-a n #选择下一个窗口
C-a [space] #选择下一个窗口
C-a p #选择上一个窗口
C-a C-a #移动到上一次选择的窗口
C-a A #修改当前窗口的title
C-a [ #进入复制模式。
C-a ] #将buffer中的内容粘贴出来,退出复制模式。vim 中最好是在insert模式下。

管理

查看运行的后台进程

(1)jobs -l

img

jobs命令只看当前终端生效的,关闭终端后,在另一个终端jobs已经无法看到后台跑得程序了,此时利用ps(进程查看命令)

(2)ps -ef

1
2
3
4
ps -aux|grep chat.js
a:显示所有程序
u:以用户为主的格式来显示
x:显示所有程序,不以终端机来区分

img

注:

  用ps -def | grep查找进程很方便,最后一行总是会grep自己

  用grep -v参数可以将grep命令排除掉

1
ps -aux|grep chat.js| grep -v grep

img

  再用awk提取一下进程ID 

1
ps -aux|grep chat.js| grep -v grep | awk ``'{print $2}'

img

3.如果某个进程起不来,可能是某个端口被占用

查看使用某端口的进程

1
lsof -i:8090

img

1
netstat -ap|grep 8090

img

查看到进程id之后,使用netstat命令查看其占用的端口

1
netstat -nap|grep 7779

img

使用kill杀掉进城后再启动

4.终止后台运行的进程

1
kill -9 进程号

img

《操作系统导论》第8章调度-多级反馈队列

多级反馈队列(Multi-level Feedback Queue,简称MLFQ)需要解决两方面的问题。首先它要优化周转时间,这可以通过优先执行较短的工作来实现。然而,操作系统常常不知道工作要运行多久,而这又是SJF等算法所必需的。其次,MLFQ希望给用户提供较好的交互体验,因此需要降低响应时间。然而,轮转调度虽然降低了响应时间,周转时间却很差。所以这里的问题是:通常我们对进程一无所知,应该如何构建调度程序来实现这些目标?调度程序如何在运行过程中学习进程的特征,从而做出更好的调度决策?

多级反馈队列:基本规则

为了构建这样的调度程序,本章将介绍多级消息队列背后的基本算法。MLFQ中有许多独立的队列,每个队列有不同的优先级。任何时刻,一个工作只能存在于一个队列中。MLFQ总是优先执行较高优先级的工作(即那些在较高级队列中的工作)。每个队列中可能会有多个工作,它们具有同样的优先级。在这种情况下,我们就对这些工作采用轮转调度。至此,我们得到了MLFQ的两条基本规则:

规则1:如果A的优先级大于B的优先级,运行A不运行B
规则2:如果A的优先级等于B的优先级,轮转运行A和B

img

上图中,最高优先级有两个工作(A和B),工作C位于中等优先级,而D的优先级最低。按刚才介绍的基本规则,由于A和B有最高优先级,调度程序将交替的调度他们,而C和D永远都没有机会运行,除非A和B已经完成。

如何改变优先级

显然,在一个工作的生命周期中,MLFQ必须按照一定的策略改变其优先级。例如,如果一个工作不断放弃CPU去等待键盘输入,这是交互型进程的可能行为,MLFQ因此会让它保持高优先级。相反,如果一个工作长时间地占用CPU,MLFQ会降低其优先级。通过这种方式,MLFQ在进程运行过程中学习其行为,从而利用工作的历史来预测它未来的行为。下面是我们第一次尝试优先级调整算法。

规则3:工作进入系统时,放在最高优先级(最上层)队列
规则4a:工作用完整个时间片后,降低其优先级(移入低一级队列)
规则4b:如果工作在其时间片以内主动释放CPU,则优先级不变

单个长工作

假如系统中有一个需要长时间运行的工作,我们看看使用当前的MLFQ调度会发生什么。下图展示了在一个有3个队列的调度程序中,随着时间的推移,这个工作的运行情况。

img

从这个例子可以看出,该工作首先进入最高优先级(Q2)。执行一个10ms的时间片后,调度程序将工作的优先级减1,因此进入Q1。在Q1执行一个时间片后,最终降低优先级进入系统的最低优先级(Q0),一直留在那里。

来了一个短工作

再看一个较复杂的例子,看看MLFQ如何近似SJF。在这个例子中,有两个工作:A是一个长时间运行的CPU密集型工作,B是一个运行时间很短的交互型工作。假设A执行一段时间后B到达。会发生什么呢?

img

上图展示了这种场景的结果。A(用黑色表示)在最低优先级队列执行(长时间运行的CPU密集型工作都这样)。B(用灰色表示)在时间为100ms时到达,并被加入最高优先级队列。由于它的运行时间很短(只有20ms),经过两个时间片,在被移入最低优先级队列之前,B执行完毕。然后A继续运行(在低优先级)。

通过这个例子,我们可以体会到这个算法的一个主要目标:如果不知道工作是短工作还是长工作,那么就在开始的时候假设其是短工作,并赋予最高优先级。如果确实是短工作,则很快会执行完毕,否则将被慢慢移入低优先级队列,而这时该工作也被认为是长工作了。通过这种方式,MLFQ近似于SJF。

结合I/O

根据上述规则4b,如果进程在时间片用完之前主动放弃CPU,则保持它的优先级不变。这条规则的意图很简单:假设交互型工作中有大量的I/O操作(比如等待用户的键盘或鼠标输入),它会在时间片用完之前放弃CPU。在这种情况下,我们不想处罚它,只是保持它的优先级不变。

下图展示了这个运行过程,交互型工作B(用灰色表示)每执行1ms便需要进行I/O操作,它与长时间运行的工作A(用黑色表示)竞争CPU。MLFQ算法保持B在最高优先级,因为B总是让出CPU。如果B是交互型工作,MLFQ就进一步实现了它的目标,让交互型工作快速运行。

img

当前MLQF的一些问题

至此,我们有了基本的MLFQ。它看起来似乎相当不错,长工作之间可以公平地分享CPU,又能给短工作或交互型工作很好的响应时间。然而,这种算法有一些非常严重的缺点。首先,会有饥饿问题。如果系统有“太多”交互型工作,就会不断占用CPU,导致长工作永远无法得到CPU。即使在这种情况下,我们也希望这些长工作也能有所进展。其次,某些用户会用一些手段欺骗调度程序,让它给予进程远超公平的资源。例如,上述算法对如下的攻击束手无策:进程在时间片用完之前,调用一个I/O操作(比如访问一个无关的文件),从而主动释放CPU。如此便可以保持在高优先级,占用更多的CPU时间。做得好时(比如,每运行99%的时间片时间就主动放弃一次CPU),工作可以几乎独占CPU。最后,一个程序可能在不同时间表现不同。一个计算密集的进程可能在某段时间表现为一个交互型的进程。用目前的方法,它不会享受系统中其他交互型工作的待遇。

提升优先级

我们首先来尝试避免饥饿问题。要让CPU密集型工作也能局的一些进展,一个简单的思路是周期性地提升所有工作地优先级,最简单的实现就是将所有工作一股脑儿地扔到最高优先级队列。于是,我们有了以下规则。

规则5:每经过一段时间,就将系统中所有工作重新加入最高优先级队列

新规则一下解决了两个问题。首先,进程不会饿死——在最高优先级队列中,它会以轮转的方式,与其他高优先级工作分享CPU,从而最终获得执行。其次,如果一个CPU密集型工作变成了交互型,当它优先级提升时,调度程序会正确对待它。

在这种场景下,我们展示长工作与两个交互型短工作竞争CPU时的行为。下图左边没有优先级提升,长工作在两个短工作到达后被饿死。右边每50ms就有一次优先级提升(这里只是举例,这个值可能过小),因此至少保证长工作会有一些进展,每过50ms就被提升到最高优先级,从而定期获得执行。

img

显然,添加时间段引入了新的问题:时间段的值该如何设定?如果设置得太高,长工作就会饥饿;如果设置得太低,交互型工作又得不到合适的CPU时间比例。

更好的计时方式

为了防止用户欺骗调度程序,让它给予进程远超公平的资源,MLQF为每层队列提供更为完善的CPU计时方式。调度程序记录一个进程在某一层中消耗的总时间,而不是在调度时重新计时。只要进程用完了自己的配额,就将它降到低一级队列中去。不论它是一次用完的,还是拆成很多次用完。

规则4:一旦工作用完了其在某一层中的时间配额(无论中间主动放弃了多少次CPU),就降低其优先级(移入低一级队列)

img

上图对比了在规则4a、4b的策略下(左),以及在新的规则4(右)的策略下,同样试图欺骗调度程序的进程的表现。没有规则4的保护时,进程可以在每个时间片结束前发起一次I/O操作,从而垄断CPU时间。有了这样的保护后,不论进程的I/O行为如何,都会慢慢地降低优先级,因而无法获得超过公平的CPU时间比例。

其他问题

关于MLFQ调度算法还有一些问题。其中一个大问题是如何配置一个调度程序,例如,配置多少队列?每一层队列的时间片配置多大?为了避免饥饿问题以及进程行为改变,应该多久提升一次进程的优先级?这些问题都没有显而易见的答案,因此只有利用对工作负载的经验,以及后续对调度程序的调优,才会导致令人满意的平衡。例如,大多数的MLFQ变体都支持不同队列可变的时间片长度。高优先级队列通常只有较短的时间片(比如10ms或者更少),因而这一层的交互工作可以更快地切换。相反,低优先级队列中更多的是CPU密集型工作,配置更长的时间片会取得更好的效果。

本章包含了一组优化的MLFQ规则。为了方便查阅,我们重新列在这里。

规则1:如果A的优先级大于B的优先级,运行A不运行B
规则2:如果A的优先级等于B的优先级,轮转运行A和B
规则3:工作进入系统时,放在最高优先级(最上层)队列
规则4:一旦工作用完了其在某一层中的时间配额(无论中间主动放弃了多少次CPU),就降低其优先级(移入低一级队列)
规则5:每经过一段时间,就将系统中所有工作重新加入最高优先级队列