本周重点
①计算机体系结构
1、最基本逻辑器件NAND(构造&代码实现AND、NOT、OR、XOR)
2、计算机硬件体系(CPU、内存、磁盘)
3、提高CPU性能水平
4、数据类型(二进制的原码、移码、补码;C语言的整数和浮点数)
5、操作系统(作用、结构)
②Linux的基本入门
1、Linux的基本命令
2、Linux用户和组的权限
3、iptables的应用
本周主要内容
DAY1 计算机体系结构
①最基本的逻辑器件NAND
基本NAND
a | b | NAND(a, b) |
---|---|---|
0 | 0 | 1 |
1 | 0 | 1 |
0 | 1 | 1 |
1 | 1 | 0 |
NAND电路
构造AND
a | b | AND(a, b) |
---|---|---|
0 | 0 | 0 |
1 | 0 | 0 |
0 | 1 | 0 |
1 | 1 | 1 |
构造NOT
a | NOT(a) |
---|---|
0 | 1 |
1 | 0 |
构造OR
A | B | OR(a, b) |
---|---|---|
0 | 0 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
1 | 1 | 1 |
构造“XOR”(见代码)
②C代码实现验证NAND构造
Linux入门以及GCC代码运行
展示目录:
ll,lsl: 代表的是list
进入目录:
cd#cd /home/os ,os是我自己创建的,你们可以自己创建
创建目录:
mkdir yangkm
编辑文本:
vi(m):i : 插入模式,代表可以编辑字符了;esc: 退出插入模式;保存并退出:先按【esc】推出插入模式,再按【:wq】创建文件:vi boolean.c (代表创建boolean.c文件)emacs
程序运行的过程:
C(【.c】文件) ————编译———> 汇编语言 ———-汇编程序——> 可重定向(机器码) ———链接器——> 可执行文件(机器码)
NAND测试:
保存之后,可以通过C语言的编译器进行编译:
gcc boolean.c -o booleangcc 【要编译的文件】 -o 【可执行文件的名词】
编译的优化级别:
gcc -Og sum_sub.c -o sum_sub #代表编译器优化“拉满”; gcc -O0 sum_sub.c -o sum_sub #代表编译器不做任何的优化 可以通过objdump -d sum_sub查看汇编程序具体在《CSAPP》第三章;
运行:
./boolean./可执行下文件名称
代码验证NAND逻辑
#include <stdio.h> #include <stdbool.h> bool nand(bool a, bool b) { return !(a && b); } bool and (bool a, bool b) { return nand(nand(a, b), nand(a, b)); } bool or (bool a, bool b) { return nand(nand(a, a), nand(b, b)); } bool not(bool a) { return nand(a, a); } bool xor (bool a, bool b) { bool nand1 = nand(a, b); bool nand2 = nand(a, nand1); bool nand3 = nand(b, nand1); return nand(nand2, nand3); } #代码实现MUX,下面会用 bool sel(bool a, bool b, bool s) { bool e = nand(s, s); bool c = nand(nand(a, s), nand(a, s)); bool d = nand(nand(e, b), nand(e, b)); return nand(nand(c, c), nand(d, d)); } #代码实现半加和全加器,下面会用 typedef struct { bool s; bool ca; } Result; Result sum(bool a, bool b) { Result result; result.s = xor (a, b); result.ca = and (a, b); return result; } Result asum(bool a, bool b, bool c) { Result result; bool d = xor (a, b); bool e = and (a, b); bool f = and (d, c); result.s = xor (d, c); result.ca = or (f, e); return result; } void main() { printf("%d\n", and (1, 1)); printf("%d\n", or (0, 1)); printf("%d\n", not(0)); printf("%d\n", xor (1, 1)); printf("%d\n", sel(1, 1, 1)); Result res = sum(1, 1); printf("%d %d\n", res.s, res.ca); Result res2 = asum(1, 1, 1); printf("%d %d\n", res2.s, res2.ca); }
③CPU
1、逻辑运算-ALU(计算)
构造MUX
sel:代表select;
a | b | sel | not(sel) | c =and(a, sel) | d=and(not(sel), b) | or(c, d) |
---|---|---|---|---|---|---|
0 | 0 | 0 | 1 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 0 | 1 | 1 |
1 | 0 | 0 | 1 | 0 | 0 | 0 |
1 | 1 | 0 | 1 | 0 | 1 | 1 |
0 | 0 | 1 | 0 | 0 | 0 | 0 |
0 | 1 | 1 | 0 | 0 | 0 | 0 |
1 | 0 | 1 | 0 | 1 | 0 | 1 |
1 | 1 | 1 | 0 | 1 | 0 | 1 |
构造”ALU”
arithmetic logic unit(运算逻辑单元)
ALU是CPU的核心。
与,或,非,异或,位移,乘法,除法,加法,减法(二进制)。 备注:MUX很多地方都会用,包括ALU
2、寄存器(存储)
DFF和MUX(NAND)构成;有记忆功能。
3、缓存(1-3级 i7)
也可以由DFF和MUX(NAND)构成;
4、程序计数器(PC)
也可以由DFF和MUX(NAND)构成;用来决定执行哪一条指令;
④内存(RAM和ROM)
1、DFF
时间是计算机里面设置好的,现实生活中的时间是连续的,计算机里面的时间是离散的,叫【cycle】,例如:
cycle=1秒
2、sequential logic时序逻辑单元
时序逻辑单元,普通(组合)的逻辑组件和DFF的组合(或者是单独的DFF):
3、构造寄存器
4、构造RAM(内存)
例:
如果是16个寄存器,那么k的长度(宽度)是4; 0-15个寄存器; 1111 = 15 如果是32个寄存器,那么k的宽度是5 寄存器0,寄存器1,寄存器2,... 寄存器15; 取第0个寄存器:0000 取第2个寄存器:0010 取第15个寄存器:1111
查找次数:
内存的查找次数取决于内存的大小, 如果从RAM8里面找寄存器,例如输入的K=001,那么找的是第1个寄存器; 如果从RAM64里面找寄存器,例如输入的K=001010,那么找到的是第2(010)个RAM8里面找第1个(001)寄存器。 内存越大,查找的次数越多。
5、缓存的局部性原理
概念:
能从“近”的地方取就不会到“远”的地方去。 1. 空间局部性; sum = sum + a[i];主要指的是a[i] 2. 时间局部性; sum = sum + a[i];主要指的是sum;
二维数组在内存的表示:
a[0][0], a[0][1], a[0][2].... a[0][M] a[1][0], a[1][1], a[1][2].... a[1][M] a[2][0], a[2][1], a[2][2].... a[2][M]
缓存局部性例子
import time import random import numpy as np import timeit # 创建一个大型的二维数组 size = 3000 twoDarray = np.random.rand(size, size) # 对行求和 def sum_rows(): return np.sum(twoDarray, axis=1) # 对列求和 def sum_columns(): return np.sum(twoDarray, axis=0) #测量执行时间 rows_time = timeit.timeit(sum_rows, number=size) columns_time = timeit.timeit(sum_columns, number=size) print(f"列求和时间:{columns_time}") print(f"行求和时间:{rows_time}")DFF和MUX(NAND)构成;有记忆功能。 由寄存器构成,多个寄存器构成一个缓存,由多个缓存再构成一个较大的缓存。 内存越大就意味着查询的次数越多;
重点:充分的利用缓存的局部性,写程序的时候要注意利用好缓存(实验的数据)。
⑤磁盘
硬盘:一般指的是机械硬盘和固态硬盘;磁盘:一般指的是机械硬盘。
⑥提高性能CPU的性能
计算机体系结构(Computer Architecture)是描述计算机各组成部分及其相互关系的一组规则和方法,是程序员所看到的计算机属性。计算机体系结构主要研究内容包括指令系统结构(Instruction Set Architecture,简称ISA)和计算机组织结构(Computer Organization)。
1、多核CISC
复杂指令系统(complex instruction set computer),代表x86。一般用于个人电脑。
1. 多线程(进程)之间的数据同步问题; 2. 散热问题(CPU普遍的问题,性能提高的同时降低散热)。
2、流水线RISC
精简指令系统(Reduced instruction set computer),代表MIPS(寄存器是32个)和ARM。一般是用于手机。
流水线(piple line)可以降低等待的时间。
依赖:
for ... sum1 = sum1 + a[i] sum2 = sum2 + a[i+1] #对奇数和偶数分别的进行相加,进行两次求和。
代码测试:
def my_dot(a, b): """ Compute the dot product of two vectors Args: a (ndarray (n,)): input vector b (ndarray (n,)): input vector with same dimension as a Returns: x (scalar): """ x = 0 for i in range(a.shape[0]): x = x + a[i] * b[i] return x np.random.seed(1) a = np.random.rand(10000000) # very large arrays b = np.random.rand(10000000) tic = time.time() # capture start time c = np.dot(a, b) toc = time.time() # capture end time # print(f"np.dot(a, b) = {c:.4f}") print(f"Vectorized version duration: {1000*(toc-tic):.4f} ms ") # tic = time.time() # capture start time c = my_dot(a,b) toc = time.time() # capture end time # print(f"my_dot(a, b) = {c:.4f}") print(f"loop version duration: {1000*(toc-tic):.4f} ms ") #print(twoDarry)
没有流水线:一条指令执行需要4个cycle,那后面的指令就必须要等4个cycle之后执行;
流水线:一条指令执行到1个cycle的时候,另外一个指令就可以进来了。
指令重排,要注意的是循环的地方,循环的地方会执行很多次;循环展开for 对奇数做加法for 对偶数做加法对两个结果相加;csapp书的里内容
应用:numpy的dot(人工智能里面用的很多)。
3、CPU的架构应用
手机:
mips和arm指令架构;
PC:
x86的指令架构;
不同的指令架构就代表不同的汇编语言:
1. hacker(《the_element_of_computer_systems》这本书的作者自创); 2. x86(《csapp》第三章, linux里面通过objdump -d 文件名); 3. mips(《David A. Patterson, John L. Hennessy - Computer Organization and Design MIPS Edition_ The Hardware_Software Interface-Morgan Kaufmann (2020)》);
通过汇编可以了解到底层的内存布局:
1. 如果寄存器多,可以不用每次都把值压入到栈里,性能会高一些。2. 逆向工程可以通过汇编到高级语言(程序编译执行的过程)。
DAY2 数据类型
①二进制-原码
Decimal(十进制) | Binary(二进制) | Decimal(十进制) | Binary(二进制) |
---|---|---|---|
0 | 0000 | -0 | 1000 |
1 | 0001 | -1 | 1001 |
2 | 0010 | -2 | 1010 |
3 | 0011 | -3 | 1011 |
4 | 0100 | -4 | 1100 |
5 | 0101 | -5 | 1101 |
6 | 0110 | -6 | 1110 |
7 | 0111 | -7 | 1111 |
缺点:
0表示不唯一; 加、减运算不统一,需要单独的硬件去做(符号)加法运算; 0010 1010 ------ 1100
②二进制-移码
-8 = 0000B
-7 = 0001B
-6 = 0010B
-5 = 0011B
-4 = 0100B
-3= 0101B
-2= 0110B
-1 = 0111B
0 = 1000B
1 = 1001B
2 = 1010B
3 = 0011B
4 = 0100B
5 = 0101B
6 = 0110B
+7 = 1111B
问题:
1. 0已经是唯一的; 2. -3 + -3 = 2(运算不统一); 0101 0101 ------ 1010
③二进制-补码
时钟有12个小时,7+8 = 15 —-> 15%12 = 3;15 = k * (12) + R —> 15 = 12 + 3;
0111 + (-0010) —> (-0010) = k(10000) + x —> (-0010 - x) = k (10000) —->
如果k=-1 -x = 10000 + 0010 x = 10000 - 0010 x = 1110 1110 = -2 -2 + 2 = 1110 + 0010 = 0000 -2 + 3 = 1110 + 0011 = 0001 -2转二进制: 方法1,10000 - 0010(2的二进制) = 1110 方法2,0010 ---取反--> 1101 ---+1---> 1110 1110以有符号的方式解析: 最高位是1,代表负数, 取反:0001,加一:0010 所以,最后的结果是等于-0010 = -2 1110以无符号的方式解析: 2^3 + 2^2 + 2^1 = 8+4+2 = 14;
③C语言-整数
无符号的整数和有符号的整数;
无符号是unsigned,有符号是singed;
大小:
机器如果超过32位:32位; 如果小于32位:要看实现的方式;
思路
给一个2进制,转成成十进制(有符号,无符号);
给一个十进制,转换成2进制;
实验
#include <stdio.h> void main() { int x = -1; unsigned u = 2147483648; printf("x = %u = %d\n", x, u); printf("u = %u = %d\n", u, u); printf("0==0U: %d\n", 0==0U); printf("-1<0: %d\n", -1 < 0); printf("-1<0U: %d\n", -1<0U); // 无符号和有符号的一起进行运算,会以无符号的为准 printf("2147483647 > -2147483647-1: %d\n", 2147483647 > -2147483647-1); printf("2147483647U > -2147483647-1: %d\n", 2147483647U > -2147483647-1); printf("2147483647 > (int) 2147483648U: %d\n", 2147483647 > (int) 2147483648U); printf("-1 > -2: %d\n", -1 > -2); printf("(unsigned) -1 > -2: %d\n",(unsigned) -1 > -2); if (-2147483648 < 2147483647) { printf("-2147483648 < 2147483647 is true\n"); } else { printf("-2147483648 < 2147483647 is false\n"); } if (-2147483648-1 < 2147483647) { printf("-2147483648-1 < 2147483647\n"); } else if (-2147483648-1 == 2147483647){ printf("-2147483648-1 == 2147483647 is false\n"); } else { printf("-2147483648-1 > 2147483647 is false\n"); } }
④C语言-浮点数
0.602 = 6.02 * 10^{-1} 0.062 = 6.02 * 10^{-2} 0.0000062
二进制和十进制转换:
十进制转二进制: 0.75 = 0.11 0.75 * 2 = 1.5 ---> 1 0.5 * 2 = 1.0 ---> 1 二进制转十进制: 0.11 = 0.75 1*2^{-1} + 1*2^{-2} = 0.5 + 0.25 = 0.75
C语言里面的float就是浮点数,一共有32位,(java里面也有)。
浮点数很容易出问题:0.1到0.2之间的数字就有很多,计算机没办法表示完。
E:是用移码来表示; 0.111...1*2^{11111111} = 01111111111111111111111111111111 E = 11111111 按照移码表示:11111111 - 10000000(偏置常数) = 1111111 1111111 转换成十进制 等于 127 0.111...1*2^{11111111} = 2^{-1} + 2^{-2} + ... + 2 ^{-23} * 2^{127} E = 10101010 10101010 - 10000000 = 101010 ---转成10进制---> 32 + 8 + 2 = 42 E = 00001000 00001000 - 10000000 = 8 - 128 = -120, 2^{-120} E = 00000000 00000000 - 10000000 = 0 - 128 = -128, 2^{-128} 浮点数最小的:0.1000...0 * 2^{-128} 浮点数最大的:0.1111...1 * 2^{127}
浮点数表示的标准是:IEEE754。
例子-浮点数的表示
16进制的数字是x=BEE00000H,x的的浮点数是多少? 【1】 【01111101】 【110 0000 0000 0000 0000 0000】 是一个负数; 阶码转换:01111101 = 125, 125 - 127 = -2 尾数部分:1+2^{-1} + 2^{-2} = 1.75 最后的值:-1.75 * 2^{-2} = -0.4375 x= -12.75, 16进制表示是多少; -1100.11 规格化:-1.10011*2^{3} E = 127 + 3 = 130 = 1000 0010 表示尾数部分:1001100 0000 0000 0000 0000 【1】【1000 0010】【1001100 0000 0000 0000 0000】 转换成十六进制:C14C0000
验证代码:
#include <stdio.h> typedef union { float f; unsigned int i; } FloatUnion; void main() { float p = -12.75f; FloatUnion u; u.f = p; printf("%08x\n", u.i); }
例子-浮点数有间隙(gap)
#include<stdio.h> void main() { float head = 61.419999f; printf("%f\n", head); }
DAY3 操作系统
①作用
1、虚拟化
好像每个程序都独占完整的内存;
2、并发
好像每个应用可以同时运行。
给CPU分配时间片
0-1毫秒:A程序1-2毫秒:B程序2-3毫秒:A程序
3、持久化
可以使用磁盘,把信息存入到磁盘,断电之后还可以使用。
4、安全
如果没有操作系统:
可以通过指针乱指内存,在内存里面乱写,可以改变别人的程序;可以自己随便的申请内存,让自己的程序占很多的内存;别人可以记住地址发起攻击;
②结构
③Linux和Windows提供的接口
④进程管理
⑤进程结构
#include <stdio.h> #include <unistd.h> #include <sys/types.h> int main() { int pid = fork(); int x = 1; if (pid == 0) { printf("child process id = %d\n", getpid()); printf("%d\n", ++x); } else {\ printf("parent process id = %d\n", getpid()); printf("%d\n", --x); } return 0; }
问题
进程间需要通信;
进程执行的顺序(同步)。
1 + ... + 100000000 有4个子进程,各自负责加一部分; 第1个进程的结果:x; 第2个进程的结果:y; 第3个进程的结果:a; 第4个进程的结果:b; 父进程:result = x+y+a+b;
解决通信:
1. 共享内存;(上课用到的书的3.16) 2. 管道; 3. 子进程往文件里面写内容,父进程读文件的内容(性能低下,不推荐)。
解决同步:
#include <stdio.h> #include <unistd.h> #include <sys/types.h> int main() { int pid = fork(); int x = 1; if (pid == 0) { sleep(2); printf("child process id = %d\n", getpid()); printf("%d\n", ++x); } else { printf("parent process id = %d\n", getpid()); wait(NULL); // 等子进程执行完毕才会继续往下执行 printf("%d\n", --x); } return 0; }
加载程序并执行
#include <stdio.h> #include <unistd.h> #include <sys/types.h> int main() { int pid = fork(); if (pid == 0) { execlp("/bin/ls", "ls", "-al", NULL); // 加载程序并执行; } else { wait(NULL); } return 0; }
DAY4 Linux基本命令
①使用Linux
修改网卡信息:vi /etc/sysconfig/network-scripts/ifcfg-ens33
重启网卡:systemctl restart network
查看ip:ip addr
关闭selinux ,vi /etc/sysconfig/selinux
可以通过远程连接的工具进行操作(cmd:ssh root@192.168.100.181
,xshell、finalshell、 tabby、堡塔、secureCRT);
②命令入门(概述)
分类:
内部命令 外部命令
Linux的命令写法:
ls 命令本身,代表列出当前文件夹的内容; ls -l 以列表的形式展示,包含创建时间等等信息; ls -al 展示所有的内容,其中a代表all
帮助:
man ls:查看ls的用法; 空格:下一页; 上下:上下; q:退出;
1、管道符号
概念:
把左边的输出当作右边的输入
例子:
ps -ef|grep 进程的名字; 通过这个命令可以查到进程的id; 通过id使用:kill -9 进程id 杀掉该进程; 可以使用top命令查看CPU占用高的进程;
2、重定向
> : 覆盖重定向,从标准输出(屏幕)到其它的文件; >> : 追加重定向
③常用的命令
1、目录操作
pwd(print work directory):展示当前所在的目录
[root@localhost ~]# pwd /root
cd:切换目录
cd .. : 返回上一级目录 cd . : 当前目录 cd 绝对路径和相对路径 cd ~:当前用户目录
2、文件(夹)创建
mkdir:创建文件夹 rmdir:删除文件夹 touch:创建文件 rm:删除单个文件 rm -rf [文件夹名],可以用来删除整个问价夹,linux有根文件夹,如果用这个命令可能会导致系统全部被删掉;
3、复制、移动目录或者文件
cp:copy mv:move [root@localhost os]# cp /home/os/test1/aaa /home/os/test2 [root@localhost test2]# mv aaa /home/os
4、软链接
类似于windows中的快捷方式。可以通过:
ln -s [实际文件位置] [快捷方式所在的位置] 例子:ln -s /home/aaa ./aaa
5、硬链接
删除了原文件之后还可以继续使用。一般用于备份日志,数据。
6、查找文件命令
which:查找命令所在的位置
which vi /usr/bin 注意,/usr/bin是外部命令的目录;
find 搜索文件
#按照名称查找,固定 find / -name history /root/.emacs.d/eshell/history /var/lib/yum/history #查找以xx开头的 [root@localhost /]# find /root/ -name "a*" /root/anaconda-ks.cfg /root/.emacs.d/auto-save-list 注意"*"是正则表达式是,代表匹配所有的内容 #按类型查找 find /home/os/ -type f f:普通文件; l:符号链接 d:目录 c:字符设备,比如键盘。 b:块设备,比如磁盘存储设备 s:套接字,socket编程,讲python的时候再去讲; p:pipe,管道(进程间通信的方式)
7、查看文件
cat 命令,查看文件内容,cat可以同时查看多个文件:
cat 1.txt 2.txt
more:
按SPACE键:显示下一页(屏)的内容; 按ENTER键:显示下一行的内容; 按b键:显示上一页(屏)的内容; 按q键:退出;
less:
PgUp:上一页 PgDn:下一页(空格) 搜索:/ + 要搜索的字符 + enter n(配合搜索用的):代表往下搜 N(配合搜索用的):代表往上搜 g: 回到第一行 G:到尾行 对比more,less不会【污染】屏幕
head(头部):
head -n 文件 展示文件内前n行的内容。
tail(尾巴):
tail -n 文件 展示文件内后n行的内容。
8、统计文件字符
wc(word count):
wc [选项] [文件名] 选项: -l : 行数 -w :字数 -c : 字节数
9、过滤字符
grep
grep "内容" [文件] #在文件里查找对应的内容 ps -ef|grep [进程名称]
10、压缩
-------压缩------- gzip [文件] 如果是对文件夹进行压缩,需要加上-r,也就是: gzip -r [文件夹] -------解压缩------- 解压缩单个文件:gunzip [文件] 解压缩文件夹:gunzip -r [文件夹]
11、归档
打包:tar -cvf [目标文件名].tar [原文件夹/文件] 解包:tar -xvf [原文件].tar
12、压缩并归档
压缩并打包:tar -zcvf [目标文件名].tar.gz [原文件夹/文件] 解包并解压:tar -zxvf [目标文件名].tar.gz 压缩并打包的文件名:os.tar.gz
④目录介绍
bin:binary(二进制)的缩写,里面有一些常用的命令。
dev:device(设备),硬件当作文件来处理的,CPU,内存,磁盘。
stderr,stdin,stdout 错误的和正确追加方式和windows一样; cd sdadasad >> log.txt 2>&1 #正确和错误的写法 Linux操作文件都是通过描述符。
home:家目录,Linux用户自己放的一些核心文件;
lib64:库文件,用来存放动态链接库的内容。
mnt:挂栽目录,用来挂栽外部的内容,比如说U盘,CDROM,光驱。。。。
proc:进程文件,用来描述进程的内容;
进程: 1. 内存里面运行的(磁盘里的叫程序); 2. 操作内存,CPU(寄存器,ALU。。。), 每个进程都有一个唯一的id,每个进程都有一个对应的文件夹,以进程id命名的。 创建进程就会生成对应的文件夹; Kill掉该进程就会删除掉对应的文件夹
srv:server,启动对应的服务之后会生成文件(如果启动http服务会生成www文件夹)。
tmp:临时文件,一些日志之类的;
var:是变量文件,里面比较重要的是log文件夹,存放的是系统的日志。
etc:比较重要,不能动,网卡配置,文件配置,用户信息配置等。
root:管理员的家文件;
usr:用户安装的目录(mysql,redis,tomcat);
bootstrap:引导文件。
补充颜色区分:
蓝色:目录;
绿色:可执行文件;
白色:一般文件;
红色:压缩文件或者是归档的文件
浅蓝色:链接文件;
红色闪烁:链接文件存在问题;
黄色:代表设备文件
青黄色:管道文件
⑤VI编辑器
1、简介
Linux和Unix系统下标准得编辑器。
vi可以忽略任何Linux和Unix的版本。
vim比vi更好看。
yum install -y vim
2、基本概念
vi编辑器的三种状态:
1. 命令模式:光标模式,进去就是命令模式; 2. 输入模式:插入模式,可以编辑,ESC退出。 3. 末行模式:: 就可以进入,ESC退出。
3、命令模式
hjkl:上下左右; dd: 剪切光标所在的这一行; p:粘贴到光标的下一行; P:粘贴到光标的上一行; yy:复制当前光标的这一行; 4yy:复制光标后的3行,一共是4行。 u:撤回操作; U:撤回当前行受影响的内容; x:剪切光标所在的字符 G:跳到末尾 gg:跳到首行的第一个字符 ctrl+左右键:按照一个一个单词去移动 n+:光标向下移动n行 n-:光标向下移动n行 H:光标移到当前屏幕的顶部; M:光标移到当前屏幕的中部; L:光标移到当前屏幕的d底部;
4、插入模式
a, i, o 的区别;
5、末行模式
set number:显示行号 set nonumber:不显示行号 /word:查找对应的单词,按n往下找,按N往上找 s/oldWord/newWord : 替换光标选中的单词 s/oldWord/newWord/g:替换光标选中的一行单词 %s/oldWord/newWord/gc:可以替换全部的,可以进行选择,选择a代表all也就是替换全部 保存退出:wq 保存不退出:w 强制退出不保存:q!
DAY5 用户组权限
①账号
用户账号
-
超级用户:root用户,是Linux操作系统中默认的超级用户账号,对本机的权限最高,类似于Windows操作系统的Adminstrator。
-
普通用户:对自己的【家目录】拥有所有的权限,zhangsan lisi。
-
程序用户:一般不允许登录,做ftp服务器,邮件。
组账号
-
多个用户绑定到一个组;
-
每个用户至少属于某一个组;
-
创建账号的时候,会自动创建一个组(和账号一致);
ID
-
分成uid和gid,uid代表用户id,gid代表组id;
-
UID:root用户的uid是0,而程序账号uid默认是1~499,普通用户的账号uid是500~60000;
-
GID:root的gid是0,程序账号组的是1~499,普通用户的账号gid是500~60000;
用户账号管理
[root@localhost os]# head -1 /etc/passwd root:x:0:0:root:/root:/bin/bash 第一个字段:root,代表账号的名称; 第二个字段:x,代表密码,是隐藏的; 第三个字段:0,uid; 第四个字段:0,gid; 第五个字段:root,备注,默认和用户一样; 第六个字段:/root,家目录的路径; 第七个字段:/bin/bash,/sbin/nologin,/bin/false
密码文件
[root@localhost os]# head /etc/shadow root:$6$410JV6fKqAvPcB80$rk3bbTCSQA8hA4zfDSvRxIzOe78ImKRzoeZQ2dYFvJuR2WQog34I.WXFpq1GBPx3zpiy.5cRzcMLwQMmQRUyz/::0:99999:7::: bin:*:18353:0:99999:7::: daemon:*:18353:0:99999:7::: adm:*:18353:0:99999:7::: lp:*:18353:0:99999:7::: sync:*:18353:0:99999:7::: shutdown:*:18353:0:99999:7::: halt:*:18353:0:99999:7::: mail:*:18353:0:99999:7::: operator:*:18353:0:99999:7::: 第一个字段:root,代表账号的名称; 第二个字段:sha-512算法,它是hash散列算法。如果是*或者是!!,代表该用户不允许登录。 第三个字段:最近一次修改密码时间的时隔天数; 第四个字段:0,密码最短有效时间,经过这个时间就会失效,0代表永不失效; 第五个字段:99999,密码最长的有效天数,99999代表永远不过期; 第六个字段:7,修改密码提示,提前7天提示修改密码; 第七个字段:密码过期多久后,禁用该用户 第八个字段:账户失效时间,账号作废的天数(1970开始计算),默认是空的,可以永久使用; 第九个字段:保留字段,目前没用。
②用户
创建用户
useradd kkk kkk:x:1002:1002::/home/kkk:/bin/bash /home/kkk:代表kkk生成的家目录 -e:失效时间 -p:密码(注意p-0p-0p-0设置不进去,要修改) -d:指定家目录(不指定的话就会直接生成一个和用户名一样的) -s:指定用户以何种方式登录 ----/bin/bash:代表可以登录 ----/sbin/nologin:代表不能登录,但是可以运行(ftp,邮件服务) ----/sbin/false:代表任何权限都没有
usermod
修改用户,和上面的用法事一样的 修改密码:passwd [用户名] 例如:passwd kkk 修改完成后,可以查看: 用户信息---> /etc/passwd 密码和有效时间 ---> /etc/shadow
userdel
userdel [用户名] #可以删掉用户,但是对应的家目录还在 userdel -r [用户名] #可以删掉用户,并且删掉家目录
passwd:
passwd命令:passwd [选项] 用户名 -d:清空密码; -l:锁定(lock)密码; -u:解锁(unlock)密码; -S:查看密码状态;
③用户组
创建组:
groupadd [选项] 组名称 [root@localhost home]# groupadd hacker [root@localhost home]# groupadd -g 7090 xj
修改组:
groupmod [选项] 组名称 groupmod -n hack hacker #把hacker修改成hack
删除组:
groupdel hacker
添加组成员:
gpasswd -a username groupname [root@localhost home]# gpasswd -a kkk xj
删除组成员:
gpasswd -d username groupname [root@localhost home]# gpasswd -d kkk root
查看用户所属的组:
groups kkk id kkk #查看详细信息 自己查:w,who,whoami #这个差别
修改文件的组
chgrp [-R] 组名 文件名 -R:递归修改文件夹里面的所有的文件 例子:chgrp -R kkk mmm,把mmm文件的归属改成属于组kkk
④权限的设置
查看文件(文件夹)的权限:
drwx------ 2 mmm kkk 76 Dec 28 03:25 mmm d:文件夹 -------三组内容------- 所属用户的权限:read(r),write(w),execute(x) 所属组的权限:---代表什么权限都没有 其它组的权限:---代表什么权限都没有
添加权限:
g+x: 表示对该文件的组赋予执行的权限 chmod u+x 文件名:给文件所属的用户加执行权限 chmod u+r 文件名:给文件所属的用户加读取权限 chmod u+w 文件名:给文件所属的用户加写的权限 chmod g+x 文件名:给文件所属的组添加执行权限 chmod g+r 文件名:给文件所属的组添加读取权限 chmod g+w 文件名:给文件所属的组添加写的权限 chmod o+x 文件名:给其它组写的权限 chmod o+r 文件名:给其它组读的权限 chmod o+w 文件名:给其它组写的权限 chmod g+x,g+r,g+w 文件名:给文件所属的组添加执行权限
去掉权限:
g-x: 表示对该文件的组赋予执行的权限 chmod u-x 文件名:给文件所属的用户去掉执行权限 chmod u-r 文件名:给文件所属的用户去掉读取权限 chmod u-w 文件名:给文件所属的用户去掉写的权限 chmod g-x 文件名:给文件所属的组去掉执行权限 chmod g-r 文件名:给文件所属的组去掉读取权限 chmod g-w 文件名:给文件所属的组去掉写的权限 chmod o-x 文件名:给其它组去掉写的权限 chmod o-r 文件名:给其它组去掉读的权限 chmod o-w 文件名:给其它组去掉写的权限 chmod g-x,g-r,g-w 文件名:给文件所属的组去掉执行权限
主组和附加组(补充):
1. 一个用户只能属于一个主组; 2. 一个用户可以属于多个附加组; 3. useradd -G :添加附加组;useradd -g: 添加主组; 4. gpasswd:第一个是主组,后面的是附加组。
chmod 数字 文件名
读 | 写 | 执行 |
---|---|---|
r | w | x |
4 | 2 | 1 |
7这个数字有几种组合的可能:1种;
6这个数字有几种组合的可能:1种;
5这个数字有几种组合的可能:1种;
4这个数字有几种组合的可能:1种;
3这个数字有几种组合的可能:1种;
2这个数字有几种组合的可能:1种;
1这个数字有几种组合的可能:1种;
上面是一对一的关系,所以只要知道一个数,就可以知道后面的3个数是什么,所以可以简化。
慎用:chmod 777 [文件名]
8进制:
7 + 2 = 118 + 3 = 13
进制:
二进制:xxB八进制:xxxo十六进制:xxxh三进制?
⑤下载
在线安装
命令:yum(yellow dog updater)
yum install net-tools
离线安装
RPM:类比于windows里面通过安装包直接安装
rpm -ivh [选项] 文件名
源码安装
直接编译源代码;
Makefile文件,C语言里,好几个文件单独的编译之后形成可重定向的文件,再进行链接(讲完shell之后再做个简单的实验)。
⑥网络命令
ping命令:
ping ip -c :发送几个数据包; -i :多长时间发一次; -f -c :尽可能多的发; -s:单个数据包的大小;
ip命令:
ip addr #查看 ip route#查看路由 ip link #查看网卡的mac地址 #添加默认网关#删除路由表#刷新路由表#启动网卡#关闭网卡
netstat(注意,要通过yum下载net-tools文件)
netstat -anlp #分别查询a,n,l,p的含义
traceroute跟踪路由
#自己查要下载什么工具 #自己查作用
⑦iptables
基础概念
安全框架:netfilter是出于Linux的内核中,用户要和netfilter进行交互,就要使用到iptables(从某种成都上来说可以代替防火墙).
四表五链:
iptable的使用:
systemctl stop firewalld systemctl disable firewalld yum install -y iptables iptables-services systemctl start iptables systemctl enable iptables iptales -t nat -nL #查看nat表