普通视图

Received before yesterday

IPv4和IPv6

2024年11月23日 00:00

原文地址:https://www.rockylinux.cn/notes/rocky-linux-9-network-configuration.html
原文作者:木子
Rocky Linux 中文社区欢迎您 https://www.rockylinux.cn

IPv4 与 IPv6

在进行 IP 配置之前,我们延伸了解一下 IPv4 与 IPv6 。 IPv4(Internet Protocol version 4)和 IPv6(Internet Protocol version 6)是互联网上用于数据包交换的两个版本的网络层协议。它们是互联网协议套件的核心部分,负责在网络设备之间路由和传递数据。

IPv4

IPv4 是第四版互联网协议,自 1981 年以来一直被广泛使用。IPv4 的特点包括: 地址空间: IPv4 使用 32 位地址,这意味着它可以支持大约 42 亿个独特的 IP 地址。 地址表示: IPv4 地址通常以点分十进制格式表示,例如 192.168.1.1。 地址配置: IPv4 地址可以手动配置(静态)或通过动态主机配置协议(DHCP)自动分配。 分片: IPv4 允许在传输过程中对数据包进行分片,这可以由发送端、接收端或中间路由器处理。 由于互联网的快速增长,IPv4 地址已经耗尽,这促使了对更广泛地址空间协议的需求。 在 IPv4 地址空间中,地址分为公网 IP、私有 IP 和 CGN(Carrier Grade NAT)地址。以下是详细区分:

公网 IP 地址

公网 IP 地址是全球唯一的,可以在整个互联网中进行通信的 IP 地址。它们不属于下列提到的私有 IP 和 CGN 地址的范围。所以,除了以下私有 IP、CGN 地址以及保留地址和特殊用途地址(如多播地址、环回地址等),其他的都属于公网 IP。

私有 IP 地址

私有 IP 地址用于局域网(LAN)内部通信,是不会在互联网中进行路由的。这些地址范围由 IANA(Internet Assigned Numbers Authority)分配:

  1. 10.0.0.0 到 10.255.255.255
  2. 172.16.0.0 到 172.31.255.255
  3. 192.168.0.0 到 192.168.255.255

CGN (Carrier Grade NAT) 地址

CGN 地址也称为共享地址空间,用于 ISP 提供的 NAT 方案,以减少 IPv4 地址的消耗。以下是该范围:

  1. 100.64.0.0 到 100.127.255.255

这些地址也不会在全球互联网中进行路由,用于解决多个用户共享一个公共 IP 地址的需求(Tailscale 用的这个地址段)。

其他特殊地址

还有一些保留和特殊用途的地址,例如:

  • 环回地址: 127.0.0.1
  • 广播地址: 255.255.255.255
  • 多播地址: 224.0.0.0 到 239.255.255.255

IPv6

IPv6 是互联网协议的最新版本,旨在解决 IPv4 地址耗尽的问题,并引入了一些新的特性和改进。IPv6 的特点包括:

  • 地址空间: IPv6 使用 128 位地址,极大地扩展了地址空间,可以支持近乎无限数量的独特 IP 地址。
  • 地址表示: IPv6 地址通常以冒号分隔的十六进制格式表示,例如 2001:0db8:85a3:0000:0000:8a 2 e:0370:7334。
  • 地址配置: IPv6 地址可以通过多种方式配置,包括静态配置、状态无关地址自动配置(SLAAC)和动态主机配置协议版本 6(DHCPv 6)。
  • 无分片: IPv6 设计时取消了路由器的分片功能,要求发送端执行路径最大传输单元(PMTU)发现,并发送适合路径上最小链路 MTU 的数据包。 在 IPv6 中,没有对应 IPv4 的私有 IP 和公网 IP 的概念,但有类似的机制来实现内网和公网的区别与应用。以下是一些重要的 IPv6 地址类型和其用途:

全球单播地址(Global Unicast Address)

全球单播地址就是 IPv6中用于在全球范围内进行通信的唯一地址,类似于 IPv4的公网 IP。其地址范围一般是以 2000::/3 开头。

唯一本地地址(Unique Local Address, ULA)

唯一本地地址在某种程度上类似于 IPv4的私有 IP 地址,用于局域网通信,不会在全球互联网中进行路由。其地址范围是 FC00::/7,也可以细分为以下两个范围:

  • 随机分配的 ULA: FD00::/8,通用情况下会使用这个范围,通过随机生成的方式保证在局部网络内的唯一性。
  • 原始分配的 ULA: FC00::/8,目前未正式广泛使用。

链路本地地址(Link-Local Address)

这些地址只能用于单个网络链路的节点之间,不能路由到其他链路。所有 IPv6 接口在启动时都会自动生成一个链路本地地址以支持邻居发现协议。其地址范围是 FE80::/10

不管是 Linux、macOS 还是 Windows 都会分配一个 Link-Local Address,以inet6 FE80::开头。

# Linux[root@localhost ~]# ifconfigens18: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500        inet 192.168.1.3  netmask 255.255.255.0  broadcast 192.168.1.255        inet6 fe80::486a:e224:31e4:d1fc  prefixlen 64  scopeid 0x20<link>        ether 52:ea:eb:77:3d:fe  txqueuelen 1000  (Ethernet)        RX packets 112410841  bytes 40294807433 (37.5 GiB)        RX errors 0  dropped 0  overruns 0  frame 0        TX packets 64910  bytes 24656852 (23.5 MiB)        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0 # macOS❯ ifconfigen0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500    options=400<CHANNEL_IO>    ether f8:28:19:6a:2b:0f    inet6 fe80::18cd:9189:ab4:ef40%en0 prefixlen 64 secured scopeid 0x6    inet 192.168.1.2 netmask 0xffffff00 broadcast 192.168.1.255    nd6 options=201<PERFORMNUD,DAD>    media: autoselect    status: active # WindowsPS C:\Users\muzi> ipconfigWindows IP 配置以太网适配器 以太网:    连接特定的 DNS 后缀 . . . . . . . :   本地链接 IPv6 地址. . . . . . . . : fe80::530b:7d8a:998a:f3f5%16   IPv4 地址 . . . . . . . . . . . . : 192.168.1.1   子网掩码  . . . . . . . . . . . . : 255.255.255.0   默认网关. . . . . . . . . . . . . : 192.168.1.254

其他类型地址

还有一些其他特殊用途的地址,比如:

  • 多播地址: FF00::/8,用于多播通信。
  • 组播地址: FF00::/8,用于组播通信。

IPv4 与 IPv6 之间的主要区别

  • 地址长度: IPv4 是 32 位,IPv6 是 128 位。
  • 地址表示法: IPv4 使用点分十进制,而 IPv6 使用冒号分隔的十六进制。
  • 地址空间: IPv6 提供了比 IPv4 更广阔的地址空间。
  • NAT 转换: 消除 NAT 以将地址空间从 32 位扩展到 128 位。
  • IPSec 支持: 在 IPv6 中,IPSec 是核心特性的一部分,但同样也需要进行配置,比如采用 strongswan 等。
  • 数据包处理: IPv6 简化了数据包头部,以提高路由效率,并取消了路由器分片功能。
  • 自动配置: IPv6 支持更高级的自动配置能力。
  • 多播和广播: IPv6 支持多播,但不支持 IPv4 那样的网络广播。取而代之,IPv6 使用多播和邻居发现协议来实现网络上的设备发现和配置。

IPv4 与 IPv6 这些区别反映了互联网协议在安全性、效率、可扩展性方面的进步,同时也提出了新的挑战,例如迁移和兼容性问题。随着 IPv6 逐渐被广泛采用,这些挑战将得到解决。

以下两图为 IPv4 与 IPv6 报文头对比:


Linux信号(signal)机制

2024年10月12日 00:00

信号(signal)是一种软中断,信号机制是进程间通信的一种方式,采用异步通信方式

一、信号类型

Linux系统共定义了64种信号,分为两大类:可靠信号与不可靠信号,前32种信号为不可靠信号,后32种为可靠信号。

1.1 概念

  • 不可靠信号: 也称为非实时信号,不支持排队,信号可能会丢失, 比如发送多次相同的信号, 进程只能收到一次. 信号值取值区间为1~31;

  • 可靠信号: 也称为实时信号,支持排队, 信号不会丢失, 发多少次, 就可以收到多少次. 信号值取值区间为32~64

1.2 信号表

在终端,可通过kill -l查看所有的signal信号

取值名称解释默认动作
1SIGHUP挂起
2SIGINT中断
3SIGQUIT退出
4SIGILL非法指令
5SIGTRAP断点或陷阱指令
6SIGABRTabort发出的信号
7SIGBUS非法内存访问
8SIGFPE浮点异常
9SIGKILLkill信号不能被忽略、处理和阻塞
10SIGUSR1用户信号1
11SIGSEGV无效内存访问
12SIGUSR2用户信号2
13SIGPIPE管道破损,没有读端的管道写数据
14SIGALRMalarm发出的信号
15SIGTERM终止信号
16SIGSTKFLT栈溢出
17SIGCHLD子进程退出默认忽略
18SIGCONT进程继续
19SIGSTOP进程停止不能被忽略、处理和阻塞
20SIGTSTP进程停止
21SIGTTIN进程停止,后台进程从终端读数据时
22SIGTTOU进程停止,后台进程想终端写数据时
23SIGURGI/O有紧急数据到达当前进程默认忽略
24SIGXCPU进程的CPU时间片到期
25SIGXFSZ文件大小的超出上限
26SIGVTALRM虚拟时钟超时
27SIGPROFprofile时钟超时
28SIGWINCH窗口大小改变默认忽略
29SIGIOI/O相关
30SIGPWR关机默认忽略
31SIGSYS系统调用异常

对于signal信号,绝大部分的默认处理都是终止进程或停止进程,或dump内核映像转储。 上述的31的信号为非实时信号,其他的信号32-64 都是实时信号。

二、信号产生

信号来源分为硬件类和软件类:

2.1 硬件方式

  • 用户输入:比如在终端上按下组合键ctrl+C,产生SIGINT信号;
  • 硬件异常:CPU检测到内存非法访问等异常,通知内核生成相应信号,并发送给发生事件的进程;

2.2 软件方式

通过系统调用,发送signal信号:kill(),raise(),sigqueue(),alarm(),setitimer(),abort()

  • kernel,使用 kill_proc_info()等
  • native,使用 kill() 或者raise()等
  • java,使用 Procees.sendSignal()等

三、信号注册和注销

3.1 注册

在进程task_struct结构体中有一个未决信号的成员变量 struct sigpending pending。每个信号在进程中注册都会把信号值加入到进程的未决信号集。

  • 非实时信号发送给进程时,如果该信息已经在进程中注册过,不会再次注册,故信号会丢失;
  • 实时信号发送给进程时,不管该信号是否在进程中注册过,都会再次注册。故信号不会丢失;

3.2 注销

  • 非实时信号:不可重复注册,最多只有一个sigqueue结构;当该结构被释放后,把该信号从进程未决信号集中删除,则信号注销完毕;
  • 实时信号:可重复注册,可能存在多个sigqueue结构;当该信号的所有sigqueue处理完毕后,把该信号从进程未决信号集中删除,则信号注销完毕;

四、信号处理

内核处理进程收到的signal是在当前进程的上下文,故进程必须是Running状态。当进程唤醒或者调度后获取CPU,则会从内核态转到用户态时检测是否有signal等待处理,处理完,进程会把相应的未决信号从链表中去掉。

4.1 处理时机

signal信号处理时机: 内核态 -> signal信号处理 -> 用户态:

  • 在内核态,signal信号不起作用;
  • 在用户态,signal所有未被屏蔽的信号都处理完毕;
  • 当屏蔽信号,取消屏蔽时,会在下一次内核转用户态的过程中执行;

4.2 处理方式

进程对信号的处理方式: 有3种

  • 默认 接收到信号后按默认的行为处理该信号。 这是多数应用采取的处理方式。
  • 自定义 用自定义的信号处理函数来执行特定的动作
  • 忽略 接收到信号后不做任何反应。

4.3 信号安装

进程处理某个信号前,需要先在进程中安装此信号。安装过程主要是建立信号值和进程对相应信息值的动作。

信号安装函数

  • signal():不支持信号传递信息,主要用于非实时信号安装;

  • sigaction():支持信号传递信息,可用于所有信号安装;
    其中 sigaction结构体

  • sa_handler:信号处理函数

  • sa_mask:指定信号处理程序执行过程中需要阻塞的信号;

  • sa_flags:标示位

    • SA_RESTART:使被信号打断的syscall重新发起。
    • SA_NOCLDSTOP:使父进程在它的子进程暂停或继续运行时不会收到 SIGCHLD 信号。
    • SA_NOCLDWAIT:使父进程在它的子进程退出时不会收到SIGCHLD信号,这时子进程如果退出也不会成为僵 尸进程。
    • SA_NODEFER:使对信号的屏蔽无效,即在信号处理函数执行期间仍能发出这个信号。
    • SA_RESETHAND:信号处理之后重新设置为默认的处理方式。
    • SA_SIGINFO:使用sa_sigaction成员而不是sa_handler作为信号处理函数。

函数原型:

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

  • signum:要操作的signal信号。
  • act:设置对signal信号的新处理方式。
  • oldact:原来对信号的处理方式。
  • 返回值:0 表示成功,-1 表示有错误发生。

4.4 信号发送

  • kill():用于向进程或进程组发送信号;
  • sigqueue():只能向一个进程发送信号,不能像进程组发送信号;主要针对实时信号提出,与sigaction()组合使用,当然也支持非实时信号的发送;
  • alarm():用于调用进程指定时间后发出SIGALARM信号;
  • setitimer():设置定时器,计时达到后给进程发送SIGALRM信号,功能比alarm更强大;
  • abort():向进程发送SIGABORT信号,默认进程会异常退出。
  • raise():用于向进程自身发送信号;

4.5 信号相关函数

信号集操作函数

  • sigemptyset(sigset_t *set):信号集全部清0;
  • sigfillset(sigset_t *set): 信号集全部置1,则信号集包含linux支持的64种信号;
  • sigaddset(sigset_t *set, int signum):向信号集中加入signum信号;
  • sigdelset(sigset_t *set, int signum):向信号集中删除signum信号;
  • sigismember(const sigset_t *set, int signum):判定信号signum是否存在信号集中。

信号阻塞函数

  • sigprocmask(int how, const sigset_t *set, sigset_t *oldset)); 不同how参数,实现不同功能
    • SIG_BLOCK:将set指向信号集中的信号,添加到进程阻塞信号集;
    • SIG_UNBLOCK:将set指向信号集中的信号,从进程阻塞信号集删除;
    • SIG_SETMASK:将set指向信号集中的信号,设置成进程阻塞信号集;
  • sigpending(sigset_t *set)):获取已发送到进程,却被阻塞的所有信号;
  • sigsuspend(const sigset_t *mask)):用mask代替进程的原有掩码,并暂停进程执行,直到收到信号再恢复原有掩码并继续执行进程。

想更进一步了解关于信号,可查看 http://akaedu.github.io/book/ch33.html

❌