# Basic

## 内核

**输入设备**：鼠标、键盘等。\
**输入设备驱动**：\
**中断事件（Interrupt Event）**：\
**输出设备**：显示器等。\
**输出设备驱动**：如显卡驱动\
**文件管理子系统（File Management Subsystem）**：硬盘是个物理设备，要按照规定格式化成为文件系统，文件管理子系统负责管理文件系统。\
**进程管理子系统（Process Management Subsystem）**：在操作系统中，进程需要分配 CPU 进行执行。\
**内存管理子系统（Memory Management Subsystem）**：不同的进程有不同的内存空间，但是整个电脑内存就这么点儿，所以需要统一管理和分配。\
**程序（Program）**：二进制的执行文件，是静态的。\
**进程（Process）**：运行起来的程序。\
**系统调用（System Call）**：很多操作是放在操作系统内核的，进程不能随便调用，比如打印机，进程需要通过系统调用来使用打印机。

![](/files/-LbW0Rd5CdGapX5gCrC4)

## 常用命令

### 磁盘管理

```bash
# list block device
lsblk

lsblk -ip $device
lsblk -ip /dev/sde

# 显示设备的 UUID
blkid

# 显示分区信息
parted $device print
parted /dev/sde print

# 显示分区信息
cat /proc/partitions

# for MBR
fdisk $divice

# for GPT
gdisk $device
gdisk /dev/sdc
gdisk -l /dev/sdb

# gdisk 操作完后，使之生效，不然要重启才会生效
partprobe -s

# 格式化
mkfs.ext4 $device
mkfs.xfs $device

# 挂载
mount
mount -l

# 卸载
umount $device
umount /dev/sdb1
```

#### LVM

```bash
# pv阶段
pvscan
pvdisplay

pvcreate /dev/sdb{1,2}

pvremove /dev/sdb{1,2} /dev/sdc{1,2}

# vg 阶段
vgscan
vgdisplay

vgcreate -s 16M influxdbvg /dev/sdb{1,2} /dev/sdc{1,2}

vgextend influxdbvg /dev/sdc3

vgremove influxdbvg

# lv 阶段
lvscan
lvdisplay

lvcreate -L 2048G -n influxdblv influxdbvg
lvresize -L +512G /dev/influxdbvg/influxdblv

lvremove /dev/influxdbvg/influxdblv
```

### 用户管理

```bash
# 创建用户
# 创建之后不会让你输入密码，需要通过 passwd 设置密码
# 若没有指定组，则默认创建一个同名的组
useradd [username]

# 设置密码
passwd

# 用户名:密码:用户ID:组ID:用户描述:用户目录:默认命令行
/etc/passwd
root:x:0:0:root:/root:/bin/zsh
...

# 组名::组ID
/etc/group
root:x:0:
...
```

### 文件管理

```bash
# 切换目录 change directory
cd
cd ..

# 查看目录 list
ls

# 第一个字符是文件类型，d 表示目录
# 剩下的9个是权限位，三个一组，分别为用户、组、其它。
# 第二个字段是硬链接（hard link）数目
# 第三个是所属用户，第四个是所属组，第五个是文件大小，第六个是被修改日期
ls -l
drwxr-xr-x 11 root root 4096 Mar 29 17:25 resource
-rw-r--r--  1 root root   24 Mar 18 11:23 token

# 打印文件内容到命令行
cat

# 合并多个文件
cat file1.sql doc*.sql >> merge.sql

# 编辑文件
vim

# 修改文件所属用户
chown

# 修改文件所属组
chgrp

# 下载文件
wget

# 过滤文件
grep

# 分页查看文件，仅支持向后翻页
more

# 分页查看文件，可以前后翻页
less

# 同步文件
rsync
rsync -av $SRC $DEST
```

### 软件管理

Linux 常用的有两种体系，CentOS 和 Ubuntu，前者使用 rpm 安装软件，后者使用 deb 安装软件。

```bash
# 安装 -i: install
rpm -i XXX.rpm # CentOS
dpkg -i XXX.rpm # Ubuntu

# 查找
rpm -qa # q: query, a: all
dpkg -l # l: list

# 删除
rpm -e # e: erase
dpkg -r # r: remove

# 搜索
yum search jdk
apt-cache jdk

# 安装
yum install XXX
apt-get install XXX

# 删除
yum erase XXX
apt-get purge XXX

# 配置文件
/etc/yum.repos.d/
/etc/apt/sources.list

```

### 运行程序

```bash
# 运行当前目录的一个程序
./program
# 退出该程序
ctrl + c

# 后台运行 no hang up
# 1文件描述符表示标准输出，2表示标准错误输出，&表示合并
# 最后一个&表示后台运行
nohup [command] > [filename] 2>&1 &

# 退出一个进程
ps -ef |grep [keyword] |awk '{print $2}'  |xargs kill -9

# 设置开机启动 /usr/lib/systemd/system 会创建一个 XXX.service
systemctl enable XXX
# 启动
systemctl start XXX
# 关闭
systemctl stop XXX

# 跟踪进程执行时系统调用和所接受的信号量
strace
```

### 系统管理

```bash
# 立即关机
shutdown -h now

# 重启
reboot

# 环境变量
.bashrc

export XXX=sss
```

### grep

```
# 在文件中查找某段文本
grep 'text' file.name

# 在目录中的所有文件中查找某段文本
grep 'text' -r folder
```

### find

```bash
# 在当前目录查找60天之前的文件
find . -mtime +60

# 删除当前目录下60天之前的文件
find . -mtime +60 -delete
find . -mtime +60 -exec rm -rf {} \;

# 查找当前目录下的空文件夹
find . -type d -empty

# 删除当前目录下的空文件夹
find . -type d -empty -delete
```

### ssh

在本地建立代理到 `10.5.3.32`

```
ssh -D 0.0.0.0:1082 -f -C -q -N root@10.5.3.32
```

通过代理 Socket5 代理（`10.211.55.4:1081`）连上 `10.5.3.33`

```
ssh -o ProxyCommand='nc -x 10.211.55.4:1081 %h %p' root@10.5.3.33
```

组合以上两个，在本地建立代理到 `192.166.127.32`，本机是通过`192.166.127.15:1031`的 Socket5 代理连到`192.166.127.32`

```
ssh -D 0.0.0.0:1082 -f -C -q -N -o ProxyCommand='nc -x 192.166.127.15:1031 %h %p' root@192.166.127.32
```

通过跳板机直连&#x20;

```bash
cat ~/.ssh/config

Host 172.16.1.*
        User root
        Port 22
        ProxyCommand ssh root@10.0.197.12 -W %h:%p
Host test
        User root
        Port 22
        HostName 172.16.1.4
        ProxyCommand ssh root@10.0.197.12 -W %h:%p
```

* `ssh 172.16.1.*` 可以直接通过跳板机 `10.0.197.12` 连接`172.16.1.*`，即支持通配符。
* `ssh test` 可以直接通过跳板机 `10.0.197.12` 连接`172.16.1.4`。

### ssh 免密登录

​SSH 是一个安全性协议，默认 SSH 链接需要密码，可以通过添加配置公钥、私钥来实现免密码登录。

​对信息的加密采用 private key，对信息的解密采用 public key。若客户端A想要登录服务器B，public key 放在 B 上，private key 放在 A 上;

​当 A 连接 B 时，B 生成一个随机数并用 public key 加密发送给 A，A 用 private key 解密发送给 B，B 确认无误后，允许 A 登录。

```bash
ssh-keygen -t rsa

ip="10.4.34.47" && \
ssh root@${ip} 'mkdir -p ~/.ssh' && \
cat ~/.ssh/id_rsa.pub | ssh root@${ip} 'cat >> ~/.ssh/authorized_keys' && \
ssh root@${ip} 'chmod 600 .ssh/authorized_keys'
```

## 系统调用

{% hint style="info" %}
系统调用可以理解为特殊的 C 语言函数，它们是连接应用程序和操作系统内核的桥梁，也是应用程序使用操作系统功能的唯一渠道。
{% endhint %}

`strace` 可以跟踪进程执行时系统调用和所接受的信号量。

### 进程管理

`fork`

* 在Linux 里，创建一个进程需要一个老的进程调用 fork 实现，老的进程叫做父进程（Parent Process），新的叫做子进程（Child Process）。
* 操作系统在启动的时候先创建一个所有用户进程的“祖宗进程”。
* 调用 fork 后，就有两个一样的进程，根据返回值来判断进程。若是子进程，则返回 0；若是父进程，则返回子进程的进程号。

Unix fork 使用了[写时复制](/notes/java/concurrency/concurrency-design-patterns/copy-on-write.md)的思想，子进程会创建父进程的完整副本，比如父进程有 1G 内存，那么子进程会复制完整的 1G 内存。但是 Linux 优化了，fork 的时候让父子进程共享地址空间，仅在父进程或子进程写入的时候才会复制。

`execve`

调用 fork 后，判断 fork 返回0，再调用 execve 来执行另一个程序。

`waitpid`

父进程调用它，将子进程的 ID 作为参数，父进程就可以知道子进程运行是否结束，是否成功。

### 内存管理

每个进程都有自己的**进程内存空间**，又分为代码段（Code Segment）、数据段（Data Segment）。数据段又分为局部变量的部分，函数进入与退出的时候创建与销毁；动态分配部分，保存较长、显式才销毁，这部分称为堆（Heap）。

`brk`：适合申请的内存较小，会和原来的堆数据连在一起。

`mmap`：重新划分一块区域。

### 文件管理

Linux 一切皆文件，标准输出（stdout）、管道、Socket、设备、文件夹等都是文件，Linux 给 每个文件分配一个文件描述符（File Descriptor），是一个整数。

`open`

`close`

`create`

`lseek`：跳到文件的某个位置。

`read`

`write`

### 信号处理

`kill`

将一个用户信号发送给另一个进程。

`sigaction`

注册一个信号处理函数。

### 进程间通信

{% hint style="info" %}
进程间通信有很多方式，主要包括：系统信号（signal）、管道（pipe）、套接字（socket）、文件锁（file lock）、消息队列（message queue）、信号量（semaphore）。
{% endhint %}

`msgget`

创建消息队列。

`msgsnd`

发送消息给消息队列。

`msgrcv`

从消息队列中取消息。

`shmget`

创建共享内存。

`shmat`

将共享内存映射到自己的内存空间。

`sem_wait`

占用信号量，若无人占用则可以占用；若已经被占用，则需要等待。

`sem_post`

释放信号量。

### 网络通信

`socket`

创建套接字。

`bind`

绑定端口。

`connect`

发起连接。

`accept`

接受连接。

`listen`

监听。

### Glibc

Linux 下标准的 C 库，GUN 发布的 libc 库。Glibc 为程序员提供丰富的 API，除了例如字符串处理、数学运算等用户态服务之外，最重要的是封装了操作系统提供的系统提供的系统服务，即系统调用的封装。

## NFS

```bash
yum -y install firewalld
systemctl start firewalld.service
systemctl enable firewalld.service
firewall-cmd --permanent --zone=public --add-service=ssh
firewall-cmd --permanent --zone=public --add-service=nfs
firewall-cmd --zone=public --add-service=rpc-bind --permanent
firewall-cmd --zone=public --add-service=mountd --permanent
firewall-cmd --reload

yum -y install nfs-utils

systemctl enable rpcbind
systemctl start rpcbind
systemctl enable nfs-server
systemctl start nfs-server

mkdir /nfsdata
chown nfsnobody:nfsnobody  /nfsdata
chmod 755 /nfsdata

vi /etc/exports

/nfsdata 172.16.0.0/16(rw,sync,no_subtree_check,no_root_squash)

exportfs -a
```

#### Reference

* <http://blog.topspeedsnail.com/archives/4109>
* <https://www.howtoforge.com/tutorial/setting-up-an-nfs-server-and-client-on-centos-7/>

## DNS

### resolve.conf

Linux DNS 解析的配置文件 `/etc/resolve.conf`。

nameserver：dns服务器地址

options：

* ndot 域名中最少包含点的个数
* timeout 超时时间，单位秒，默认5
* attempts 重试次数
* rotate 默认每次都是从头到尾依次请求nameserver，加上此参数会循环请求
* single-request 默认glibc会发送IPv4和IPv6两个并发的请求，此参数会同步发送single-request-reopen CentOS 6中的DNS解析器对于ipv4和ipv6都使用同一个socket接口，在同时发出ipv4 和ipv6解析请求后，只会收到一个ipv4的解析响应，此时socket将一处于“等待”模式，等待ipv6的解析响应，故导致解析缓慢；添加single-request-reopen后就可以重新打开一个新的socket接收ipv6的解析响应，而不影响ipv4的解析响应。

### Docker 配置 DNS

* \--dns=IP\_ADDRESS...
* \--dns-search=DOMAIN...
* \--dns-opt=OPTION...

### Kubernetes 配置 DNS

```
apiVersion: v1
kind: Pod
metadata:
  namespace: default
  name: dns-example
spec:
  containers:
    - name: test
      image: nginx
  dnsPolicy: "None"
  dnsConfig:
    options:
    - name: timeout
      value: "1"
    - name: attempts
      value: "2"
    - name: rotate
    - name: single-request-reopen
```

## 动态追踪技术

通过探针机制采集内核或应用程序的运行信息，不用修改内核和应用程序的代码，获得丰富的信息。相比于断点，不会中断程序运行；相比于日志，不需要重新编译和部署。仅会带来很小的性能损耗，小于 5%。

为了追踪内核或用户空间的事件，Dtrace 和 SystemTap 都会把用户传入的追踪处理函数（一般称为 Action），关联到被称为探针的检测点上。这些探针，实际上也就是各种动态追踪技术所依赖的**事件源**。

DTrace 源于 Solaris，是动态追踪技术的鼻祖。无法在 Linux 中运行。在内核中常驻运行，把 D 语言脚本提交到内核的运行时执行。

SystemTap 没有常驻运行时，需要先把脚本编译成内核模块，再插入内核执行，所以启动较慢。

### 事件源

分为静态探针、动态探针、硬件事件三类。

![](/files/-MPgNTBlIveH9_hsn3aI)

### 动态追踪机制

Linux 提供了一系列动态追踪机制，如 ftrace、perf、eBPF（Linux 版的 DTrace，BCC）、SystemTap、sysdig 等。

![](/files/-MPgPYKhn_ikze34w5h5)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://yunzhao.gitbook.io/notes/computer-science/linux/basic.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
