12、管理 Docker 容器的网络栈

管理 Docker 容器的网络栈

容器网络基础

Docker 容器之间可以相互 ping 通,并且能够访问外部网络。为了实现外部访问,容器的端口会被映射到主机端口。容器使用网络命名空间,当创建第一个容器时,会为其创建一个新的网络命名空间。

在容器和 Linux 桥之间会创建一个虚拟以太网(vEthernet 或 vEth)链接。从容器的 eth0 端口发送的流量通过 vEth 接口到达桥接器,然后进行交换。可以使用以下命令查看 Linux 桥:

$ sudo brctl show

该命令的输出类似于以下内容,显示桥接器名称以及映射到的容器上的 vEth 接口:

$ bridge name  bridge            id    STP       enabled interfaces
docker0        8000.56847afe9799 no    veth44cb727    veth98c3700
连接容器到外部世界

主机上的 iptables NAT 表用于伪装所有外部连接,示例如下:

$ sudo iptables -t nat -L -n
...
Chain POSTROUTING (policy ACCEPT) target prot opt
source destination MASQUERADE all -- 172.17.0.0/16
!172.17.0.0/16
...
从外部世界访问容器

端口映射同样使用主机上的 iptables NAT 选项完成。

Docker 桥接器

默认情况下,Docker 服务器会在 Linux 内核中创建一个 docker0 桥接器,它可以在其他物理或虚拟网络接口之间来回传递数据包,使它们表现得像一个单一的以太网网络。可以使用以下命令查看:

root@ubuntu:~# ifconfig
docker0   Link encap:Ethernet  HWaddr 56:84:7a:fe:97:99
          inet addr:172.17.42.1  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::5484:7aff:fefe:9799/64 Scope:Link
          inet6 addr: fe80::1/64 Scope:Link
          ...
          collisions:0 txqueuelen:0
          RX bytes:516868 (516.8 KB)  TX bytes:46460483 (46.4 MB)
eth0      Link encap:Ethernet  HWaddr 00:0c:29:0d:f4:2c
          inet addr:192.168.186.129  Bcast:192.168.186.255
Mask:255.255.255.0

当有一个或多个容器运行时,可以通过在主机上运行 brctl 命令并查看输出的接口列来确认 Docker 是否已将它们正确连接到 docker0 桥接器。首先,使用以下命令安装桥接工具:

$ apt-get install bridge-utils

以下是一个连接了两个不同容器的主机示例:

root@ubuntu:~# brctl show
bridge name     bridge id           STP enabled   interfaces
docker0         8000.56847afe9799   no            veth21b2e16
                                                  veth7092a45

Docker 在创建容器时会使用 docker0 桥接器设置,并为新容器分配一个来自桥接器可用范围的新 IP 地址。例如:

root@ubuntu:~# docker run -t -i --name container1 ubuntu:latest
/bin/bash
root@e54e9312dc04:/# ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:ac:11:00:07
inet addr:172.17.0.7 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: 2001:db8:1::242:ac11:7/64 Scope:Global
inet6 addr: fe80::42:acff:fe11:7/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
...
root@e54e9312dc04:/# ip route
default via 172.17.42.1 dev eth0
172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.7

默认情况下,Docker 提供一个 vnet docker0,其 IP 地址为 172.17.42.1,Docker 容器的 IP 地址范围是 172.17.0.0/16。

修改默认设置

要更改 Docker 的默认设置,可以修改 /etc/default/docker 文件。例如,将默认桥接器从 docker0 更改为 br0 的步骤如下:
1. 停止 Docker 服务:

# sudo service docker stop
  1. 关闭 docker0 接口:
# sudo ip link set dev docker0 down
  1. 删除 docker0 桥接器:
# sudo brctl delbr docker0
  1. 清空 iptables NAT 表的 POSTROUTING 链:
# sudo iptables -t nat -F POSTROUTING
  1. /etc/default/docker 文件中添加新的桥接器设置:
# echo 'DOCKER_OPTS="-b=br0"' >> /etc/default/docker
  1. 创建 br0 桥接器:
# sudo brctl addbr br0
  1. 为 br0 桥接器分配 IP 地址:
# sudo ip addr add 192.168.10.1/24 dev br0
  1. 启动 br0 桥接器:
# sudo ip link set dev br0 up
  1. 启动 Docker 服务:
# sudo service docker start

使用以下命令可以显示新的桥接器名称和 Docker 服务的 IP 地址范围:

root@ubuntu:~# ifconfig
br0       Link encap:Ethernet  HWaddr ae:b2:dc:ed:e6:af
          inet addr:192.168.10.1  Bcast:0.0.0.0  Mask:255.255.255.0
          inet6 addr: fe80::acb2:dcff:feed:e6af/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:7 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:738 (738.0 B)
eth0      Link encap:Ethernet  HWaddr 00:0c:29:0d:f4:2c
          inet addr:192.168.186.129  Bcast:192.168.186.255
Mask:255.255.255.0
          inet6 addr: fe80::20c:29ff:fe0d:f42c/64 Scope:Link
                         ...
DNS 配置

Docker 可以为每个容器提供主机名和 DNS 配置,而无需构建自定义镜像。它通过将容器内的 /etc 文件覆盖为虚拟文件来写入新信息。可以在容器内运行 mount 命令查看。容器在创建时会接收与主机相同的 /resolv.conf 文件,如果主机的 /resolv.conf 文件被修改,只有在容器重启时才会反映在容器的 /resolv.conf 文件中。

在 Docker 中,可以通过以下两种方式设置 DNS 选项:
- 使用 docker run --dns=<ip-address>
- 在 Docker 守护进程文件中添加 DOCKER_OPTS="--dns ip-address"

还可以使用 --dns-search=<DOMAIN> 指定搜索域。

主要的 DNS 文件包括:
- /etc/hostname
- /etc/resolv.conf
- /etc/hosts

添加 DNS 服务器的命令示例:

# docker run --dns=8.8.8.8 --net="bridge" -t -i  ubuntu:latest
/bin/bash

添加主机名的命令示例:

#docker run --dns=8.8.8.8 --hostname=docker-vm1  -t -i  ubuntu:latest
/bin/bash
容器与外部网络通信故障排除

只有当 ip_forward 参数设置为 1 时,数据包才能在容器之间传递。通常,可以将 Docker 服务器保持在默认设置 --ip-forward=true ,Docker 会在服务器启动时将 ip_forward 设置为 1。可以使用以下命令检查设置:

# cat /proc/sys/net/ipv4/ip_forward
0
# echo 1 > /proc/sys/net/ipv4/ip_forward
# cat /proc/sys/net/ipv4/ip_forward
1

启用 ip-forward 后,容器与外部世界之间的通信将成为可能,在多桥接器设置中,它也是容器间通信所必需的。

Docker 不会删除或修改 Docker 过滤链中任何预先存在的规则,这允许用户创建规则来限制对容器的访问。Docker 使用 docker0 桥接器在单个主机上的所有容器之间进行数据包流动,并在 iptables 的 FORWARD 链中添加一条规则(空白接受策略)以允许两个容器之间的数据包流动。 --icc=false 选项将丢弃所有数据包。

当 Docker 守护进程配置为 --icc=false --iptables=true 并且使用 --link= 选项运行 docker run 时,Docker 服务器将为新容器插入一对 iptables ACCEPT 规则,以便它可以连接到其他容器暴露的端口。

默认情况下,Docker 的转发规则允许所有外部 IP 访问。要仅允许特定 IP 或网络访问容器,可以在 Docker 过滤链的顶部插入一个否定规则。例如,使用以下命令限制外部访问,仅允许源 IP 10.10.10.10 访问容器:

#iptables -I DOCKER -i ext_if ! -s 10.10.10.10 -j DROP
限制容器之间的 SSH 访问

限制一个容器到另一个容器的 SSH 访问的步骤如下:
1. 创建两个容器 c1 和 c2:

# docker run -i -t --name c1 ubuntu:latest /bin/bash
root@7bc2b6cb1025:/# ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:ac:11:00:05
 inet addr:172.17.0.5 Bcast:0.0.0.0 Mask:255.255.0.0
 inet6 addr: 2001:db8:1::242:ac11:5/64 Scope:Global
 inet6 addr: fe80::42:acff:fe11:5/64 Scope:Link
 ...
# docker run -i -t --name c2 ubuntu:latest /bin/bash
root@e58a9bf7120b:/# ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:ac:11:00:06
 inet addr:172.17.0.6 Bcast:0.0.0.0 Mask:255.255.0.0
 inet6 addr: 2001:db8:1::242:ac11:6/64 Scope:Global
 inet6 addr: fe80::42:acff:fe11:6/64 Scope:Link
  1. 使用 ping 工具测试容器之间的连通性:
root@7bc2b6cb1025:/# ping 172.17.0.6
PING 172.17.0.6 (172.17.0.6) 56(84) bytes of data.
64 bytes from 172.17.0.6: icmp_seq=1 ttl=64 time=0.139 ms
64 bytes from 172.17.0.6: icmp_seq=2 ttl=64 time=0.110 ms
^C
--- 172.17.0.6 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.110/0.124/0.139/0.018 ms
root@7bc2b6cb1025:/#
root@e58a9bf7120b:/# ping 172.17.0.5
PING 172.17.0.5 (172.17.0.5) 56(84) bytes of data.
64 bytes from 172.17.0.5: icmp_seq=1 ttl=64 time=0.270 ms
64 bytes from 172.17.0.5: icmp_seq=2 ttl=64 time=0.107 ms
^C
--- 172.17.0.5 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 0.107/0.188/0.270/0.082 ms
root@e58a9bf7120b:/#
  1. 在两个容器上安装 openssh-server:
#apt-get install openssh-server
  1. 在主机上启用 iptables。
  2. 停止 Docker 服务,并在主机的默认 docker 文件中添加 DOCKER_OPTS="--icc=false --iptables=true"
root@ubuntu:~# iptables -L -n
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
DOCKER all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
#service docker stop
#vi /etc/default/docker
  1. 重启 Docker 服务:
# service docker start
  1. 检查 iptables:
root@ubuntu:~# iptables -L -n
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED, ESTABLISHED
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
DOCKER all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED, ESTABLISHED
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
DROP all -- 0.0.0.0/0 0.0.0.0/0

此时,主机的 iptables 中添加了 DROP 规则,容器之间的连接将被丢弃,无法进行 SSH 连接。

容器链接

可以使用 --link 参数来实现旧版容器之间的通信或连接。步骤如下:
1. 创建第一个容器作为服务器(sshserver):

root@ubuntu:~# docker run -i -t -p 2222:22 --name sshserver ubuntu
bash
root@9770be5acbab:/#
#root@ubuntu:~# iptables -L -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
Chain DOCKER (0 references)
target     prot opt source               destination
ACCEPT     tcp  --  0.0.0.0/0            172.17.0.3           tcp
dpt:22
  1. 创建第二个容器作为 SSH 客户端:
root@ubuntu:~# docker run -i -t --name sshclient --link
sshserver:sshserver
ubuntu bash
root@979d46c5c6a5:/#
  1. 检查 iptables 规则:
root@ubuntu:~# iptables -L -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
Chain DOCKER (0 references)
target     prot opt source               destination
ACCEPT     tcp  --  0.0.0.0/0            172.17.0.3           tcp
dpt:22
ACCEPT     tcp  --  172.17.0.4           172.17.0.3           tcp
dpt:22
ACCEPT     tcp  --  172.17.0.3           172.17.0.4           tcp
spt:22
root@ubuntu:~#
  1. 使用 docker inspect 检查链接的容器:
root@ubuntu:~# docker inspect -f "{{ .HostConfig.Links }}"
sshclient
[/sshserver:/sshclient/sshserver]
  1. 使用 IP 地址成功 SSH 进入 SSH 服务器:
#ssh root@172.17.0.3 -p 22

使用 --link 参数,Docker 会在容器之间创建一个安全通道,无需在容器外部暴露任何端口。

libnetwork 和容器网络模型

libnetwork 是用 Go 语言实现的,用于连接 Docker 容器。其目标是提供一个容器网络模型(CNM),帮助程序员提供网络库的抽象。libnetwork 的长期目标是遵循 Docker 和 Linux 的哲学,提供独立工作的模块,满足容器网络的可组合需求,并将 Docker 引擎和 libcontainer 中的网络逻辑模块化到一个单一的、可重用的库中,具体做法包括:
- 用 libnetwork 替换 Docker 引擎的网络模块。
- 允许本地和远程驱动为容器提供网络。
- 提供一个 dnet 工具来管理和测试 libnetwork(目前仍在开发中)。

libnetwork 实现了 CNM,它规范了为容器提供网络所需的步骤,同时提供了一个可用于支持多个网络驱动的抽象。其端点 API 主要用于管理相应的对象并进行记录,以提供 CNM 所需的抽象级别。

CNM 对象

CNM 基于三个主要组件构建:
1. Sandbox
- 包含容器网络栈的配置,包括路由表管理、容器接口和 DNS 设置。
- 可以是 Linux 网络命名空间、FreeBSD 监狱或其他类似概念。
- 可能包含来自多个网络的多个端点,代表容器的网络配置,如 IP 地址、MAC 地址和 DNS 条目。
- libnetwork 使用特定于操作系统的参数来填充由沙箱表示的网络配置,并提供一个框架,以便在多个操作系统中实现沙箱。
- 目前有两个沙箱实现( namespace_linux.go configure_linux.go )用于唯一标识主机文件系统上的路径,一个沙箱与单个 Docker 容器关联。
- 沙箱的运行时元素由以下数据结构表示:

type sandbox struct {
      id            string
       containerID   string
      config        containerConfig
      osSbox        osl.Sandbox
      controller    *controller
      refCnt        int
      endpoints     epHeap
      epPriority    map[string]int
      joinLeaveDone chan struct{}
      dbIndex       uint64
      dbExists      bool
      isStub        bool
      inDelete      bool
      sync.Mutex
}
  • 新的沙箱从网络控制器实例化:
func (c *controller) NewSandbox(containerID string, options
...SandboxOption)
 (Sandbox, error) {
    .....
}
  1. Endpoint
    - 将沙箱连接到网络,并为容器暴露的服务提供与同一网络中部署的其他容器的连接性。
    - 可以是 Open vSwitch 的内部端口或类似的 vEth 对。
    - 只能属于一个网络和一个沙箱,代表一个服务,并提供各种 API 来创建和管理端点。
    - 具有全局范围,但仅附加到一个网络。
    - 端点由以下结构体指定:
type endpoint struct {
   name          string
   id            string
   network       *network
   iface         *endpointInterface
   joinInfo      *endpointJoinInfo
   sandboxID     string
   exposedPorts  []types.TransportPort
   anonymous     bool
   generic      map[string]interface{}
   joinLeaveDone chan struct{}
   prefAddress   net.IP
   prefAddressV6 net.IP
   ipamOptions   map[string]string
   dbIndex       uint64
   dbExists      bool
   sync.Mutex
}
  • 端点与唯一的 ID 和名称关联,附加到网络和沙箱 ID,还与 IPv4 和 IPv6 地址空间关联,每个端点与一个端点接口关联。
    3. Network
  • 一组能够直接相互通信的端点称为网络。
  • 提供同一主机或多个主机内所需的连接性,每当创建或更新网络时,会通知相应的驱动。
  • 例如 VLAN 或 Linux 桥接器,在集群内具有全局范围。
  • 网络由网络控制器控制,每个网络都有名称、地址空间、ID 和网络类型:
type network struct {
   ctrlr        *controller
   name         string
   networkType  string
   id           string
   ipamType     string
   addrSpace    string
   ipamV4Config []*IpamConf
   ipamV6Config []*IpamConf
   ipamV4Info   []*IpamInfo
   ipamV6Info   []*IpamInfo
   enableIPv6   bool
   postIPv6     bool
   epCnt        *endpointCnt
   generic      options.Generic
   dbIndex      uint64
   svcRecords   svcMap
   dbExists     bool
   persist      bool
   stopWatchCh  chan struct{}
   drvOnce      *sync.Once
   internal     bool
   sync.Mutex
}
  1. Network controller
    - 网络控制器对象提供创建和管理网络对象的 API。
    - 是 libnetwork 的入口点,通过将特定驱动绑定到给定网络来工作,支持多个活动驱动(包括内置和远程驱动)。
    - 允许用户将特定驱动绑定到给定网络,其结构体如下:
type controller struct {
   id             string
   drivers        driverTable
   ipamDrivers    ipamTable
   sandboxes      sandboxTable
   cfg            *config.Config
   stores         []datastore.DataStore
   discovery     hostdiscovery.HostDiscovery
   extKeyListener net.Listener
   watchCh        chan *endpoint
   unWatchCh      chan *endpoint
   svcDb          map[string]svcMap
   nmap           map[string]*netWatch
   defOsSbox      osl.Sandbox
   sboxOnce       sync.Once
   sync.Mutex
}

综上所述,通过对 Docker 容器网络栈的管理、配置和故障排除,以及对 libnetwork 和 CNM 的了解,可以更好地实现容器之间的通信和网络连接,满足不同场景下的需求。

管理 Docker 容器的网络栈(续)

容器网络管理的关键要点总结

为了更清晰地理解容器网络管理的各个方面,下面通过表格形式对前面提到的关键操作和配置进行总结:
| 操作类型 | 具体操作 | 命令示例 |
| — | — | — |
| 查看 Linux 桥 | 显示桥接器信息 | sudo brctl show |
| 连接容器到外部世界 | 查看 iptables NAT 表 | sudo iptables -t nat -L -n |
| 修改默认桥接器 | 一系列步骤将默认桥接器从 docker0 改为 br0 | 1. sudo service docker stop
2. sudo ip link set dev docker0 down
3. sudo brctl delbr docker0
4. sudo iptables -t nat -F POSTROUTING
5. echo 'DOCKER_OPTS="-b=br0"' >> /etc/default/docker
6. sudo brctl addbr br0
7. sudo ip addr add 192.168.10.1/24 dev br0
8. sudo ip link set dev br0 up
9. sudo service docker start |
| DNS 配置 | 添加 DNS 服务器 | docker run --dns=8.8.8.8 --net="bridge" -t -i ubuntu:latest /bin/bash |
| 故障排除 | 检查和设置 ip_forward 参数 | 1. cat /proc/sys/net/ipv4/ip_forward
2. echo 1 > /proc/sys/net/ipv4/ip_forward
3. cat /proc/sys/net/ipv4/ip_forward |
| 限制 SSH 访问 | 一系列步骤限制容器间 SSH 访问 | 1. 创建容器 c1 和 c2
2. 测试连通性(ping)
3. 安装 openssh-server
4. 启用 iptables
5. 停止 Docker 服务并修改配置文件
6. 重启 Docker 服务
7. 检查 iptables |
| 容器链接 | 创建服务器和客户端容器并链接 | 1. docker run -i -t -p 2222:22 --name sshserver ubuntu bash
2. docker run -i -t --name sshclient --link sshserver:sshserver ubuntu bash |

容器网络管理的流程图

下面通过 mermaid 流程图展示容器网络的基本管理流程:

graph LR
    classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
    classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px

    A([开始]):::startend --> B(创建容器):::process
    B --> C{检查网络配置}:::decision
    C -->|需要修改| D(修改默认设置):::process
    C -->|不需要修改| E(配置 DNS):::process
    D --> E
    E --> F{测试连通性}:::decision
    F -->|失败| G(故障排除):::process
    F -->|成功| H(进行其他操作):::process
    G --> F
    H --> I([结束]):::startend
深入理解 CNM 组件之间的关系

前面介绍了 CNM 的三个主要组件(Sandbox、Endpoint、Network)和 Network controller,下面通过流程图进一步展示它们之间的关系:

graph LR
    classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px

    A(Network controller):::process --> B(Network):::process
    B --> C(Endpoint):::process
    C --> D(Sandbox):::process
    D --> E(Docker 容器):::process
    B -.-> E(提供网络连接)
    C -.-> E(提供服务连接)

从这个流程图可以看出,Network controller 负责管理 Network,Network 包含多个 Endpoint,Endpoint 连接到 Sandbox,而 Sandbox 与 Docker 容器关联。整个过程中,Network 为容器提供网络连接,Endpoint 为容器提供服务连接。

未来容器网络管理的发展趋势

虽然 libnetwork 已经在容器网络管理方面提供了很多便利,但未来容器网络管理仍有一些发展趋势值得关注:
1. 多网络驱动支持的增强 :随着云计算和容器技术的不断发展,可能会出现更多类型的网络驱动。libnetwork 有望进一步增强对多种网络驱动的支持,以满足不同用户的需求。
2. 更智能的网络配置 :未来可能会出现更智能的网络配置工具,能够根据容器的类型、用途和资源需求自动进行网络配置,减少人工干预。
3. 安全性的进一步提升 :容器网络的安全性始终是一个重要问题。未来可能会在 CNM 中集成更多的安全机制,如加密通信、访问控制等,以保护容器网络免受攻击。

总结

容器网络管理是 Docker 应用中的一个重要方面,涉及到网络配置、故障排除、容器链接等多个环节。通过对 Docker 容器网络栈的深入理解,以及对 libnetwork 和 CNM 的运用,可以更好地实现容器之间的通信和网络连接。同时,随着技术的不断发展,未来容器网络管理将朝着更智能、更安全的方向发展。希望本文能够帮助读者更好地掌握容器网络管理的相关知识和技能,在实际应用中更加得心应手。

已经博主授权,源码转载自 https://pan.quark.cn/s/053f1da40351 在计算机科学领域,MIPS(Microprocessor without Interlocked Pipeline Stages)被视作一种精简指令集计算机(RISC)的架构,其应用广泛存在于教学实践和嵌入式系统设计中。 本篇内容将深入阐释MIPS汇编语言中涉及数组处理的核心概念与实用操作技巧。 数组作为一种常见的数据结构,在编程中能够以有序化的形式储存及访问具有相同类型的数据元素集合。 在MIPS汇编语言环境下,数组通常借助内存地址与索引进行操作。 以下列举了运用MIPS汇编处理数组的关键要素:1. **数据存储**: - MIPS汇编架构采用32位地址系统,从而能够访问高达4GB的内存容量。 - 数组元素一般以连续方式存放在内存之中,且每个元素占据固定大小的字节空间。 例如,针对32位的整型数组,其每个元素将占用4字节的存储空间。 - 数组首元素的地址被称为基地址,而数组任一元素的地址可通过基地址加上元素索引乘以元素尺寸的方式计算得出。 2. **寄存器运用**: - MIPS汇编系统配备了32个通用寄存器,包括$zero, $t0, $s0等。 其中,$zero寄存器通常用于表示恒定的零值,$t0-$t9寄存器用于暂存临时数据,而$s0-$s7寄存器则用于保存子程序的静态变量或参数。 - 在数组处理过程中,基地址常被保存在$s0或$s1寄存器内,索引则存储在$t0或$t1寄存器中,运算结果通常保存在$v0或$v1寄存器。 3. **数组操作指令**: - **Load/Store指令**:这些指令用于在内存与寄存器之间进行数据传输,例如`lw`指令用于加载32位数据至寄存器,`sw`指令...
根据原作 https://pan.quark.cn/s/cb681ec34bd2 的源码改编 基于Python编程语言完成的飞机大战项目,作为一项期末学习任务,主要呈现了游戏开发的基本概念和技术方法。 该项目整体构成约500行代码,涵盖了游戏的核心运作机制、图形用户界面以及用户互动等关键构成部分。 该项目配套提供了完整的源代码文件、相关技术文档、项目介绍演示文稿以及运行效果展示视频,为学习者构建了一个实用的参考范例,有助于加深对Python在游戏开发领域实际应用的认识。 我们进一步研究Python编程技术在游戏开发中的具体运用。 Python作为一门高级编程语言,因其语法结构清晰易懂和拥有丰富的库函数支持,在开发者群体中获得了广泛的认可和使用。 在游戏开发过程中,Python经常与Pygame库协同工作,Pygame是Python语言下的一款开源工具包,它提供了构建2D游戏所需的基础功能模块,包括窗口系统管理、事件响应机制、图形渲染处理、音频播放控制等。 在"飞机大战"这一具体游戏实例中,开发者可能运用了以下核心知识点:1. **Pygame基础操作**:掌握如何初始化Pygame环境,设定窗口显示尺寸,加载图像和音频资源,以及如何启动和结束游戏的主循环流程。 2. **面向对象编程**:游戏中的飞机、子弹、敌人等游戏元素通常通过类的设计来实现,利用实例化机制来生成具体的游戏对象。 每个类都定义了自身的属性(例如位置坐标、移动速度、生命值状态)和方法(比如移动行为、碰撞响应、状态更新)。 3. **事件响应机制**:Pygame能够捕获键盘输入和鼠标操作事件,使得玩家可以通过按键指令来控制飞机的移动和射击行为。 游戏会根据这些事件的发生来实时更新游戏场景状态。 4. **图形显示与刷新**:...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值