之前虽然也自己用vps搭搭机场、部署一下自己的小网站啥的,但是对linux和操作系统没有太多深入了解,所以双11在拉钩抢了一些课,随便记记。

这种东西还是要看多用,所以就大概过一遍知识点,有个印象。

计算机组成原理


32位和64位

  • 如果是软件,那么我们的数据库有 32 位和 64 位版本;
  • 如果是操作系统,那么在阿里云上选择 Centos 和 Debian 版本的时候,也会有 32/64 版本;
  • 如果是 CPU,那么有 32 位 CPU,也有 64 位 CPU。

冯诺依曼模型

输入设备

输出设备

内存

CPU(中央处理器)

  • 如果 CPU 每次可以计算 4 个 byte,那么我们称作 32 位 CPU

  • 如果 CPU 每次可以计算 8 个 byte,那么我们称作 64 位 CPU

  • 这里的 32 和 64,称作 CPU 的位宽。

总线

CPU 和内存以及其他设备之间,也需要通信,因此我们用一种特殊的设备进行控制,就是总线。总线分成 3 种:

  • 一种是地址总线,专门用来指定 CPU 将要操作的内存地址
  • 还有一种是数据总线,用来读写内存中的数据
  • 最后一种总线叫作控制总线,用来发送和接收关键信号,比如中断信号,还有设备复位、就绪等信号,都是通过控制总线传输。同样的,CPU 需要对这些信号进行响应,这也需要控制总线

存储器分级策略

假设有一个二维数组,总共有 1M 个条目,如果我们要遍历这个二维数组,应该逐行遍历还是逐列遍历?

逐行遍历会更快。当 CPU 遍历二维数组的时候,会先从 CPU 缓存中取数据。CPU 设计不是每次读取一个内存地址,而是读取每次读取相邻的多个内存地址,

可以二维数组想象成只有一行的一维数组,行坐标增加时,内存空间是跳跃的。列坐标增加时,内存空间是连续的。

SSD、内存和 L1 Cache 相比速度差多少倍?

因为内存比 SSD 快 101000 倍,L1 Cache 比内存快 100 倍左右。因此 L1 Cache 比 SSD 快了 1000100000 倍。所以你有没有发现 SSD 的潜力很大,好的 SSD 已经接近内存了,只不过造价还略高。

Linux指令入门

什么是shell

Shell 把我们输入的指令,传递给操作系统去执行,所以 Shell 是一个命令行的用户界面。

几种常见的文件类型

Linux 把所有的设备都抽象成了文件,比如说打印机、USB、显卡等。这让整体的系统设计变得高度统一。

  • 普通文件(比如一个文本文件)没有符号结尾的是普通文件
  • 目录文件(目录也是一个特殊的文件,它用来存储文件清单,比如/也是一个文件) / 结尾的是目录
  • 可执行文件(rm就是一个可执行文件)。* 结尾的是可执行文件
  • 管道文件。 | 结尾的管道文件
  • Socket 文件。= 结尾的是 Socket 文件
  • 软链接文件。@ 结尾的是软链接
  • 硬链接文件。= 结尾的是 Socket 文件

文件的增删改查

man

man意思是 manual,就是说明书的意思,这里指的是系统的手册。比如使用man touch就会列出touch命令的详细用法。

touch

touch指令本来是用来更改文件的时间戳的,但是如果文件不存在touch也会帮助创建一个空文件。

touch test.txt

mkdir

增加一个目录

mkdir test

如果要创建的文件夹的父目录不存在,要使用-p参数,这个参数控制mkdir当发现目标目录的父级目录不存在的时候会递归的创建:

mkdir -p test/child-test

ls

lslist 的缩写,查看当前目录下所有文件,如果要查看更完善的信息,还可以使用ls -l-lls指令的可选参数。

rm

rmremove 的缩写,用于删除一个文件或文件夹。

删除文件:

rm test.txt

删除文件夹,要加-r参数,代表递归删除的意思:

rm -r test

cat

cat指令将文件连接到标准输出流并打印到屏幕上。但是cat不适合用来打印输出大文件。

more

more可以帮助我们分页读取文件。

less

more差不多,但是可以向上翻页。

head/tail

headtail是一组,它们用来读取一个文件的头部 N 行或者尾部 N 行。

tail -f

-ffollow 的意思,就是文件追加的内容会跟随输出到标准输出流。

grep

  • g 就是 global,全局;

  • re 就是 regular expression,正则表达式;

  • p就是 pattern模式。

which

可以查询一个指令文件所在的位置。

which go会打印/usr/bin/go

find

find 指令帮助我们在文件系统中查找文件。

可以使用find / -iname "*.txt"/是路径,-iname这个参数是用来匹配查找的,i 字母代表忽略大小写,这里也可以用-name替代

进程

应用的可执行文件是放在文件系统里,启动可执行文件,就会在操作系统里(具体来说是内存中)形成一个应用的副本,这个副本就是进程。

什么是进程(进程的定义是什么)?

进程就是应用的执行副本。

进程的作用是什么?

进程是操作系统分配资源的最小单位。

ps

p代表processs代表snapshot

使用此命令可以查看当前的进程。

如图有两个进程:

  • zsh是打开了这个控制台,执行shell的是zsh
  • ps是使用ps命令启动时,被ps自己捕捉到。

什么是TTY?

操作系统上的 TTY 是一个输入输出终端的概念,比如用户打开bash,操作系统就为用户分配了一个输入输出终端。

使用-e可以查看操作系统的所有进程, 使用-f可以显示更多的描述字段。如图:

描述字段:

  • UID:指进程的所有者。
  • PID:进程的唯一标识。
  • PPID:父进程的唯一标识。
  • C:CPU占用。
  • STIME:开始时间。
  • TTY:进程所在的TTY,没有就是问号。
  • CMD:进程启动时的命令。如果是方括号括起来的,那就是系统进程或内核进程。

top

ps的区别是,top显示实时数据而不是快照。

htop

top更强大的一个非自带的工具,需要自己安装。

管道(Pipeline)

管道的作用是在命令和命令之间传递数据,更准确的说是在进程和进程之间传递数据。

输入输出流

每个进程拥有自己的标准输入流,标准输出流,标准错误流。

  • 标准输入流:用0表示,可以作为进程执行的上下文,进程执行可以从输入流中获取数据。
  • 标准输出流:用1表示,标准输出流的写入结果会被打印到屏幕上。
  • 标准错误流:如果进程在执行过程中发生异常,那么异常信息会被记录到标准错误流中。
重定向
  • > :覆盖重定向
  • >>:追加重定向

ls -l,结果会写入标准输出流,进而被打印,如图:

ls -l > out 会把上图的内容存入到out文件,不会在屏幕上打印。

ls -l >> out 会把上图的内容追加存入到out文件,不会在屏幕上打印。

管道的作用和分类

管道和重定向很像,但是管道是一个连接一个进行计算,重定向是将一个文件的内容定向到另一个文件,这二者经常会结合使用。

有两种类型的管道:

  • 匿名管道:这种管道也在文件系统中,但是它只是一个存储节点,不属于任何一个目录。说白了,就是没有路径。
  • 命令管道:这种管道就是一个文件,有自己的路径。

管道具有FIFO(先进先出)的特性。

管道的使用场景

排序

ls | sort -r -r表示倒序,按照文件名称倒序排列显示。

去重

sort a.txt | uniq,先排序,再将排序结果去重。

筛选

find ./ | grep Springfind ./ 递归列出当前目录下的文件,grep从输出流中找出包含Spring关键字的行。

find ./ | grep Spring | grep -v MyBatisgrep -v MyBatis代表不包含 MyBatis关键字。

数行数

find ./ -iname "*.js" | wc -l

找到./路径下,所有js文件,然后统计行数。

中间结果

find ./ -iname "*.js" | tee jslist | grep test

找到./路径下,所有js文件,然后存入jslist文件,然后筛选有关键字grep的文件,打印到控制台。

tee这个执行就像英文字母中的 T 一样,连通管道两端,下面又开了口。这个开口,在函数式编程里面叫作副作用。

xargs

xargs指令从标准数据流中构造并执行一行行的指令。

ls | grep jslist | xargs -I gg mv gg prefix_gg

将包含jslist关键字的文件加上prefix前缀,如图:

管道文件

上文中说管道有匿名管道和命名管道,匿名管道通过|就可以创造和使用。

而命名管道是要挂到文件夹中的,因此需要创建。

mkfifo指令可以创建一个命名管道,如图:

根据一个IP地址列表,逐个ping这些ip,并收集每个IP的延迟等。

cat iplist | xargs -n1 ping -c2 > pinglistres


用户和权限

权限抽象

用户和用户组

  • linux将用户抽象为账户,账户可以登录系统。

  • linux支持组,每个用户可以在多个组,可以利用组给用户快速分配权限。

  • root账户也叫超级管理员账户,他可以使用系统提供的全部能力。

文件权限:

  • 读权限 r
  • 写权限w
  • 执行权限x

然后每个文件又可以从 3 个维度去配置上述的 3 种权限:

  • 用户维度。每个文件可以所属 1 个用户,用户维度配置的 rwx 在用户维度生效;
  • 组维度。每个文件可以所属 1 个分组,组维度配置的 rwx 在组维度生效;
  • 全部用户维度。设置对所有用户的权限。

分析下面两个文件的权限

1
2
drwxr-xr-x 5 root root    4096 12月 30 14:15 codespace
-rw-r--r-- 1 root root 77 11月 8 13:36 dump.rdb
  • 第一位 - 代表普通文件,d代表目录,p代表管道
  • rwx 代表用户维度,这里是表示codespace的所属用户可以读写执行这个文件。
  • r-x 代表用户组维度,这里表示codespace所属用户组里的所有用户可以执行这个文件。
  • r-x代表所有用户可以执行这个codespace文件
初始权限问题

一个文件创建后,文件的所属用户会被设置成创建文件的用户

linux中,每个用户创建时,会有一个同名的用户组也被创建,登录后,工作分组默认使用它的同名分组。

使用newgrp指令可以切换到另一个工作分组。

所以文件被创建后的权限通常是:rw-rw-r--

公共执行文件的权限

一个文件权限如果是可执行,但是不可读?那它也无法执行。

1
2
ls -l /usr/bin/ls`
-rwxr-xr-x 1 root root 117608 8月 20 2019 /usr/bin/ls
用户分组指令

groups

查看当前用户的分组

groups root可以查看指定用户(root)的分组

id

查看当前用户信息

  • uid 是用户 id

  • gid 是组 id

  • groups 后面是每个分组和分组的 id。对应groups查看到的分组

cat /etc/passwd

查看所有用户

创建用户

sudo useradd foo

sudo的意思是superuser do,这里表示使用超级管理员的身份去执行这条命令。

创建分组

sudo groupadd hello

为用户增加次级分组

组分为主要分组和次级分组。主要分组只有一个(默认创建的用户同名分组?),次级分组可以有多个。

使用sudo usermode -a -G hello foo把我们前面创建的foo用户加入到hello分组中。

-a代表append,-G代表一个次级分组的清单, 最后一个foo是账户名。

这时使用groups foo查看如图所示:

修改用户的主要分组

sudo usermod -g hello foo

文件权限管理指令

查看

ls -l

修改文件权限

1
2
3
4
5
6
# 设置foo可以执行
chmod +x ./foo
# 不允许foo执行
chmod -x ./foo
# 也可以同时设置多个权限
chmod +rwx ./foo

因为rwx在 Linux 中用相邻的 3 个二进制位来表示:

第一组是用户权限,第二组是组权限,第三组是所有用户的权限。然后用-代表没有权限。

1
2
3
4
# 设置rwxrwxrwx (111111111 -> 777)
chmod 777 ./foo
# 设置rw-rw-rw-(110110110 -> 666)
chmod 666 ./foo
  • 第一位

  • - 为普通文件:Linux中最多的一种文件类型, 包括 纯文本文件、二进制文件、数据格式的文件(data)、各种压缩文件。

  • d 为目录文件:就是目录, 能用 cd 命令进入的。

    • b 为块设备文件:存储数据以供系统存取的接口设备,简单而言就是硬盘。例如一号硬盘的代码是 /dev/hda1等文件。
  • c 为字符文件:串行端口的接口设备,例如键盘、鼠标等等。

    • s 为套接字文件:通常用在网络数据连接。可以启动一个程序来监听客户端的要求,客户端就可以通过套接字来进行数据通信,最常在 /var/run目录中看到这种文件类型。
  • f 为管道文件:FIFO也是一种特殊的文件类型,它主要的目的是,解决多个程序同时存取一个文件所造成的错误。FIFO是first-in-first-out(先进先出)的缩写。

  • l 为链接文件:类似Windows下面的快捷方式。第一个属性为 [l],例如 [lrwxrwxrwx]。

  • rwx

    • r 是否可读。
    • w 是否可写。
    • x 是否可执行。

修改文件所属用户

chown foo iplist 修改文件iplist的所属用户为foo

chown foo.hello iplist同时修改文件iplist的所属用户为foo,用户组为hello

使用ls -l iplist:

1
-rwxr--r-- 1 foo hello 25 1月   8 11:15 iplist

####网络命令

远程操作指令

ssh(Secure Shell)

ssh user@ip

然后输入密码就可以登录进远程服务器。

ifconfig

查看本地IP以及本地有哪些网络接口

查看本地网络状态

netstat

不传任何参数的netstat帮助查询所有的本地 socket

socket 是网络插槽被抽象成了文件,负责在客户端、服务器之间收发数据。

查看TCP连接:

netstat -t

查看端口占用:

netstat -ntlp | grep 22

-n是将一些特殊的端口号用数字显示,-t是指看 TCP 协议,-l是只显示连接中的连接,-p是显示程序名称。

网络测试

ping

查看本机到某个网站的网络延迟。

1
2
3
4
5
6
7
➜  ~ ping www.baidu.com
PING www.a.shifen.com (180.101.49.11) 56(84) bytes of data.
64 bytes from 180.101.49.11 (180.101.49.11): icmp_seq=1 ttl=49 time=9.72 ms
64 bytes from 180.101.49.11 (180.101.49.11): icmp_seq=2 ttl=49 time=9.59 ms
64 bytes from 180.101.49.11 (180.101.49.11): icmp_seq=3 ttl=49 time=9.58 ms
--- www.a.shifen.com ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4005ms
  • ping一个网站需要使用 ICMP 协议。因此你可以在上图中看到 icmp 序号
  • ttl叫作 time to live,是封包的生存时间。
  • time是往返一次的时间。

telnet

查看本机到某个 IP + 端口的网络是否通畅

1
2
3
4
➜  ~ telnet www.baidu.com 443
Trying 180.101.49.12...
Connected to www.baidu.com.
Escape character is '^]'.
DNS查询

host

查询拉勾网的 DNS:

1
2
3
4
5
➜  ~ host www.lagou.com
www.lagou.com is an alias for lgmain.cdn.lagou.com.
lgmain.cdn.lagou.com has address 117.50.36.103
lgmain.cdn.lagou.com has address 106.75.118.232
lgmain.cdn.lagou.com has address 117.50.39.99

dig

显示的更加详细:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
➜  ~ dig www.lagou.com

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el7 <<>> www.lagou.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 63898
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;www.lagou.com. IN A

;; ANSWER SECTION:
www.lagou.com. 560 IN CNAME lgmain.cdn.lagou.com.
lgmain.cdn.lagou.com. 60 IN A 117.50.39.99
lgmain.cdn.lagou.com. 60 IN A 106.75.118.232
lgmain.cdn.lagou.com. 60 IN A 117.50.36.103

;; Query time: 1 msec
;; SERVER: 183.60.83.19#53(183.60.83.19)
;; WHEN: 五 1月 08 18:20:27 CST 2021
;; MSG SIZE rcvd: 104

软件的安装

yum

yum是Python 开发的,提供的是rpm包,因此只有redhat系的 Linux,比如 Fedora,Centos 支持yum。yum的主要能力就是帮你解决下载和依赖两个问题。

apt

sudo apt remove vim 删除vim

dpkg -l vim vim 的状态从ii变成了rc,r是期望删除,c是实际上还有配置文件遗留

sudo apt purge vim 可以彻底删除vim

进程和线程

进程和线程

  1. 进程是软件的副本,是计算机分配资源的最小单位。
  2. 线程运行在进程里,线程是CPU调度的最小单位。

原子操作

原子操作就是操作不可分。在多线程环境,一个原子操作的执行过程无法被中断。

i++ 由 读取 i 的值、计算 i +1 、把新值赋给 i 。

竞争条件

两个线程并发执行i++

https://s0.lgstatic.com/i/image/M00/68/E8/CgqCHl-lBrSAKBmrAADNiS8bkAY490.png

访问共享资源的程序片段我们称为临界区。

cas 指令

很多 CPU 都提供 Compare And Swap 指令。这个指令的作用是更新一个内存地址的值,比如把i更新为i+1,但是这个指令明确要求使用者必须确定知道内存地址中的值是多少。

tas 指令

Test-And-Set 指令(tas)。tas 指令的目标是设置一个内存地址的值为 1,它的工作原理和 cas 相似。

锁(lock),目标是实现抢占(preempt)。就是只让给定数量的线程进入临界区。

自旋锁

1
2
3
4
5
function lock(){
while(!getLock()){
// do nothing
}
}

使用一个while循环获取锁,直到锁被其它线程释放。这种情况线程不会主动释放资源,我们称为自旋锁。

  • 优点:不会发生线程切换,因为一直循环执行”空指令”。
  • 缺点:比较消耗CPU资源,如果一直拿不到锁,就会一直执行。

生产者消费者模型

Monitor 实现了生产者、消费者模型。

  • 如果一个线程拿到锁,那么这个线程继续执行;

  • 如果一个线程竞争锁失败,Montior 就调用 wait 方法触发生产者的逻辑,把线程加入等待集合;

  • 如果一个线程执行完成,Monitor 就调用一次 notify 方法恢复一个等待的线程。

分布式环境的锁

类似 redis 的 setnx 、setex 等指令。。

乐观锁

类似git提交冲突,假设冲突不会发生,等到发生时再处理。而不是一开始就拒绝(悲观锁)。

线程调度

  • 先到先服务
  • 短作业优先
  • 优先级队列
  • 抢占
  • 多级队列模型

饥饿和死锁

哲学家就餐问题:

11111.png

死锁有 4 个基本条件。

  • 资源存在互斥逻辑:每次只有一个线程可以抢占到资源。这里是哲学家抢占叉子。

  • 持有等待:这里哲学家会一直等待拿到叉子。

  • 禁止抢占:如果拿不到资源一直会处于等待状态,而不会释放已经拥有的资源。

  • 循环等待:这里哲学家们会循环等待彼此的叉子。

进程间通信

  • 管道 :管道的核心是不侵入、灵活,不会增加程序设计负担,又能组织复杂的计算过程。
  • 本地内存共享:共享内存的方式,速度很快,但是程序不是很好写,因为这是一种侵入式的开发。只要不是高性能场景,进程间通信通常不考虑共享内存的方式。
  • 本地消息/队列
  • 远程调用(rpc): RPC 真正的缺陷是增加了系统间的耦合。当系统主动调用另一个系统的方法时,就意味着在增加两个系统的耦合。长期增加 RPC 调用,会让系统的边界逐渐腐化。

内存管理

垃圾回收 gc

  • 引用计数算法(Reference Counter)
  • Root Tracing 算法
  • 标记-清除(Mark Sweep)算法
  • 三色标记-清除算法