JAVA EE初阶 - 预备知识(一)

一、管道

在计算机编程和操作系统环境中,输入、输出和错误管道是用于在不同进程或程序之间传递数据和信息的重要机制,下面分别对它们进行详细介绍:

输入管道(Standard Input,stdin)

  • 定义:输入管道是进程获取外部数据的通道。它允许一个进程从其他进程、用户输入设备(如键盘)或文件中接收数据。当一个进程启动时,操作系统通常会为其分配一个标准输入流,进程可以通过读取这个输入流来获取所需的数据。
  • 工作原理:在命令行环境中,用户可以通过键盘输入数据,这些数据会被发送到当前正在运行的程序的标准输入管道中。程序可以使用相应的函数或方法来读取输入管道中的数据。例如,在 Python 中,可以使用 input() 函数从标准输入读取用户输入的一行文本;在 Java 中,可以使用 Scanner 类来读取标准输入。
  • 示例(Python)
# 从标准输入读取用户输入
user_input = input("请输入一些内容: ")
print(f"你输入的内容是: {user_input}")

  • 管道连接示例:在 Unix/Linux 系统中,可以使用管道符号 | 来连接多个命令,将前一个命令的输出作为后一个命令的输入。例如,ls -l | grep .txt 命令将 ls -l 命令的输出通过管道传递给 grep .txt 命令,grep 命令从其输入管道中读取数据并进行筛选。

输出管道(Standard Output,stdout)

  • 定义:输出管道是进程向外部发送数据的通道。进程可以将计算结果、提示信息等数据通过输出管道发送到其他进程、文件或显示设备(如显示器)。当一个进程启动时,操作系统会为其分配一个标准输出流,进程可以将数据写入这个输出流。
  • 工作原理:程序可以使用相应的函数或方法将数据写入输出管道。在 Python 中,可以使用 print() 函数将数据输出到标准输出;在 Java 中,可以使用 System.out.println() 方法。
  • 示例(Java)
public class OutputExample {public static void main(String[] args) {// 向标准输出打印信息System.out.println("这是一个输出示例");}
}

  • 重定向示例:在命令行中,可以使用重定向符号 > 将命令的输出重定向到文件中。例如,ls -l > file_list.txt 命令将 ls -l 命令的输出重定向到 file_list.txt 文件中,而不是显示在屏幕上。

错误管道(Standard Error,stderr)

  • 定义:错误管道用于进程输出错误信息和诊断信息。当进程在执行过程中遇到错误或异常时,会将相关的错误信息通过错误管道发送出去,以便用户或其他程序能够及时了解问题所在。与标准输出管道不同,错误管道专门用于处理错误情况,这样可以将正常输出和错误信息分开处理。
  • 工作原理:程序在捕获到错误或异常时,可以将错误信息写入错误管道。在 Python 中,可以使用 sys.stderr 来输出错误信息;在 Java 中,可以使用 System.err.println() 方法。
  • 示例(Python)
import systry:result = 1 / 0
except ZeroDivisionError:# 向标准错误输出错误信息print("发生了除零错误", file=sys.stderr)

  • 分离输出和错误示例:在命令行中,可以使用不同的重定向符号将标准输出和错误输出分别重定向到不同的文件。例如,ls non_existent_file 2> error.log 1> output.log 命令将错误信息重定向到 error.log 文件,将正常输出重定向到 output.log 文件。

管道在进程间通信中的作用

输入、输出和错误管道在进程间通信中起着关键作用,它们允许不同的进程之间进行数据交换和信息传递,使得多个进程可以协同工作,完成更复杂的任务。通过管道,一个进程的输出可以作为另一个进程的输入,形成一个处理链,提高了系统的灵活性和可扩展性。

二、脚本语言漏洞举例(乱入)

1.Python 的 subprocess 模块

概述

subprocess 模块是 Python 标准库中用于创建新进程连接到它们的输入 / 输出 / 错误管道并获取它们的返回码的模块。它提供了一个更强大且灵活的方式来执行外部命令,是 Python 中替代旧的 os.system()os.popen() 等函数的推荐方法。

常用方法和功能

  • subprocess.run():这是 Python 3.5 及以上版本中用于执行外部命令的高级接口。它会等待命令执行完成,并返回一个 CompletedProcess 对象,该对象包含了命令的返回码、标准输出和标准错误等信息。
import subprocessresult = subprocess.run(['ls', '-l'], capture_output=True, text=True)
if result.returncode == 0:print(result.stdout)
else:print(result.stderr)

  • subprocess.Popen():这是一个更底层的接口,允许你更精细地控制子进程的执行。你可以手动管理子进程的输入、输出和错误流,还可以在命令执行过程中进行交互。

import subprocessprocess = subprocess.Popen(['ping', 'www.example.com'], stdout=subprocess.PIPE, text=True)
while True:output = process.stdout.readline()if output == '' and process.poll() is not None:breakif output:print(output.strip())
安全风险

如果在使用 subprocess 模块时直接将用户输入作为命令的一部分,而没有进行充分的验证和过滤,就可能会导致 OS 注入攻击。例如:

import subprocessuser_input = input("请输入要执行的命令参数: ")
# 不安全的写法,可能导致命令注入
subprocess.run(f'ls {user_input}', shell=True)

2.Java 的 Runtime.exec() 方法

概述

Runtime.exec() 是 Java 中用于执行外部系统命令的方法。Runtime 类代表 Java 应用程序运行时的环境,通过 Runtime.getRuntime() 方法可以获取当前 Java 虚拟机的运行时对象,然后调用 exec() 方法来执行外部命令。

常用调用方式

  • 传递字符串参数:可以直接传递一个包含完整命令的字符串给 exec() 方法。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;public class RuntimeExecExample {public static void main(String[] args) {try {Process process = Runtime.getRuntime().exec("ls -l");BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));String line;while ((line = reader.readLine()) != null) {System.out.println(line);}int exitCode = process.waitFor();System.out.println("命令执行完毕,返回码: " + exitCode);} catch (IOException | InterruptedException e) {e.printStackTrace();}}
}

  • 传递字符串数组参数:也可以传递一个字符串数组,数组的每个元素代表命令的一个部分。
Process process = Runtime.getRuntime().exec(new String[]{"ls", "-l"});
安全风险

同样,如果在使用 Runtime.exec() 方法时将用户输入直接拼接到命令中,而没有进行严格的验证和过滤,会存在 OS 注入的风险。例如:

import java.io.IOException;
import java.util.Scanner;public class UnsafeRuntimeExec {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);System.out.println("请输入要执行的命令参数: ");String userInput = scanner.nextLine();try {// 不安全的写法,可能导致命令注入Runtime.getRuntime().exec("ls " + userInput);} catch (IOException e) {e.printStackTrace();}}
}

三、OS注入攻击(再次乱入)

OS 注入攻击,即操作系统注入攻击,是一种恶意攻击手段,攻击者通过利用应用程序或系统中的漏洞,将恶意的操作系统命令注入到目标系统中执行,以获取对系统的控制权或执行其他恶意操作。以下是关于它的详细介绍:

攻击原理

  • 输入验证缺失:与 SQL 注入类似,很多应用程序会接收用户输入并将其用于执行系统命令或与操作系统进行交互。如果应用程序没有对用户输入进行严格的验证和过滤,攻击者就可以输入包含恶意操作系统命令的内容,这些命令会被操作系统当作正常命令执行。
  • 命令拼接漏洞:在一些情况下,应用程序使用字符串拼接的方式来构建要执行的系统命令。攻击者通过注入恶意命令片段,改变原本的命令逻辑,从而执行他们期望的操作。例如,在一个执行文件下载的功能中,正常的命令可能是 wget https://example.com/file.txt,攻击者可以通过在输入字段中输入恶意内容,如 ; rm -rf /,使得最终执行的命令变成 wget https://example.com/file.txt; rm -rf /,从而导致系统中的文件被删除。

攻击方式

  • 通过 Web 应用漏洞:如果 Web 应用存在漏洞,攻击者可以通过在 Web 页面的输入框、表单等位置输入恶意命令,利用 Web 应用与操作系统的交互来执行注入的命令。比如在一个文件上传功能中,攻击者可以构造包含恶意命令的文件名,当服务器对文件名进行处理并执行相关系统命令时,就可能触发 OS 注入。
  • 利用网络服务漏洞:一些网络服务在处理用户请求时可能存在漏洞,攻击者可以向这些服务发送特制的请求,其中包含恶意的操作系统命令。例如,某些 FTP 服务器在处理用户的命令输入时,如果没有进行充分的验证,攻击者就可以通过 FTP 命令注入恶意的操作系统指令。
  • 利用脚本语言漏洞:在使用脚本语言编写的应用程序中,如果对用户输入的处理不当,也可能导致 OS 注入攻击。例如,在 Python 的 subprocess 模块或 Java 的 Runtime.exec() 方法中,如果直接使用用户输入来执行系统命令,而没有进行安全检查,就容易受到攻击。

危害

  • 系统控制与数据窃取:攻击者可以获取系统的管理员权限或其他高级权限,从而能够访问、窃取系统中的敏感数据,如用户账号信息、机密文件等。
  • 系统破坏与服务中断:能够删除重要的系统文件、篡改系统配置,导致系统无法正常运行,使服务中断,影响业务的连续性,给企业和用户带来严重的损失。
  • 进一步攻击的跳板:一旦攻击者成功实施 OS 注入攻击并控制了目标系统,就可以将该系统作为跳板,进一步对内部网络中的其他系统进行攻击,扩大攻击范围。

防范措施

  • 严格输入验证:对所有来自用户的输入进行严格的验证和过滤,确保输入只包含合法的字符和内容,不包含任何可能导致命令注入的特殊字符或命令关键字。
  • 使用安全的函数和方法:在编写代码时,优先使用安全的函数和方法来执行系统命令或与操作系统交互。这些函数通常会对输入进行自动的安全处理,减少注入风险。
  • 最小权限原则:为应用程序和用户分配最小的权限,只授予其执行必要操作所需的权限,避免使用具有过高权限的账户来运行应用程序或执行系统命令。
  • 系统更新与漏洞修复:及时更新操作系统、应用程序和相关软件,修复已知的安全漏洞,降低被攻击的风险。

四、进程间通信的方式

进程间通信(Inter - Process Communication,IPC)是指在不同进程之间传播或交换信息的机制。以下是常见的进程间通信方式:

1. 管道(Pipe)

  • 匿名管道(Anonymous Pipe)
    • 原理:一种半双工的通信方式,数据只能在一个方向上流动,通常用于具有亲缘关系的进程(如父子进程)之间。在创建管道时,操作系统会返回两个文件描述符,一个用于读,一个用于写。
    • 示例(Unix/Linux 系统,C 语言):父进程向子进程发送数据
#include <stdio.h>
#include <unistd.h>
#include <string.h>int main() {int pipefd[2];pid_t pid;char buffer[100];if (pipe(pipefd) == -1) {perror("pipe");return 1;}pid = fork();if (pid == -1) {perror("fork");return 1;}if (pid == 0) { // 子进程close(pipefd[1]); // 关闭写端read(pipefd[0], buffer, sizeof(buffer));printf("子进程收到: %s\n", buffer);close(pipefd[0]);} else { // 父进程close(pipefd[0]); // 关闭读端const char *message = "Hello, child process!";write(pipefd[1], message, strlen(message));close(pipefd[1]);}return 0;
}

  • 命名管道(Named Pipe,FIFO)
    • 原理:一种全双工的通信方式,它可以在不相关的进程之间进行通信。命名管道以文件的形式存在于文件系统中,进程通过打开和操作这个文件来进行数据传输。
    • 示例(Unix/Linux 系统,C 语言):一个进程写数据,另一个进程读数据
// 写进程
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>#define FIFO_NAME "myfifo"int main() {int fd;const char *message = "Hello, named pipe!";fd = open(FIFO_NAME, O_WRONLY);write(fd, message, strlen(message));close(fd);return 0;
}// 读进程
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>#define FIFO_NAME "myfifo"int main() {int fd;char buffer[100];fd = open(FIFO_NAME, O_RDONLY);read(fd, buffer, sizeof(buffer));printf("收到消息: %s\n", buffer);close(fd);return 0;
}

2. 消息队列(Message Queue)

  • 原理:消息队列是存放在内核中的消息链表,每个消息队列由一个标识符(即队列 ID)来标识。进程可以向消息队列中添加消息,也可以从消息队列中读取消息。消息队列可以实现消息的随机查询,不一定要以先进先出的顺序读取。
  • 示例(Python,使用multiprocessing.Queue

from multiprocessing import Process, Queuedef sender(q):q.put("Hello from sender!")def receiver(q):message = q.get()print(f"Receiver got: {message}")if __name__ == '__main__':q = Queue()p1 = Process(target=sender, args=(q,))p2 = Process(target=receiver, args=(q,))p1.start()p2.start()p1.join()p2.join()

3. 共享内存(Shared Memory)

  • 原理:多个进程可以访问同一块物理内存区域,是最快的一种 IPC 方式。因为数据不需要在不同的进程之间复制,而是直接在共享内存区域进行读写操作。
  • 示例(Unix/Linux 系统,C 语言)

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>#define SHM_SIZE 1024int main() {int shmid;key_t key;char *shm, *s;key = ftok(".", 'a');shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0666);shm = shmat(shmid, NULL, 0);strcpy(shm, "Hello, shared memory!");s = shm;while (*s != '\0') {putchar(*s++);}putchar('\n');shmdt(shm);shmctl(shmid, IPC_RMID, NULL);return 0;
}

4.信号量(Semaphore)

  • 原理:信号量是一个计数器,用于控制多个进程对共享资源的访问。它主要用于实现进程间的同步和互斥。当信号量的值大于 0 时,表示可以访问共享资源;当信号量的值为 0 时,表示需要等待其他进程释放资源。
  • 示例(Unix/Linux 系统,C 语言)

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>union semun {int val;struct semid_ds *buf;unsigned short *array;
};void sem_init(int semid) {union semun arg;arg.val = 1;if (semctl(semid, 0, SETVAL, arg) == -1) {perror("semctl");exit(1);}
}void sem_wait(int semid) {struct sembuf sb = {0, -1, 0};if (semop(semid, &sb, 1) == -1) {perror("semop");exit(1);}
}void sem_signal(int semid) {struct sembuf sb = {0, 1, 0};if (semop(semid, &sb, 1) == -1) {perror("semop");exit(1);}
}int main() {int semid;key_t key;key = ftok(".", 'a');semid = semget(key, 1, IPC_CREAT | 0666);sem_init(semid);sem_wait(semid);printf("进入临界区\n");sem_signal(semid);printf("离开临界区\n");semctl(semid, 0, IPC_RMID);return 0;
}

5.套接字(Socket)

  • 原理:套接字是一种网络编程接口,它不仅可以用于不同主机之间的进程通信,也可以用于同一主机上的进程通信。通过创建套接字,进程可以建立网络连接,发送和接收数据。
  • 示例(Python,本地进程间通信)
# 服务器端
import socketserver_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
server_socket.bind('./uds_socket')
server_socket.listen(1)conn, addr = server_socket.accept()
data = conn.recv(1024)
print(f"收到消息: {data.decode()}")
conn.close()
server_socket.close()# 客户端
import socketclient_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
client_socket.connect('./uds_socket')
message = "Hello, socket!"
client_socket.sendall(message.encode())
client_socket.close()

五、进程间通信方式的选择依据是什么?

在选择进程间通信(IPC)方式时,需要综合考虑多个因素,以下是一些主要的选择依据:

通信需求方面

  • 数据传输量
    • 少量数据:如果进程间只需要传输少量的数据,如状态信息、标志位等,管道(包括匿名管道和命名管道)、消息队列是比较合适的选择。例如,在一个简单的父子进程通信场景中,父进程向子进程发送一个启动信号,使用匿名管道就可以高效地完成。
    • 大量数据:当需要传输大量数据时,共享内存是最佳选择。因为共享内存直接在物理内存中开辟一块区域供多个进程访问,数据不需要在进程间复制,避免了数据复制带来的开销,能显著提高数据传输效率。比如,在图像处理应用中,一个进程负责采集图像数据,另一个进程负责对图像进行处理,使用共享内存可以快速地将采集到的大量图像数据传递给处理进程。
  • 数据传输方向
    • 单向传输:匿名管道是一种半双工的通信方式,数据只能在一个方向上流动,适合单向的数据传输场景。例如,在一个日志处理系统中,一个进程负责生成日志,另一个进程负责将日志写入文件,使用匿名管道可以方便地将日志数据从生成进程传输到写入进程。
    • 双向传输:命名管道、套接字和共享内存都支持双向的数据传输。如果两个进程需要频繁地进行数据交互,例如客户端 - 服务器架构中的客户端和服务器进程,使用套接字可以实现双向的通信,并且可以在不同主机之间进行通信。
  • 数据传输的实时性
    • 实时要求高:共享内存和套接字更适合对实时性要求较高的场景。共享内存由于直接操作物理内存,数据传输几乎没有延迟;套接字可以通过设置合适的网络参数和协议,保证数据的实时传输。例如,在实时监控系统中,传感器数据需要及时传输到处理进程进行分析,使用共享内存或套接字可以满足实时性要求。
    • 实时要求低:消息队列对实时性的要求相对较低,它允许消息在队列中进行缓冲和排队。例如,在一个邮件系统中,用户发送的邮件可以先放入消息队列中,然后由后台进程逐步处理和发送,不需要立即处理。

进程关系方面

  • 亲缘关系进程:对于具有亲缘关系的进程(如父子进程),匿名管道是一种简单且高效的通信方式。因为匿名管道的创建和使用与进程的亲缘关系紧密相关,父进程创建管道后可以方便地将文件描述符传递给子进程。例如,在一个多进程的文件处理程序中,父进程可以通过匿名管道将文件的部分内容传递给子进程进行处理。
  • 非亲缘关系进程:命名管道、消息队列、共享内存和套接字可以用于非亲缘关系的进程之间的通信。其中,套接字不仅可以用于同一主机上的非亲缘关系进程通信,还可以用于不同主机之间的进程通信,具有更广泛的适用性。例如,在一个分布式系统中,不同服务器上的进程可以通过套接字进行通信和数据交换。

同步与互斥需求方面

  • 需要同步互斥:如果多个进程需要对共享资源进行同步访问,避免数据竞争和不一致问题,信号量是一个重要的选择。信号量可以作为一种同步机制,控制进程对共享资源的访问顺序。例如,在一个多进程的数据库管理系统中,多个进程可能同时需要访问数据库中的某个表,使用信号量可以确保同一时间只有一个进程可以对该表进行写操作,保证数据的一致性。
  • 不需要同步互斥:如果进程间的通信不需要严格的同步和互斥机制,如简单的数据传递场景,可以选择管道或消息队列等方式。这些方式相对简单,不需要额外的同步操作。

系统兼容性和可移植性方面

  • 特定系统:不同的操作系统对各种 IPC 方式的支持程度可能有所不同。例如,某些实时操作系统可能对共享内存和信号量的支持更好,而在一些嵌入式系统中,可能更倾向于使用简单的管道或消息队列。在选择 IPC 方式时,需要考虑目标系统的特性和限制。
  • 跨平台需求:如果应用程序需要在不同的操作系统上运行,套接字是一个比较好的选择,因为它具有良好的跨平台性。大多数操作系统都提供了对套接字编程的支持,并且可以通过标准的网络协议进行通信。

开发复杂度方面

  • 简单开发:管道和消息队列的使用相对简单,不需要复杂的编程和配置。对于初学者或对开发时间要求较高的项目,可以优先考虑使用这些方式。例如,在一个小型的脚本化应用中,使用管道可以快速实现进程间的通信。
  • 复杂功能:共享内存和套接字的使用相对复杂,需要处理更多的细节,如内存管理、网络连接和错误处理等。但它们可以实现更复杂的功能,如高性能的数据传输和分布式通信。在开发大型的分布式系统或对性能要求较高的应用时,可能需要选择这些方式。

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

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

相关文章

STM32HAL库快速入门教程——常用外设学习(2)

目录 一、STM32HAL库开发&#xff08;8&#xff09;——CubeMX配置DMA 1.1、什么是DMA&#xff1f; 1.2、内存内存之间的传输&#xff08;单次&#xff09; ​编辑 1.3、内存外设之间的传输&#xff08;ADC&#xff09; 二、STM32HAL库开发&#xff08;9&#xff09;——…

Spring Boot 整合 SSE(Server-Sent Events)

1、简述 SSE&#xff08;Server-Sent Events&#xff09;是一种基于HTTP协议的单向通信机制&#xff0c;允许服务器向浏览器持续发送实时更新。与WebSocket不同&#xff0c;SSE更简单&#xff0c;使用HTTP/1.1协议即可&#xff0c;不需要额外的协议升级。 SSE的特点&#xff…

汽车ECU实现数据安全存储的一种方案

一、 综述 在车辆ECU中总是有一些密钥或重要数据需进行机密性保护&#xff0c;但因产品选型、成本等考虑&#xff0c;导致一些ECU的芯片不支持硬件安全模块&#xff08;例如HSM、TEE等&#xff09;。此时&#xff0c;为保障数据的机密性&#xff0c;可考虑通过软件实现数据的安…

十进制数到十六进制数的转换

十进制数x&#xff0c;若能表示为&#xff0c;n为大于等于0的整数。ni4j。i取值为0、1、2和3。综合i和j&#xff0c;若i为0&#xff0c;则该16进制数为1后面加j个0&#xff1b;若i为1&#xff0c;则该16进制数为2后面加j个0&#xff1b;若i为2&#xff0c;则该16进制数为4后面加…

基于YoloV11+PaddleOCR的车牌检测系统

文章目录 一、CCPD数据集进行处理1.1 从文件夹构建txt格式数据集1.2 运行脚本按照8&#xff1a;2划分训练集&#xff0c;测试集 二 、YOLOV11训练模型2.1 编写car_plate.yaml文件2.2 编写train脚本&#xff1a;2.3 训练过程 三、PaddleOCR识别车牌号3.1 安装paddleocr&#xff…

2月12日鸿蒙生态日日新PLOG,多款应用上架

2月12日鸿蒙生态日日新PLOG &#xff1a;北京医院挂号通、有度、远光商旅等多款应用上架&#xff1b;钉钉、得到、航班管家等多款重点应用功能更新。 ​​​

Python----PyQt开发(PyQt高级:手搓一个简单的记事本)

一、效果展示 二、设计PyQt界面 2.1、设置图标 self.setWindowIcon(QIcon(./images/icon/1.png)) # 窗口图标 2.2、设置标题 self.file_name 无标题-新建文本文档 # 默认文件名 self.setWindowTitle(self.file_name) # 窗口标题 2.3、添加菜单栏、工具栏、状态栏 # 创…

Java 大视界 -- 大数据伦理与法律:Java 技术在合规中的作用与挑战(87)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

什么是AI Agent、Chat、RAG、MoE

什么是AI Agent、Chat、RAG、MoE 目录 什么是AI Agent、Chat、RAG、MoE定义与原理功能特点应用场景AI Agent有哪些关键组成部分感知模块决策模块知识模块行动模块学习模块AI Agent、Chat、RAG、MoE是人工智能领域中不同的概念和技术,它们在功能、原理和应用等方面存在一些区别…

在 debian 12 上安装 mysqlclient 报错

报错如下 Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple Collecting mysqlclientUsing cached https://pypi.tuna.tsinghua.edu.cn/packages/61/68/810093cb579daae426794bbd9d88aa830fae296e85172d18cb0f0e5dd4bc/mysqlclient-2.2.7.tar.gz (91 kB)Installi…

自反馈与流量震荡:从 TCP/IP 路由到交通导航

为什么不能基于流量或时延做路由度量&#xff0c;而不仅仅基于跳数。原因在于这里存在一个自反馈&#xff1a; 路由决策导致流量变化&#xff1b;时延由流量变化而变化&#xff1b;流量时延影响路由决策。 当某条链路流量减少时&#xff0c;路由协议会将其度量调低&#xff0…

Jtti:centos主机如何搭建lnmp环境

在 CentOS 主机上搭建 LNMP(Linux Nginx MySQL/MariaDB PHP)环境是构建高性能 Web 服务器的常见选择。以下是搭建 LNMP 环境的详细步骤&#xff1a; 步骤 1: 更新系统 首先&#xff0c;更新系统的包列表和安装的包&#xff0c;以确保你的系统是最新的&#xff1a; sudo y…

如果需要保护多个域名怎么办?

随着企业和个人在网上的存在越来越重要&#xff0c;管理和保护多个域名变得尤为关键&#xff0c;那么如果需要保护这些域名&#xff0c;应该采取什么样的措施呢&#xff1f; 许多企业会选择注册与其品牌相关的不同后缀&#xff0c;或者与其产品、服务相关的域名。这不仅可以防…

从Sora到有言:3D视频生成技术的突破与应用

近年来&#xff0c;AIGC领域飞速发展&#xff0c;这个词也越来越高频地出现在了大家的生活中。AIGC 能完成的任务也越来越多&#xff0c;大模型的能力飞速增长 —— 从Deepseek生成文字&#xff0c;到StableDiffusion生成图像&#xff0c;再到Sora可以生成视频。 而现在&#x…

Apollo 9.0 控制算法 -- lon based pid controller

文章目录 1. 纵向控制算法1.1 算法结构1.1.1 外环&#xff1a;位置环1.1.2 内环&#xff1a;速度环 1.2 参数整定 2. 代码解析2.1 控制器初始化 LonController::Init()2.1.1 PID控制参数和标定表参数加载2.1.2 PID控制器初始化2.1.3 超前/滞后控制器初始化2.1.4 俯仰角滤波器初…

【JavaScript】《JavaScript高级程序设计 (第4版) 》笔记-Chapter12-BOM

十二、BOM 虽然 ECMAScript 把浏览器对象模型&#xff08;BOM&#xff0c;Browser Object Model&#xff09;描述为 JavaScript 的核心&#xff0c;但实际上 BOM 是使用 JavaScript 开发 Web 应用程序的核心。BOM 提供了与网页无关的浏览器功能对象。 HTML5 规范中有一部分涵盖…

Qt信号槽调用出错:Qt: Dead lock detected while activating a BlockingQueuedConnection

目录 1.现象和原因分析 2. 总结 1.现象和原因分析 就在最近的开发过程中&#xff0c;程序一运行在控制台就打印&#xff1a; Qt: Dead lock detected while activating a BlockingQueuedConnection&#xff1a; 咋一看&#xff0c;怎么出现死锁了呢&#xff1f;仔细看下…

Jenkins项目CICD流程

Jenkins项目流程:1.配置git环境 git config --...2.把前后端的目录初始化位本地工作目录 #git init3.提交到本地git #git add ./ git commit -m "" git tag v14.然后提交到远程git(通过,用户,群组,项目,管理项目)git remote add origin http://...git push -…

Springboot_实战

项目开发 lombok使用 自动为实体类提供get、set、toString方法 引入依赖 实体类上添加注解 统一响应结果 注意要写get、set方法&#xff1b;下面是错误的&#xff0c;因此要加上Data注解 一个注册的接口的示例 Controller层 Service层 Mapper层 参数校验 但是同样存在一…

C++自研游戏引擎-碰撞检测组件-八叉树AABB检测算法实现

八叉树碰撞检测是一种在三维空间中高效处理物体碰撞检测的算法&#xff0c;其原理可以类比为一个管理三维空间物体的智能系统。这个示例包含两个部分&#xff1a;八叉树部分用于宏观检测&#xff0c;AABB用于微观检测。AABB可以更换为均值或节点检测来提高检测精度。 八叉树的…