当前位置: 首页 > news >正文

Linux高性能服务器编程——ch6笔记

第6章 高级I/O函数

6.1 pipe函数

用于创建一个管道,以实现进程间通信。
int pipe(int fd[2]);

读端文件描述符fd[0]和写端文件描述符fd[1]构成管道的两端,默认是阻塞的,fd[0]读出数据,fd[1]写入数据。管道内部传输的数据是字节流。
如果fd[1]的引用计数减少至0,即没有任何进程需要往管道中写入数据,则针对f[0]的read操作将返回0,即读取到了文件结束标记(EOF);反之,如果fd[0]计数减少至 0,即没有任何进程需要从管道读取数据,则针对fd[1]的write操作将失败,并引发SIGPIPE信号。
socketpair函数:双向管道,但仅能在本地使用。

6.2 dup函数和dup2函数

用于复制文件描述符,但不继承原文件描述符的属性。
int dup(int file_descriptor);
int dup2(int file_descriptor_one, int file_descriptor_two);

dup函数创建一个新的文件描述符(系统当前可用的最小整数),与原有file_descriptor指向相同文件、管道或者网络连接。
dup2函数类似,但返回第一个不小于file_descriptor_two的整数。

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>int main(int argc, char *argv[])
{if (argc < 2){printf("usage: %s ip_address port_number\n", basename(argv[0]));return 1;}const char *ip = argv[1];int port = atoi(argv[2]);struct sockaddr_in address;bzero(&address, sizeof(address));address.sin_family = AF_INET;inet_pton(AF_INET, ip, &address.sin_addr);address.sin_port = htons(port);int sock = socket(PF_INET, SOCK_STREAM, 0);assert(sock > 0);int ret = bind(sock, (struct sockaddr *)&address, sizeof(address));assert(ret != -1);ret = listen(sock, 5);assert(ret != -1);struct sockaddr_in client;socklen_t client_addrlength = sizeof(client);int connfd = accept(sock, (struct sockaddr *)&client, &client_addrlength);if (connfd < 0){printf("errno is : %d\n", errno);}else{close(STDOUT_FILENO);  //关闭标准输出文件描述符,值为1dup(connfd);  //返回最小可用文件描述符,返回1
// 服务器输出到标准输出的内容就会直接发送到与客户连接对应的 socket 上
// 因此 printf 的输出将被客户端获得(而不是显示在服务器程序的终端上)printf("abcd\n");close(connfd);}close(sock);return 0;
}

6.3 readv函数和writev函数

ssize_t readv(int fd, const struct iovec* vector, int count);
ssize_t writev(int fd, const struct iovec* vector, int count);

readv函数将数据从文件描述符读到分散的内存块中,即分散读;writev函数则将多块分散的内存数据一并写入文件描述符中,即集中写。
当Web服务器解析完一个HTTP请求之后,如果目标文档存在,且客户具有读取该文档的权限,那么它就需要发送一个HTTP应答来传输该文档。这个HTTP应答包含1个状态行、多个头部字段、1个空行和文档的内容。前3部分的内容可能被Web服务器放置在一块内存中,而文档的内容则通常被读到另外一块单独的内存中(通过read函数或mmap函数)。我们并不需要把这两部分内容拼接到一起再发送,而是可以使用writev函数将它们同时写出。

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>#define BUFFER_SIZE 1024/* 定义两种HTTP状态吗和状态信息 */
static const char *status_line[2] = {"200 OK", "500 Internal server error"};int main(int argc, char *argv[])
{if (argc < 3){printf("usage: %s ip_address port_number filename\n", basename(argv[0]));return 1;}const char *ip = argv[1];int port = atoi(argv[2]);/* 将目标文件作为程序的第三个参数传入 */const char *file_name = argv[3];struct sockaddr_in address;bzero(&address, sizeof(address));address.sin_family = AF_INET;inet_pton(AF_INET, ip, &address.sin_addr);address.sin_port = htons(port);int sock = socket(PF_INET, SOCK_STREAM, 0);assert(sock >= 0);int ret = bind(sock, (struct sockaddr *)&address, sizeof(address));assert(ret != -1);ret = listen(sock, 5);assert(ret != -1);struct sockaddr_in client;socklen_t client_addrlength = sizeof(client);int connfd = accept(sock, (struct sockaddr *)&client, &client_addrlength);if (connfd < 0){printf("errno is : %d\n", errno);}else{/* 用于保存HTTP应答的状态行、头部字段和一个空行的缓冲区 */char header_buf[BUFFER_SIZE];memset(header_buf, '\0', BUFFER_SIZE);/* 用于存放目标文件内容的应用程序缓存 */char *file_buf = NULL;/* 用于获取目标文件的属性,比如是否为目录,文件大小等 */struct stat file_stat;/* 记录目标文件是否是有效文件 */bool valid = true;/* 缓冲区header_buf目前已经使用了多少字节的空间 */int len = 0;if (stat(file_name, &file_stat) < 0) /* 目标文件不存在 */{valid = false;}else{if (S_ISDIR(file_stat.st_mode)) /* 目标文件是一个目录 */{valid = false;}else if (file_stat.st_mode & S_IROTH) /* 当前用户有读取目标文件的权限 */{/* 动态分配缓存区file_buf, 并制定其大小为目标文件的大小* file_stat.st_size 加1, 然后将目标文件读入缓存区file_buf中 */int fd = open(file_name, O_RDONLY);file_buf = new char [file_stat.st_size + 1];memset(file_buf, '\0', file_stat.st_size + 1);if (read(fd, file_buf, file_stat.st_size) < 0){valid = false;}}else{valid = false;}}/* 如果目标文件有效,则发送正常的HTTP应答 */if (valid){/* 下面这部分内容将HTTP应答的状态行、“Content-Length”头部字段和一个空行* 依次加入header_buf中 */ret = snprintf(header_buf, BUFFER_SIZE - 1, "%s %s\r\n","HTTP/1.1", status_line[0]);len += ret;ret = snprintf(header_buf + len, BUFFER_SIZE - 1 - len,"Content-Length: %d\r\n", file_stat.st_size);len += ret;ret = snprintf(header_buf + len, BUFFER_SIZE - 1 - len,"%s", "\r\n");/* 利用writev将header_buf和file_buf的内容一并写出 */struct iovec iv[2];iv[0].iov_base = header_buf;iv[0].iov_len = strlen(header_buf);iv[1].iov_base = file_buf;iv[1].iov_len = file_stat.st_size;ret = writev(connfd, iv, 2);}else /* 如果目标文件无效,则通知客户端服务器发生了"内部错误" */{ret = snprintf(header_buf, BUFFER_SIZE - 1, "%s %s\r\n","HTTP/1.1", status_line[1]);len += ret;ret = snprintf(header_buf + len, BUFFER_SIZE - 1 - len, "%s","\r\n");send(connfd, header_buf, strlen(header_buf), 0);}close(connfd);delete[] file_buf;}close(sock);return 0;
}

省略了HTTP请求的接收及解析,该代码只关注HTTP应答的发送。

6.4 sendfile函数

在内核中操作,在两个文件描述符之间直接传递数据。避免了内核缓冲区和用户缓冲区之间的数据拷贝,效率很高,这被称为零拷贝。
ssize_t sendlile(int out_fd, int in_fd, off_t* offset, size_t count);

in_fd(待读出)必须是一个支持类似mmap函数的文件描述符,即它必须指向真实的文件,不能是socket和管道;而out_fd(待写入)则必须是一个socket。由此可见,sendfile几乎是专门为在网络上传输文件而设计的。

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/sendfile.h>int main(int argc, char *argv[])
{if (argc <= 3){printf("usage: %s ip_address port_numberr filename\n", basename(argv[0]));return 1;}const char *ip = argv[1];int port = atoi(argv[2]);const char *file_name = argv[3];int filefd = open(file_name, O_RDONLY);assert(filefd > 0);struct stat stat_buf;fstat(filefd, &stat_buf);struct sockaddr_in address;bzero(&address, sizeof(address));address.sin_family = AF_INET;inet_pton(AF_INET, ip, &address.sin_addr);address.sin_port = htons(port);int sock = socket(PF_INET, SOCK_STREAM, 0);assert(sock > 0);int ret = bind(sock, (struct sockaddr *)&address, sizeof(address));assert(ret != -1);ret = listen(sock, 5);assert(ret != -1);struct sockaddr_in client;socklen_t client_addrlength = sizeof(client);int connfd = accept(sock, (struct sockaddr *)&client, &client_addrlength);if (connfd < 0){printf("errno is : %d\n", errno);}else{sendfile(connfd, filefd, NULL, stat_buf.st_size);close(connfd);close(filefd);}close(sock);return 0;
}

没有为目标文件分配任何用户空间的缓存,也没有执行读取文件的操作,但同样实现 了文件的发送。

6.5 mmap函数和munmap函数

mmap函数用于申请一段内存空间。可以将这段内存作为进程间通信的共享(也可为调用进程所私有)内存,
也可以将文件内接映射到其中。munmap函数则释放由mmap创建的这段内存空间。

void* mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
int munmap(void *start, size_t length);

6.6 splice函数

用于在两个文件描述符之间移动数据,也是零拷贝。

ssize_t splice(int fd_in, loff_t* off_in, int fd_out, loff_t* off_out, size_t len, unsigned int flags);

fd_in和fd_out必须至少有一个是管道文件描述符。

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>int main(int argc, char *argv[])
{if (argc <= 2){printf("usage: %s ip_address port_number\n", basename(argv[0]));return 1;}const char *ip = argv[1];int port = atoi(argv[2]);struct sockaddr_in address;bzero(&address, sizeof(address));address.sin_family = AF_INET;inet_pton(AF_INET, ip, &address.sin_addr);address.sin_port = htons(port);int sock = socket(PF_INET, SOCK_STREAM, 0);assert(sock >= 0);int ret = bind(sock, (struct sockaddr *)&address, sizeof(address));assert(ret != -1);ret = listen(sock, 5);assert(ret != -1);struct sockaddr_in client;socklen_t client_addrlength = sizeof(client);int connfd = accept(sock, (struct sockaddr *)&client, &client_addrlength);if (connfd < 0){printf("errno is : %d\n", errno);}else{int pipefd[2];ret = pipe(pipefd); /* 创建管道 */assert(ret != -1);/* 将connfd上流入的客户数据定向到管道中 */ret = splice(connfd, NULL, pipefd[1], NULL, 32768,SPLICE_F_MORE | SPLICE_F_MOVE);assert(ret != -1);/* 将管道的输出定向到connfd客户连接文件描述符 */ret = splice(pipefd[0], NULL, connfd, NULL, 32768,SPLICE_F_MORE | SPLICE_F_MOVE);assert(ret != -1);close(connfd);}close(sock);return 0;
}

通过splice函数将客户端的内容读入到pipefd[1]中,然后再使用splice函数从pipefd[0]中读出该内容到客户端,从而实现了简单高效的回射服务。整个过程未执行recv或send操作,因此也未涉及用户空间和内核空间之间的数据拷贝。

6.7 tee函数

在两个管道文件描述符之间复制数据,也是零拷贝操作。它不消耗数据,因此源文件描述符上的数据仍然可以用于后续的读操作。

ssize_t tee(int fd_in, int fd_out, size_t len, unsigned int flags);

#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>int main(int argc, char *argv[])
{if (argc != 2){printf("usage: %s <file>\n", basename(argv[0]));return 1;}int filefd = open(argv[1], O_CREAT | O_WRONLY | O_TRUNC, 0666);assert(filefd > 0);int pipefd_stdout[2];int ret = pipe(pipefd_stdout);assert(ret != -1);int pipefd_file[2];ret = pipe(pipefd_file);assert(ret != -1);/* 将标准输入内容输入管道pipefd_stdout */ret = splice(STDIN_FILENO, NULL, pipefd_stdout[1], NULL,32768, SPLICE_F_MORE | SPLICE_F_MOVE);assert(ret != -1);/* 将管道pipefd_stdout 的输出复制到管道pipefd_file的输入端 */ret = tee(pipefd_stdout[0], pipefd_file[1], 32768, SPLICE_F_NONBLOCK);assert(ret != -1);/* 将管道pipefd_file的输出定向到文件描述符filefd上,从而将标准输入的内容写入文件 */ret = splice(pipefd_file[0], NULL, filefd, NULL,32768, SPLICE_F_MORE | SPLICE_F_MOVE);assert(ret != -1);/* 将管道pipefd_stdout 的输出定向到标准输出,其内容和写入文件的内容完全一致 */ret = splice(pipefd_stdout[0], NULL, STDOUT_FILENO, NULL,32768, SPLICE_F_MORE | SPLICE_F_MOVE);assert(ret != -1);close(filefd);close(pipefd_stdout[0]);close(pipefd_stdout[1]);close(pipefd_file[0]);close(pipefd_file[1]);return 0;
}

6.8 fcntl函数

提供了对文件描述符的各种控制操作,另外一个常见的控制文件描述符属性和行为的系统调用是ioctl,而且ioctl比fcntl能够执行更多的控制。但是,对于控制文件描述符常用的属性和行为,fcntl函数是由POSIX规范指定的首选方法。
网络编程中,fcntl函数通常用来将一个文件描述符设置为非阻塞的。
SIGIO和SIGURG这两个信号与其他Linux信号不同,它们必须与某个文件描述符相关联方可使用:当被关联的文件描述符可读或可写时,系统将触发 SIGIO信号;当被关联的文件描述符(而且必须是一个socket)上有带外数据可读时,系统将触发 SIGURG信号。将信号和文件描述符关联的方法,就是使用fcntl函数为目标文件描述符指定宿主进程或进程组,那么被指定的宿主进程或进程组将捕获这两个信号。使用 SIGIO时,还需要利用fcntl设置其O_ASYNC标志(异步I/O标志,不过SIGIO信号模型并非真正意义上的异步I/O模型)。

相关文章:

Linux高性能服务器编程——ch6笔记

第6章 高级I/O函数 6.1 pipe函数 用于创建一个管道&#xff0c;以实现进程间通信。 int pipe(int fd[2]); 读端文件描述符fd[0]和写端文件描述符fd[1]构成管道的两端&#xff0c;默认是阻塞的&#xff0c;fd[0]读出数据&#xff0c;fd[1]写入数据。管道内部传输的数据是字节…...

【C语言进阶】文件操作

文件操作 1. 为什么使用文件2. 什么是文件2.1程序文件2.2 数据文件2.3 文件名 3. 文件的打开和关闭3.1 文件指针3.2 文件的打开和关闭 4. 文件的顺序读写4.1 对比一组函数 5. 文件的随机读写5.1 fseek5.2 ftell5.3 rewind 6. 文本文件和二进制文件7. 文件读取结束的判定7.1 被错…...

Redis学习(第八章缓存策略)

目录 RdisExample 课程介绍 1.Redis介绍 2.Redis 安装 3. Redis的数据结构 4. Redis缓存特性 5. Redis使用场景 6. Redis客户端-Jedis 7. Jedis Pipeline 8. Redis缓存策略 学习资料 QA 相关问题 http, socket ,tcp的区别 RdisExample 项目代码地址&#xff1a;htt…...

springboot+vue开发的视频弹幕网站动漫网站

springbootvue开发的视频弹幕网站动漫网站 演示视频 https://www.bilibili.com/video/BV1MC4y137Qk/?share_sourcecopy_web&vd_source11344bb73ef9b33550b8202d07ae139b 功能&#xff1a; 前台&#xff1a; 首页&#xff08;猜你喜欢视频推荐&#xff09;、轮播图、分类…...

【CSS】常见 CSS 布局

1. 响应式布局 <!DOCTYPE html> <html><head><title>简单的响应式布局</title><style>/* 全局样式 */body {font-family: Arial, sans-serif;margin: 0;padding: 0;}/* 头部样式 */header {background-color: #333;color: #fff;padding: …...

数据结构---HashMap和HashSet

HashMap和HashSet都是存储在哈希桶之中&#xff0c;我们可以先了解一些哈希桶是什么。 像这样&#xff0c;一个数组数组的每个节点带着一个链表&#xff0c;数据就存放在链表结点当中。哈希桶插入/删除/查找节点的时间复杂度是O(1) map代表存入一个key值&#xff0c;一个val值…...

SLAM中相机姿态估计算法推导基础数学总结

相机模型 基本模型 内参 外参 对极几何 对极约束 外积符号 基础矩阵F和本质矩阵E 相机姿态估计问题分为如下两步: 本质矩阵 E t ∧ R Et^{\wedge}R Et∧R因为 t ∧ t^{\wedge} t∧其实就是个3x3的反对称矩阵&#xff0c;所以 E E E也是一个3x3的矩阵 用八点法估计E…...

【RS】遥感影像/图片64位、16位(64bit、16bit)的意义和区别

在数字图像处理中&#xff0c;我们常常会听到不同的位数术语&#xff0c;比如64位、16位和8位&#xff08;64bit、16bit、8bit&#xff09;。这些位数指的是图像的深度&#xff0c;也就是图像中每个像素可以显示的颜色数。位数越高&#xff0c;图像可以显示的颜色数就越多&…...

【单元测试】--基础知识

一、什么是单元测试 单元测试是软件开发中的一种测试方法&#xff0c;用于验证代码中的单个组件&#xff08;通常是函数、方法或类&#xff09;是否按预期工作。它旨在隔离和测试代码的最小单元&#xff0c;以确保其功能正确&#xff0c;提高代码质量和可维护性。单元测试通常…...

golang 反射机制

在 go 语言中&#xff0c;实现反射能力的是 reflect包&#xff0c;能够让程序操作不同类型的对象。其中&#xff0c;在反射包中有两个非常重要的 类型和 函数&#xff0c;两个函数分别是&#xff1a; reflect.TypeOfreflect.ValueOf 两个类型是 reflect.Type 和 reflect.Value…...

【Javascript】创建对象的几种方式

通过字面量创建对象 通过构造函数创建对象 Object()-------------构造函数 通过构造函数来实例化对象 给person注入属性 Factory工厂 this指向的是对象的本身使⽤new 实例化⼀个对象&#xff0c;就像⼯⼚⼀样...

深度学习_3_实战_房价预测

梯度 实战 代码&#xff1a; # %matplotlib inline import random import torch import matplotlib.pyplot as plt # from d21 import torch as d21def synthetic_data(w, b, num_examples):"""生成 Y XW b 噪声。"""X torch.normal(0,…...

HCIA -- 动态路由协议之RIP

一、静态协议的优缺点&#xff1a; 缺点&#xff1a; 1、中大型网络配置量过大 2、不能基于拓扑的变化而实时的变化 优点&#xff1a; 1、不会额外暂用物理资源 2、安全问题 3、计算路径问题 简单、小型网络建议使用静态路由&#xff1b;中大型较复杂网络&#xff0c;建议使用…...

JS常用时间操作moment.js参考文档

Moment.js是一个轻量级的JavaScript时间库&#xff0c;它方便了日常开发中对时间的操作&#xff0c;提高了开发效率。日常开发中&#xff0c;通常会对时间进行下面这几个操作&#xff1a;比如获取时间&#xff0c;设置时间&#xff0c;格式化时间&#xff0c;比较时间等等。下面…...

基于 FFmpeg 的跨平台视频播放器简明教程(九):Seek 策略

系列文章目录 基于 FFmpeg 的跨平台视频播放器简明教程&#xff08;一&#xff09;&#xff1a;FFMPEG Conan 环境集成基于 FFmpeg 的跨平台视频播放器简明教程&#xff08;二&#xff09;&#xff1a;基础知识和解封装&#xff08;demux&#xff09;基于 FFmpeg 的跨平台视频…...

设计模式_备忘录模式

备忘录模式 介绍 设计模式定义案例问题堆积在哪里解决办法备忘录模式行为型模式&#xff0c; 保存了数据某一个时间点的状态 在需要的时候进行回档单机游戏的角色 数据保存并且回档保存和回档加一个状态管理类 类图 代码 MomentData using UnityEngine;public class MomentD…...

双势阱模型

双势阱模型 原子钟 传统的原子钟利用氨分子 由于隧道效应&#xff0c;上顶点的氮原子可以贯穿三个氢原子形成的势垒&#xff0c;到达下顶点对体系注入微波能量后&#xff0c;氮原子在上下定点之间振荡&#xff0c;体系的能量在两个稳定态之间交替变换&#xff0c;其振荡频率决…...

文献阅读:The Reversal Curse: LLMs trained on “A is B” fail to learn “B is A”

文献阅读&#xff1a;The Reversal Curse: LLMs trained on “A is B” fail to learn “B is A” 1. 文章简介2. 实验 & 结果考察 1. finetune实验2. 真实知识问答 3. 结论 & 思考 文献链接&#xff1a;https://arxiv.org/abs/2309.12288 1. 文章简介 这篇文章是前…...

真实感受:是智能家居在选择合适的技术!

科技从来都是为了让我们的生活更加的简单、舒适&#xff0c;而智能家居的智能&#xff0c;体现在如何更更更方便的使用我需要控制的家居。 例如&#xff1a;下班躺在床上想休息&#xff0c;房间和大厅的灯还开着&#xff0c;这时你会选择什么产品躺着解决问题&#xff1f; 红外…...

前端 TS 快速入门之二:接口

1. 接口有什么用 通过 interface 定义接口。 检测对象的属性&#xff0c;不会去检查属性的顺序&#xff0c;只要相应的属性存在并且类型也是对的就可以。 interface IPerson {name: string;age: number; } function say(person: IPerson): void {console.log(my name is ${pers…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

C++ 基础特性深度解析

目录 引言 一、命名空间&#xff08;namespace&#xff09; C 中的命名空间​ 与 C 语言的对比​ 二、缺省参数​ C 中的缺省参数​ 与 C 语言的对比​ 三、引用&#xff08;reference&#xff09;​ C 中的引用​ 与 C 语言的对比​ 四、inline&#xff08;内联函数…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)

目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff0…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比

在机器学习的回归分析中&#xff0c;损失函数的选择对模型性能具有决定性影响。均方误差&#xff08;MSE&#xff09;作为经典的损失函数&#xff0c;在处理干净数据时表现优异&#xff0c;但在面对包含异常值的噪声数据时&#xff0c;其对大误差的二次惩罚机制往往导致模型参数…...

人机融合智能 | “人智交互”跨学科新领域

本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...

uniapp手机号一键登录保姆级教程(包含前端和后端)

目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号&#xff08;第三种&#xff09;后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...

【JavaSE】多线程基础学习笔记

多线程基础 -线程相关概念 程序&#xff08;Program&#xff09; 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序&#xff0c;比如我们使用QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程分配内存…...