目录

4. 自动化构建-make/Makefile

4.1 背景

4.2 基本使用

4.2.1 依赖关系

4.2.2 依赖方法

4.2.3 make执行流程(如果依赖项不存在或更旧,则会先执行形成依赖项的依赖关系)

4.2.4 .PHONY声明伪目标、make执行条件

4.2.5 变量定义及其他指令

5. Linux第一个系统程序-进度条

5.1 回车与换行的区别

5.2 行缓冲区

5.3 倒计时程序

5.4 进度条代码实现

6. 版本控制器Git

6.1 版本控制器

6.2 git 简史

6.3 安装git

6.4 在git创建项目并下载到本地

6.5 三板斧(add添加、commit提交、push同步)

7. 调试器 -gdb/cgdb的使用

7.1 gdd/cgdb安装

7.2 示例代码

7.3 预备知识

7.4 常见cgdb/gdb的使用

7.5 调试技巧


4. 自动化构建-make/Makefile

4.1 背景

        • 会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力

        • 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作

        • makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。

        • make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。

        • make是一条命令,makefile(Makefile中的M大写也可以)是一个文件,两个搭配使用,完成项目自动化构建。

4.2 基本使用

        makefile文件的内容主要是依赖关系依赖方法命令。

        makefile中代码的缩进一定要使用Tab不能使用空格!!!

        实例代码

#include <stdio.h>int main()
{printf("hello Makefile!\n");return 0;
}
myproc:myproc.cgcc -o myproc myproc.c.PHONY:clean
clean:rm -f myproc

        依赖关系:上面的文件myproc,它依赖myproc.c

        依赖方法:gcc -o myproc myproc.c ,就是与之对应的依赖方法

        伪目标:.PHONY修饰的是伪目标

        clean指令:运行make clean,则执行伪目标clean的指令,rm -f myproc

4.2.1 依赖关系

        依赖关系的声明

target: prerequisites

        左边 (target):称为 目标 ;右边 (prerequisites):称为 先决条件(或依赖项)

        依赖关系决定依赖方法的源文件和目标文件。

        一个目标的声明到下一个目标声明之间,都是本目标要执行的依赖方法或者命令。

4.2.2 依赖方法

        根据依赖关系执行相应的指令。以下的每个依赖关系下面的gcc一行就是依赖方法。

        例如:

process:myprog.o dep1.o dep2.ogcc -o process myprog.o dep1.o dep2.omyprog.o:myprog.cgcc -c myprog.cdep1.o:dep1.cgcc -c dep1.cdep2.o:dep2.cgcc -c dep2.c.PHONY:clean
clean:rm -f *.o myprog

4.2.3 make执行流程(如果依赖项不存在或更旧,则会先执行形成依赖项的依赖关系)

        指令“make”只会执行第一个目标!!但是特殊情况会递归执行。如下:

        在 shell 输入 make 确实只执行了第一个目标 process。但是,为了完成“执行 process”这个任务,make 发现 process依赖于myprog.o、dep1.o 和 dep2.o,而这三个文件还不存在或需要更新。于是,make 自动地、递归地先去执行能生成这些依赖文件的目标规则。这就像是为了完成一个任务,你必须先完成它的所有子任务。(类似将每个依赖关系的gcc依赖方法入栈,然后依次出栈)

当您输入 make 时,make 会按照以下步骤执行:

        1. 找到默认目标:make 读取 Makefile,确定第一个目标是 process。

        2. 检查 process的依赖:它发现 process依赖于 myprog.o 、dep1.o和 dep2.o 这三个文件。

        3. 递归解决依赖(关键步骤):

                对于 myprog.o:make 检查是否存在 myprog.o 文件,以及它是否比它的依赖 myprog.c 更旧。由于 myprog.o 还不存在,make 发现有一条规则明确描述了如何构建它:myprog.o: myprog.c。于是,make 先跳转去执行那条规则的命令:gcc -c myprog.c。这样就生成了 myprog.o。

                对于 dep1.o:同样的过程发生。make 检查 dep1.o,发现它不存在,于是去执行 dep1.o: dep1.c 规则的命令:gcc -c dep1.c,生成了 dep1.o。

                对于dep2.o同理。

        4. 所有依赖就绪,执行最终目标:现在,myprog.o 、dep1.o和 dep2.o 都已经生成且是最新的。make 回到最初的目标 process,检查发现所有依赖都已就绪,于是执行它的命令:gcc -o process myprog.o dep1.o dep2.o

        5. 结束:最终目标 process 生成完成,make 退出。

# 终端执行make之后,打印make的指令流程,可见先执行生成myprog.o、dep1.o、dep2.o之后,再链接生成process
$ make
gcc -c myprog.c
gcc -c dep1.c
gcc -c dep2.c
gcc -o process myprog.o dep1.o dep2.o

4.2.4 .PHONY声明伪目标、make执行条件

1. make执行条件

        对于普通文件目标:目标文件相对于其依赖项是否过期决定是否执行

                目标文件不存在,执行。

                目标文件比它的任何一个依赖文件旧,执行。(取决于目标文件和依赖文件Modify时间的新旧)

                目标文件存在且比所有依赖文件新,跳过。

        对于伪目标 (用 .PHONY 声明):

                无条件执行。

2. 声明伪目标.PHONY:不进行检查,无条件执行命令

        伪目标是为了解决名字冲突问题而生的。假设你有一个名为 clean 的文件:

        如果没有 .PHONY 声明:当你运行 make clean 时,make 发现已经有一个叫 clean 的文件,而且这个文件没有任何依赖,因此它会被判定为“最新”,从而拒绝执行删除命令。这与你的意图完全相反。

        有了 .PHONY: clean 声明:你明确告诉 make:“clean 这个名字代表的不是一个文件,而是一个动作标签”。这样,无论文件系统中是否存在 clean 文件,make clean 命令都会坚决地执行清理动作。

# 也可以声明目标文件,则会无条件执行,不推荐
.PHONY:myprog
myprog:myprog.cgcc -o myprog myprog.c# 声明clean标签,无条件执行clean目标要执行的指令内容
.PHONY:clean
clean:rm -f *.o myprog

4.2.5 变量定义及其他指令

        在依赖关系或者命令行前加@,会让 Make 工具不显示该命令本身的打印信息(只执行命令,不输出命令内容)。

1. 变量定义

        makefile文件中的变量定义类似C语言中的define宏定义。但是变量的使用需要用$()进行解引用。

BIN=process
CC=gcc
SRC=myproc.c
FLAGS=-o
RM=rm -f$(BIN):$(SRC)$(CC) $(FLAGS) $@ $^.PHONY:clean
clean:$(RM) $(BIN)

2. 多文件变量定义

        代码功能:1.将目录下所有的.c文件编译成.o文件;2.将所有.o文件链接成可执行文件process。3.可以通过make clean删除.o和可执行文件。

        多文件变量定义格式见代码

BIN=process
CC=gcc# 可以使用shell指令给变量赋值
#SRC=$(shell ls *.c)    # 1.将当前目录下所有以 .c 结尾的源文件的文件名列表赋值给变量 SRC。
SRC=$(wildcard *.c)     # 功能同上
OBJ=$(SRC:.c=.o)        # 2.将SRC中文件名的后缀全部换成.o
LFLAGS=-o
FLAGS=-c
RM=rm -f$(BIN):$(OBJ)    # 将所有的.o文件链接成process$(CC) $(LFLAGS) $@ $^
%.o:%.c    #将所有的.c编译成对应的.o文件$(CC) $(FLAGS) $< -o $@.PHONY:clean
clean:$(RM) $(OBJ) $(BIN)

3. 多文件变量操作

自动变量含义特点典型场景
$@

指代当前规则中的目标文件名称(即 : 左侧的文件名)

1. 随目标变化而自动替换

2. 适用于任何目标(文件目标或伪目标)

编译或链接时指定输出文件名,例如:

a.o: a.c

    gcc -c a.c -o $@

等价于 gcc -c a.c -o a.o

$^指代当前目标的所有依赖文件

1. 包含所有依赖(不止一个)

2. 会自动去除重复的依赖项

链接阶段(需要所有目标文件),例如:

myprog: a.o b.o c.o

    gcc $^ -o $@

等价于 gcc a.o b.o c.o -o myprog

$<

指代当前目标的第一个依赖文件

1. 只取依赖列表中的第一个文件

2. 不会处理后续依赖

编译阶段(单个源文件生成目标文件),例如:

a.o: a.c head.h

    gcc -c $< -o $@

等价于 gcc -c a.c -o a.o(只使用第一个依赖 a.c)

%.c

模式通配符,表示所有以 .c 结尾的源文件(% 匹配任意字符串)

1. 匹配一类文件(而非单个文件)

2. 用于定义通用规则的依赖

定义通用编译规则的依赖,例如:
%.o: %.c
表示 “所有 .o 文件依赖于同名 .c 文件”
%.o

模式通配符,表示所有以 .o 结尾的目标文件

1. 匹配一类文件(而非单个文件)

2. 用于定义通用规则的目标

定义通用编译规则的目标,例如:

%.o: %.c

    gcc -c $< -o $@

表示 “所有 .o 文件都由对应 .c 文件编译生成”

5. Linux第一个系统程序-进度条

5.1 回车与换行的区别

        简单来说:

                回车 (Carriage Return, CR, \r):将光标移动到当前行的行首。

                换行 (Line Feed, LF, \n): 将光标移动到下一行的相同位置(垂直向下移动一行)。

        把它们想象成一台老式打字机:

                回车就是你用手把打字机的滚筒推回最左边的动作。

                换行就是你转动滚筒,把纸向上推一行的动作。

        要完成“新起一行”这个我们现代人认知中的操作,需要同时执行 回车 + 换行。

        注意:有时我们的\n会被转换成\r\n。

5.2 行缓冲区

        在Linux系统下运行对比以下两份代码:

        发现:有\n的代码先打印再睡眠,没\n的代码先睡眠再打印。

        实际程序都是按照顺序执行的,只是\n有刷新行缓冲区的功能,所以会先打印;而没有\n的代码不会刷新行缓冲区,所以就不会显示,而在程序运行结束以后也会刷新行缓冲区,所以右边的代码在程序运行结束后会打印“hello world!”

        在C标准库中有一个fflush函数(头文件是stdio.h),可以手动刷新缓冲区。对上图右边的代码添加fflush(stdout),刷新输出缓冲区,就会先打印hello world,再睡眠3秒。

#include <stdio.h>
#include <unistd>int main()
{printf("hello bite!");fflush(stdout);sleep(3);return 0;
}

5.3 倒计时程序

#include<stdio.h>
#include<unistd.h>int main()
{int i = 10;while(i >= 0){//限定宽度为2,"-"表示左对齐,\r表示回车,回到行的开头位置printf("%-2d\r",i); fflush(stdout);     //刷新行缓冲区--i;sleep(1);}printf("\n");return 0;
}

5.4 进度条代码实现

        注意事项:

        1. 即使进度条停止,但label仍在变化,说明仅仅可能是网络问题导致下载速度慢导致,而并不是下载停止了。

        【免费】Linux系统小程序-进度条实现资源-CSDN下载

6. 版本控制器Git

6.1 版本控制器

        为了能够更方便我们管理这些不同版本的文件,便有了版本控制器。所谓的版本控制器,就是能让你了解到一个文件的历史,以及它的发展过程的系统。通俗的讲就是一个可以记录工程的每一次改动和版本迭代的一个管理系统,同时也方便多人协同作业。

        目前最主流的版本控制器就是 Git 。Git 可以控制电脑上所有格式的文件,例如 doc、excel、dwg、dgn、rvt等等。对于我们开发人员来说,Git 最重要的就是可以帮助我们管理软件开发项目中的源代码文件

6.2 git 简史

        同生活中的许多伟大事物一样,Git 诞生于一个极富纷争大举创新的年代。

        Linux 内核开源项目有着为数众多的参与者。 绝大多数的 Linux 内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991-2002年间)。 到 2002 年,整个项目组开始启用一个专有的分布式版本控制系统 BitKeeper 来管理和维护代码。

        到了 2005 年,开发 BitKeeper 的商业公司同 Linux 内核开源社区的合作关系结束,他们收回了 Linux内核社区免费使用 BitKeeper 的权力。 这就迫使 Linux 开源社区(特别是 Linux 的缔造者 LinusTorvalds)基于使用 BitKeeper 时的经验教训,开发出自己的版本系统。 他们对新的系统制订了若干目标:速度、简单的设计、对非线性开发模式的强力支持(允许成千上万个并行开发的分支)、完全分布式、有能力高效管理类似 Linux 内核一样的超大规模项目(速度和数据量)。

        自诞生于 2005 年以来,Git 日臻成熟完善,在高度易用的同时,仍然保留着初期设定的目标。 它的速度飞快,极其适合管理大项目,有着令人难以置信的非线性分支管理系统。

6.3 安装git

# Centos
sudo yum install git# Ubuntu
sudo apt install -y git# 查看git版本
$ git --version
git version 1.8.3.1

6.4 在git创建项目并下载到本地

        1. 创建仓库

        2. 拉取远端仓库到本地

        a. 复制仓库的链接

        b. 拉取远端仓库到本地

        然后git就直接把你创建的仓库linux-system-programming拉取到了本地,本地就多出一个名为linux-system-programming的目录。

        查看此目录发现里面有以下几个文件:README.en和README分别是英文和中文的仓库说明;.gitignore用来设置需要忽略的文件类型;.git才是把远端仓库拉取到本地的本地仓库。

6.5 三板斧(add添加、commit提交、push同步)

         当前工作区是指:linux-system-programming目录

       1. git add

                将代码放到刚才下载好的目录中,然后add添加到.git本地仓库的暂存区。

git add [文件名]

        2. git commit

                提交改动到本地,提交的时候应该注明提交日志, 描述改动的详细内容。

git commit -m "XXX"

        3. git push

                同步到远端服务器上,需要填入用户名密码. 同步成功后, 刷新 gitee 页面就能看到代码改动了。

git push

        4. 补充指令

指令功能
git status查看本次git仓库的状态(即修改、新增、add、commit的状态)
git log查看git提交日志,显示每次提交的详细信息
git pull如果有人在其他设备往你的仓库push内容,等你下一次使用时需要pull拉取远端仓库的最新内容以进行同步。(远程仓库和任何人相比,都是最新的)

        5. 其他

                a. ".gitignore"需要忽略的特定后缀的文件列表。保证上传的都是源文件。

                b. 首次提交会让输入提交者的名称和邮箱,方便溯源。在git log中也可以看到。

7. 调试器 -gdb/cgdb的使用

7.1 gdd/cgdb安装

Ubuntu: sudo apt-get install -y gdb
Centos: sudo yum install -y gdbUbuntu: sudo apt-get install -y cgdb
Centos: sudo yum install -y cgdb

        cgdb和gdb的功能相同,相比于gdb的纯命令行,cgdb有分屏界面,上窗口:显示源代码(可滚动查看,类似代码编辑器)。下窗口:传统的 gdb 命令窗口(可输入 gdb 命令)。以cgdb为例学习。

7.2 示例代码

// mycode.c
#include <stdio.h>
int Sum(int s, int e)
{int result = 0;for (int i = s; i <= e; i++){result += i;}return result;
}int main()
{int start = 1;int end = 100;printf("I will begin\n");int n = Sum(start, end);printf("running done, result is: [%d-%d]=%d\n", start, end, n);return 0;
}

7.3 预备知识

        • 程序的发布方式有两种, debug 模式和release 模式, Linux gcc/g++ 出来的二进制程序,默认是release 模式。

        • 要使用gdb调试,必须在源代码生成二进制程序的时候, 加上-g 选项,如果没有添加,程序无法被编译

$ gcc mycmd.c -o mycmd # 默认模式,不支持调试
$ file mycmd
mycmd: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically
linked, interpreter /lib64/ld-linux-x86-64.so.2,
BuildID[sha1]=82f5cbaada10a9987d9f325384861a88d278b160, for GNU/Linux
3.2.0, not stripped$ gcc mycmd.c -o mycmd -g # debug模式
$ file mycmd
mycmd: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically
linked, interpreter /lib64/ld-linux-x86-64.so.2,
BuildID[sha1]=3d5a2317809ef86c7827e9199cfefa622e3c187f, for GNU/Linux
3.2.0, with debug_info, not stripped

7.4 常见cgdb/gdb的使用

        • 开始: gdb binFile

        • 退出: ctrl + d 或 quit 调试命令

命令作用样例
显示源代码
list/l n

显示源代码,从n位置开始,每次列出10行

list/l 1

list/l 函数名

列出指定函数的源代码

list/l main
list/l 文件名:行号/函数名列出指定文件的源代码

list/l mycode.c:1

调试运行
r/run

程序头开始连续执行

run

n/next

单步执行,不进入函数内部, 逐过程 F10next

s/step

单步执行,进入函数内部, 逐语句 F11step

finish

执行到当前函数返回,然后停止finish

continue/c

当前位置开始连续执行程序continue

until 行号

执行到指定行号until 20
设置断点,设置条件断点

break/b 行号

在指定行号设置断点break 10

break/b 函数名

在函数开头(入口处)设置断点break main

break/b [文件名]:行号/函数名

在指定行号设置断点

break mycode.c:10

b 行号 条件

添加条件断点b 9 if i == 30 # 9是行号,表示新增断点的位置

condition 断点号 条件

给已有断点添加条件condition 2 i==30 #给2号断点,新增条件i==30
删除断点

delete/d

breakpoints

删除所有断点

delete breakpoints

delete/d

breakpoints n

删除序号为n的断点

delete breakpoints 1
delete/d n

删除序号为n的断点

delete 1
启用/禁用断点

disable n

禁用序号为n的断点disable 4

disable breakpoints

禁用所有断点disable breakpoints

enable breakpoints

启用所有断点enable breakpoints
查看断点列表

info/i breakpoints

查看当前设置的断点列表info breakpoints

info/i break/b

查看当前所有断点的信息info b
查看变量值

print/p 表达式

打印表达式的值print start+end

p 变量

打印指定变量的值p x

display 变量名

跟踪显示指定变量的值(每次停止时)(监视)display x

undisplay 编号

取消对指定编号的变量的跟踪显示undisplay 1

info/i locals

查看当前栈帧的局部变量值info locals
watch 变量名

执行时监视一个表达式(如变量)的值。如果监视的表达式在程序运行期间的值发生变化,GDB 会暂停程序的执行,并通知使用者。(l类似变量断点)

watch x

set var 变量=值

修改变量的值set var i=10
查看函数栈帧

backtrace/bt

查看当前执行栈的各级函数调用及参数backtrace
退出调试

quit

退出GDB调试器quit

        gdb不退出,断点编号依次递增。

        gdb会自动记忆最新的一条指令,Enter执行gdb记忆的指令。

# 查看可执行文件(或目标文件)process 中包含的与调试相关的段(section)信息。
readelf -S process | grep -i debug

7.5 调试技巧

        1. 调试的本质:找到问题的代码。断点的本质:是把代码进行块级别划分,以块为单位进行快速定位区域。finish:确定问题是否在函数内。until:局部区域快速执行。

        2. watch的使用:如果有一些变量不应该修改,但是你怀疑他修改导致了问题,你可以watch他,如果变化了,就会通知你。

        3. set var确定问题的原因,并进行临时修改。

        4. 条件断点方便在循环中查找问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/97948.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/97948.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/97948.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Django RBAC权限实战全流程

基于 Django 内置权限体系&#xff08;RBAC&#xff09; 的简单实战案例。 我会从 建模、创建用户、角色和权限、分配权限、接口校验 全流程讲解&#xff0c;既简单又全面。1️⃣ 项目和应用初始化 pip install django djangorestframework django-admin startproject myproje…

科学研究系统性思维的理论基础:数字化研究工具

一、核心概念深度解析 1.1 数字化研究的本质转变 数字化工具不仅是技术升级&#xff0c;更是科研范式的哲学重构。这种转变在认识论层面体现为三个关键突破&#xff1a; 时空界限的崩塌 传统研究受物理空间和实时性限制&#xff0c;而Google Colab等平台实现了全球724小时协作。…

C# COM口串口调试助手实现

一、核心功能模块设计 基础通信功能 波特率自适应&#xff08;支持9600-115200bps&#xff09;数据格式配置&#xff08;8N1/7E2等&#xff09;流控支持&#xff08;RTS/CTS硬件流控&#xff09;接收/发送缓冲区管理&#xff08;4KB2双缓冲&#xff09; 数据处理功能 HEX/ASCII…

模块内聚类型有哪些

考题: 内聚类型是衡量模块内部各元素之间联系紧密程度的概念。其中,要求处理元素相关且按特定次序执行,属于(__)。 A 时间内聚 B 顺序内聚 C 过程内聚 D 逻辑内聚 一、什么是模块内聚 模块内聚反映的是模块内部各组成部分之间的功能关联程度,内聚越高,模块的独立性越好…

Selenium基础操作

Selenium 基础操作 作为一名资深爬虫工程师&#xff0c;我将带您全面掌握Selenium自动化测试与网页爬取技术。 本教程基于Python 3.12&#xff0c;使用uv进行依赖管理&#xff0c;并通过FastAPI搭建模拟网站供实战练习。 第一章&#xff1a;环境搭建 1.1 安装Python 3.12 …

Gateway-路由-规则配置

1.路由 路由是指网络设备&#xff08;如路由器、交换机、或软件&#xff09;根据一张路径表&#xff08;路由表&#xff09;&#xff0c;为数据包选择一条从源地址到目标地址的传输路径的过程。它就像快递配送系统&#xff0c;查看地址并决策下一步往哪里送”&#xff0c;该过…

BP神经网络多输入多输出回归预测+SHAP可解释分析+新数据预测(MATLAB完整源码)

该MATLAB代码实现了一个基于前馈神经网络的回归预测模型,并结合SHAP(Shapley Additive exPlanations)值分析进行特征重要性评估。

【51单片机单按键控制2个LED循环闪烁】2022-12-7

缘由--CSDN问答 #include "reg52.h" sbit LED1P1^0; sbit LED2P1^5; sbit anjnP3^2; void main() {unsigned char H0,L0,Ys0;LED1LED20;while(1){if(anjn0&&Ys0){if(L>3)L0;while(anjn0);}if(L0)LED1LED20;//0表示亮1表示熄else if(L1){LED11;LED20;}else…

RustFS企业级高可用部署全指南:多活架构与跨数据中心实战

作为一名深耕分布式存储多年的架构师&#xff0c;我在金融、AI和物联网领域多次成功落地RustFS高可用集群。本文将分享如何构建99.95%可用性的RustFS企业级部署方案&#xff0c;涵盖从单数据中心到多活架构的全场景实践。 一、高可用架构设计核心 RustFS的高可用性建立在分布式…

leetcode算法题记录:

14、最长公共前缀编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀&#xff0c;返回空字符串 ""。示例 1&#xff1a;输入&#xff1a;strs ["flower","flow","flight"] 输出&#xff1a;"fl"示例 2&…

HarmonyOS 应用开发深入浅出:基于 Stage 模型与 ArkUI 的声明式开发实践

好的&#xff0c;请看这篇关于 HarmonyOS 应用开发中 Stage 模型与 ArkUI 声明式开发实践的技术文章。 HarmonyOS 应用开发深入浅出&#xff1a;基于 Stage 模型与 ArkUI 的声明式开发实践 引言 随着 HarmonyOS 的不断发展&#xff0c;其应用开发范式也经历了重大的演进。从…

web服务解析案例

题目 模拟一个基于 DNS&#xff08;域名系统&#xff09;和 Nginx 的 Web 服务架构。 整体是模拟从用户输入域名&#xff0c;经 DNS 解析找到 Web 服务器&#xff0c;再由 Web 服务器&#xff08;Nginx&#xff09;提供内容的完整 Web 服务流程。 主机规划主机名ip地址软件说明…

揭示电解液与界面奥秘,理论计算赋能水系电池创新

揭示电解液与界面奥秘&#xff0c;理论计算赋能水系电池创新随着全球对高安全、低成本储能需求的激增&#xff0c;水系电池成为了下一代电池技术的重要候选者。然而&#xff0c;其性能瓶颈&#xff0c;如循环寿命、能量密度等&#xff0c;深深根植于复杂的电解液化学和电极-电解…

xv6实验:Ubuntu2004 WSL2实验环境配置(包括git clone网络问题解决方法)

基本配置参考MIT6.S081 Ubuntu22.04 WSL2实验环境配置,wsl安装配置参考本栏的另一篇文章WSL2&#xff08;ubuntu20.04&#xff09;vscode联合开发(附迁移方法) 如执行: git clone git://github.com/mit-pdos/xv6-riscv.git出现错误,或者无法clone情况,可以挂一个代理,然后按如…

reversed()方法

在 Python 中&#xff0c;reversed() 是一个内置函数&#xff0c;用于返回一个反向迭代器对象。这个函数可以处理多种序列类型的数据&#xff0c;如列表、元组、字符串、范围对象等&#xff0c;通过它可以方便地实现序列元素的反向遍历。下面从基本语法、适用对象、使用示例等方…

根据文本区域`textarea`的内容调整大小`field-sizing:content`

field-sizing:content 新属性&#xff0c;可以让 文本域textarea 根据输入的内容自动调整大小&#xff0c; 无需使用javascript See the Pen 根据文本区域textarea的内容调整大小field-sizing:content by liu874396180 ( liu874396180) on CodePen.

Python3练习题

上一节中全面讲解了基础知识&#xff0c;为了巩固知识点&#xff0c;当然最好的方法就是练习了。 练习 1&#xff1a;变量类型转换与算术运算 需求&#xff1a;接收用户输入的两个数字&#xff08;可能是整数或字符串格式&#xff09;&#xff0c;转换为浮点数后计算 “幂运算、…

Motioncam Color S + 蓝激光:3D 视觉革新,重塑工业与科研应用新格局

在工业自动化、科研探索及智能检测等前沿领域&#xff0c;对物体进行高精度、高速度且稳定可靠的三维成像&#xff0c;始终是推动技术进步与效率提升的关键诉求。过往的 3D 成像设备&#xff0c;常因精度欠佳、对复杂材质适应性差、难以应对动态场景等局限&#xff0c;在实际应…

用html5写一个第一视角的摩托车开车游戏,画上摩托车把手,把手两侧放上可操控方向的按钮,再加上,前进和减速的按钮

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>第一视角摩托车</title><style>html…

SpringMVC 系列博客(一):基础概念与注解开发入门

目录 一、引言 二、MVC 模式&#xff1a;SpringMVC 的设计基石 2.1 MVC 三大组件 2.2 主流 MVC 框架对比 2.3 MVC 模式的核心优势 三、SpringMVC 框架&#xff1a;是什么&#xff1f;为什么学&#xff1f; 3.1 什么是 SpringMVC&#xff1f; 3.2 为什么要学 SpringMVC&a…