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

Linux | 进程控制(进程终止与进程等待)

文章目录

  • Linux | 进程控制 — 进程终止 & 进程等待
    • 1、进程终止
      • 进程常见退出方法
      • 1.1退出码
        • 基本概念
        • 获取退出码的方式
        • 常见退出码约定
        • 使用场景
      • 1.2 strerror函数 & errno宏
      • 1.3 _exit函数
      • 1.4_exit和exit的区别
        • 1.4.1 所属头文件与函数原型
        • 1.4.2 执行过程差异
        • **结合现象分析**:
    • 2、进程等待
      • 2.1 进程等待的作用
      • 2.2 僵尸进程(Zombie Process)
      • 2.3 `wait()` 系统调用
      • 2.4 `waitpid()` 系统调用
      • 2.5 示例代码
    • 3、进程程序替换
      • 3.1 `exec` 系列函数
        • 3.1.1 `execl()`
        • 3.1.2 `execlp()`
        • 3.1.3 `execle()`
        • 3.1.4 `execv()`
        • 3.1.5 `execvp()`
        • 3.1.6 `execvpe()`
      • 3.2 `exec` 系列函数的特点
      • 3.3 示例代码

Linux | 进程控制 — 进程终止 & 进程等待

1、进程终止

进程常见退出方法

进程退出场景

  • 代码运行完毕,结果正确
  • 代码运行完毕,结果不正确
  • 代码异常终止

正常终止(可以通过echo $?查看进程退出码)

1.从main返回

2.调用exit

3._exit

异常退出:

  • ctrl + c,信号终止

1.1退出码

在 Linux 系统中,进程的退出码(也称为返回值)是进程结束时返回给其父进程或系统的值,用于表示进程执行的结果。下面从基本概念、获取方式、常见约定、使用场景等方面详细讲解。

基本概念
  • 进程的退出码是一个整数值,范围通常是 0 - 255。在 C 语言编写的程序中,通常通过 main 函数的 return 语句或者 exit() 函数来设置退出码。例如:
#include <stdio.h>
#include <stdlib.h>int main() {// 使用 return 语句设置退出码return 0; // 或者使用 exit() 函数// exit(0); 
}
获取退出码的方式
  • 父进程获取子进程退出码:父进程可以使用 wait()waitpid() 等系统调用获取子进程的退出状态信息,然后通过一些宏来提取退出码。示例如下:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>int main() {pid_t pid = fork();if (pid == 0) {// 子进程return 42;} else if (pid > 0) {// 父进程int status;waitpid(pid, &status, 0);if (WIFEXITED(status)) {int exit_code = WEXITSTATUS(status);printf("子进程退出码: %d\n", exit_code);}}return 0;
}
  • shell 中获取进程退出码:在 shell 里,可以使用 $? 变量获取上一个执行命令的退出码。例如:
./my_program
echo $?
常见退出码约定

虽然 Linux 没有强制统一所有程序使用特定的退出码,但存在一些被广泛遵循的约定:

  • 退出码 0:表示进程正常结束,任务成功完成。这是最常见的退出码,表示程序按预期执行完毕。
  • 退出码 1:一般代表通用的错误,当程序遇到一些未明确分类的错误时,常返回这个退出码。
  • 退出码 2:通常意味着程序在使用命令行参数时出现了错误,例如参数数量不对、参数格式错误等。
  • 退出码 126:表示命令虽然找到了,但由于权限问题或其他原因无法执行。
  • 退出码 127:表明命令未找到,可能是因为命令拼写错误或者该命令不在系统的搜索路径中。
  • 退出码 128 + N:其中 N 是信号编号。当进程因接收到信号而终止时,退出码通常是 128 + 信号编号。例如,进程因接收到 SIGTERM(信号编号 15)而终止,退出码就是 143(128 + 15)。
使用场景
  • 错误处理与调试*:开发人员可以根据退出码快速定位程序出现问题的大致原因。例如,如果程序返回退出码 2,就可以先检查命令行参数的处理逻辑。
  • 脚本流程控制:在 shell 脚本中,根据命令的退出码决定后续的操作。比如,如果某个依赖程序执行失败(返回非零退出码),脚本可以选择终止执行或者尝试其他替代方案。
./dependency_program
if [ $? -ne 0 ]; thenecho "依赖程序执行失败,脚本终止"exit 1
fi
  • 系统监控:系统监控工具可以根据进程的退出码判断进程是否正常运行。如果进程频繁以非零退出码结束,可能表示系统存在潜在问题,需要进一步排查。

1.2 strerror函数 & errno宏

strerror

头文件#include<string.h>

返回值:指向描述error errnum的错误字符串的指针,简单来说可以将退出码和对应的错误对应上。

举例:

#include<string.h>
int main()
{for(int i=0;i<10;i++){printf("%d: %s\n",strerror(i));}return 0;
}

效果如下,后面输出的就是退出码对应的错误描述:

errno

头文件#include<errno.h>

简单的说,errno会返回最后的一次错误码,使用errno可以获得退出码,通过返回退出码,在多进程中也可以让父进程知道子进程的状况。

注意:但是当进程异常退出的时候,本质可能就是代码没有跑完,那么进程的退出码就无意义了,所以应该要先看进程退出的时候,如果要关心进程的推出情况,要先关心退出时后有没有出异常,如果没有异常,再看结果是否正确,然后关心退出码。


  • 父进程关心子进程的退出,只需要确定:
    1. 父进程是否收到来自子进程的信号,若没有,说明没有异常,代码正常跑完
    2. 查看退出结果:0表示成功,非0表示错误,对应各自的原因

举例:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>int main()
{int ret = 0;char *p = (char*)malloc(1000*1000*1000*4);if(p==NULL){printf("malloc error, %d: %s\n".errno,strerror(errno));ret = errno;}   else{printf("malloc success\n");}   return ret;
}

1.3 _exit函数

头文件#include<unistd.h>

函数格式void _exit(int status);

exit函数最后也会调用_exit,但是在调用exit之前,还会做以下工作:

1、执行用户通过atexiton_exit定义的清理函数

2、关闭所有打开的流,所有的缓存数据均被写入

3、调用_exit

例1:

int main()
{printf("hello linux\n");exit(12);
}

或者:

int main()
{printf("hello linux\n");return 12;
}

编译执行完后再使用echo $?查询退出码,效果均如下:
在这里插入图片描述

区别在于:exit在任意地方被调用,都表示调用进程直接退出,如果调用的是return,只表示当前函数返回,原进程继续运行,如果调用一个含exit或者return的函数,就可以明显观察到。

1.4_exit和exit的区别

在 Linux 系统中,exit_exit 都用于终止进程,但它们在功能实现、调用过程以及使用场景等方面存在明显区别,下面为你详细介绍:

1.4.1 所属头文件与函数原型
  • exit:它是标准 C 库中的函数,其原型定义在 <stdlib.h> 头文件中,函数原型为 void exit(int status);。这里的 status 是进程的退出状态码,通常 0 表示正常退出,非零表示异常退出。
  • _exit:这是一个系统调用,其原型定义在 <unistd.h> 头文件中,函数原型为 void _exit(int status);status 的含义与 exit 中的相同。

1.4.2 执行过程差异
  • exit

    • 在调用 exit 时,它会先执行一些清理工作。首先,会调用所有通过 atexit 函数注册的清理函数,这些函数可以用于释放资源、关闭文件描述符等操作。
    • 接着,会刷新所有打开的标准 I/O 流缓冲区,将缓冲区中的数据写入对应的文件或设备。
    • 最后,调用 _exit 系统调用来真正终止进程,并将 status 作为退出状态返回给父进程。
  • _exit

    • _exit 是一个底层的系统调用,它会直接终止进程,不会执行任何清理工作。也就是说,它不会调用 atexit 注册的函数,也不会刷新标准 I/O 流缓冲区。
结合现象分析
int main()
{printf("hello world");sleep(1);//使用sleep能够观察到一些现象,下文会提及exit(11);
}

运行完毕后再调用echo $?查看退出码,效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

但是将exit改为_exit后:

int main()
{printf("hello world");sleep(1);_exit(11);
}

运行完毕后再调用echo $?查看退出码,效果如下:

在这里插入图片描述

原因

当代码中输出的内容以\n结尾时,当代码运行到printf这条语句时,程序会直接输出内容,但是如果没有以\n结尾,那么就会先将内容存到缓冲区中,当程序结束前会冲刷缓冲,关闭流,然后就有打印输出的效果,也正因此会发现运行的时候是先等待了一秒钟,输出句子后程序马上结束,而不是先输出句子,等待一秒钟再结束程序。


结合下图

  • 调用exit()后会先执行用户定义的清理函数,再冲刷缓冲,关闭流等,因此会有打印字符串的效果,最后再调用_exit系统调用
  • _exit()是一个系统调用接口,调用_exit()后,其会在操作系统内部直接终止进程,对应缓冲区的数据不做刷新。

2、进程等待

2.1 进程等待的作用

  • 之前在Linux | 进程状态一文中有提及过僵尸进程的问题,如果子进程退出,父进程没有反应,可能造成僵尸进程的问题,导致内存泄漏
  • 当进程一旦变成僵尸状态,即使使用Kill -9也无法结束进程,需要通过进程等待来结束它,进而解决内存泄漏的问题
  • 需要通过进程等待,获得子进程的退出情况和父进程给子进程分配的任务完成的情况,例如子进程执行程序完毕后结果是否正确,或者是否正常退出
  • 父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息。

在Linux中,进程等待是指一个进程(通常是父进程)等待其子进程终止并获取其退出状态。这是通过系统调用 wait()waitpid() 来实现的。进程等待的主要目的是防止子进程成为“僵尸进程”(Zombie Process),并确保父进程能够获取子进程的退出状态。

2.2 僵尸进程(Zombie Process)

当一个子进程终止时,它的退出状态需要被父进程读取。如果父进程没有读取子进程的退出状态,子进程的进程描述符仍然保留在系统中,这种进程称为“僵尸进程”。僵尸进程不占用CPU资源,但会占用进程表中的条目,如果系统中存在大量僵尸进程,可能会导致进程表耗尽,无法创建新的进程。

2.3 wait() 系统调用

wait() 系统调用会使父进程阻塞,直到它的任意一个子进程终止。如果已经有子进程终止,wait() 会立即返回。

#include <sys/types.h>
#include <sys/wait.h>pid_t wait(int *status);
  • 参数:

    • status: 一个指向整数的指针,用于存储子进程的退出状态。可以通过宏(如 WIFEXITED(status)WEXITSTATUS(status) 等)来解析这个状态。
  • 返回值:

    • 成功时返回终止的子进程的PID。
    • 如果没有子进程,返回-1,并设置 errnoECHILD

2.4 waitpid() 系统调用

waitpid() 提供了比 wait() 更灵活的控制,允许父进程等待特定的子进程,并且可以指定是否阻塞。

#include <sys/types.h>
#include <sys/wait.h>pid_t waitpid(pid_t pid, int *status, int options);
  • 参数:

    • pid: 指定要等待的子进程的PID。
      • pid > 0: 等待进程ID等于 pid 的子进程。
      • pid = -1: 等待任意子进程,与 wait() 类似。
      • pid = 0: 等待与调用进程属于同一个进程组的任意子进程。
      • pid < -1: 等待进程组ID等于 pid 绝对值的任意子进程。
    • status: 与 wait() 中的 status 参数相同,用于存储子进程的退出状态。
    • options: 控制 waitpid() 的行为,常用的选项有:
      • WNOHANG: 如果没有子进程退出,立即返回,不阻塞。
      • WUNTRACED: 如果子进程被暂停(例如通过 SIGSTOP 信号),也返回。
  • 返回值:

    • 成功时返回终止的子进程的PID。
    • 如果指定了 WNOHANG 且没有子进程退出,返回0。
    • 如果出错,返回-1,并设置 errno

2.5 示例代码

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>int main() {pid_t pid = fork();if (pid < 0) {perror("fork failed");exit(1);} else if (pid == 0) {// 子进程printf("Child process is running\n");sleep(2);printf("Child process is exiting\n");exit(42);} else {// 父进程int status;printf("Parent process is waiting for child\n");wait(&status);if (WIFEXITED(status)) {printf("Child exited with status %d\n", WEXITSTATUS(status));} else {printf("Child did not exit normally\n");}}return 0;
}

3、进程程序替换

在Linux中,进程程序替换是指将一个进程当前执行的程序替换为另一个全新的程序。这个过程是通过 exec 系列函数来实现的。进程程序替换后,进程的PID、父进程、文件描述符等信息保持不变,但进程的代码段、数据段、堆栈等会被新程序的内容替换。

exec 系列函数是Linux系统调用的一部分,它们的作用是加载并执行一个新的程序,替换当前进程的地址空间。执行成功后,原程序的代码将不再运行,而是由新程序从头开始执行。


3.1 exec 系列函数

exec 系列函数有多个变体,它们的核心功能相同,但在参数传递方式和行为上略有不同。exec系列函数只有失败返回值(-1),没有成功返回值

以下是常用的 exec 函数:

3.1.1 execl()
int execl(const char *path, const char *arg, ..., (char *) NULL);
  • 功能: 加载并执行指定路径的程序。

  • 参数:

    • path: 要执行的程序的完整路径。
    • arg: 程序的命令行参数,第一个参数通常是程序名,最后一个参数必须是 NULL
  • 示例:

    execl("/bin/ls", "ls", "-l", NULL);
    

    这行代码会执行 /bin/ls 程序,并传递 -l 参数。


3.1.2 execlp()
int execlp(const char *file, const char *arg, ..., (char *) NULL);
  • 功能: 类似于 execl(),但会在 PATH 环境变量中查找可执行文件。
  • 参数:
    • file: 要执行的程序名(不需要完整路径)。
    • arg: 程序的命令行参数,最后一个参数必须是 NULL
  • 示例:
    execlp("ls", "ls", "-l", NULL);
    
    这行代码会在 PATH 中查找 ls 并执行。

3.1.3 execle()
int execle(const char *path, const char *arg, ..., (char *) NULL, char *const envp[]);
  • 功能: 加载并执行指定路径的程序,并允许指定环境变量。
  • 参数:
    • path: 要执行的程序的完整路径。
    • arg: 程序的命令行参数,最后一个参数必须是 NULL
    • envp: 自定义的环境变量数组,必须以 NULL 结尾。
  • 示例:
    char *envp[] = {"USER=test", "PATH=/bin", NULL};
    execle("/bin/ls", "ls", "-l", NULL, envp);
    

3.1.4 execv()
int execv(const char *path, char *const argv[]);
  • 功能: 加载并执行指定路径的程序,参数通过数组传递。
  • 参数:
    • path: 要执行的程序的完整路径。
    • argv: 命令行参数数组,必须以 NULL 结尾。
  • 示例:
    char *argv[] = {"ls", "-l", NULL};
    execv("/bin/ls", argv);
    

3.1.5 execvp()
int execvp(const char *file, char *const argv[]);
  • 功能: 类似于 execv(),但会在 PATH 环境变量中查找可执行文件。
  • 参数:
    • file: 要执行的程序名(不需要完整路径)。
    • argv: 命令行参数数组,必须以 NULL 结尾。
  • 示例:
    char *argv[] = {"ls", "-l", NULL};
    execvp("ls", argv);
    

3.1.6 execvpe()
int execvpe(const char *file, char *const argv[], char *const envp[]);
  • 功能: 类似于 execvp(),但允许指定环境变量。
  • 参数:
    • file: 要执行的程序名(不需要完整路径)。
    • argv: 命令行参数数组,必须以 NULL 结尾。
    • envp: 自定义的环境变量数组,必须以 NULL 结尾。
  • 示例:
    char *argv[] = {"ls", "-l", NULL};
    char *envp[] = {"USER=test", "PATH=/bin", NULL};
    execvpe("ls", argv, envp);
    

3.2 exec 系列函数的特点

  1. 替换当前进程:

    • exec 系列函数会用新程序替换当前进程的地址空间,包括代码段、数据段、堆栈等。
    • 进程的PID、父进程、文件描述符等信息保持不变。
  2. 不创建新进程:

    • exec 不会创建新进程,它只是替换当前进程的内容。
  3. 成功时不返回:

    • 如果 exec 执行成功,它不会返回,因为原程序的代码已经被替换。
    • 如果 exec 失败,它会返回 -1,并设置 errno
  4. 文件描述符的继承:

    • 默认情况下,exec 会保留进程打开的文件描述符(除非显式设置 FD_CLOEXEC 标志)。

3.3 示例代码

  • 实例1:

​ 以下是一个完整的示例,展示如何使用 fork()exec() 创建子进程并替换程序:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>int main() {pid_t pid = fork();if (pid < 0) {perror("fork failed");exit(1);} else if (pid == 0) // 子进程{printf("子进程正在执行\n");// 替换为 ls 程序char *argv[] = {"ls", "-l", NULL};execvp("ls", argv);//如果进程替换成功,则下面的代码不会执行,如果进程替换失败(例如命令错误、路径错误等原因导致错误),则会执行下面的语句perror("hello world\n");exit(1);} else // 父进程{int status;wait(&status); // 等待子进程结束printf("父进程检测到子进程退出\n");}return 0;
}

程序运行结果:
在这里插入图片描述

  • 实例2:

    test1.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <sys/types.h>int main() {pid_t pid = fork();if (pid < 0) {perror("fork failed");exit(1);}   else if (pid == 0) // 子进程{   printf("子进程正在执行\n");// 替换为 ls 程序//char *argv[] = {"ls", "-l", NULL};//execvp("ls", argv);//execl("/usr/bin/ls","/usr/bin/ls","-ln","-a",NULL);execl("./test2","test2",NULL);//如果进程替换成功,则下面的代码不会执行perror("hello world\n");exit(1);}   else // 父进程{   int status;wait(&status); // 等待子进程结束printf("父进程检测到子进程退出\n");}   return 0;
}

test2.c

#include<stdio.h>int main(){printf("这是test2\n");return 0;
}

将test1.c编译成可执行文件后,执行结果如下:

在这里插入图片描述

相关文章:

Linux | 进程控制(进程终止与进程等待)

文章目录 Linux | 进程控制 — 进程终止 & 进程等待1、进程终止进程常见退出方法1.1退出码基本概念获取退出码的方式常见退出码约定使用场景 1.2 strerror函数 & errno宏1.3 _exit函数1.4_exit和exit的区别1.4.1 所属头文件与函数原型1.4.2 执行过程差异**结合现象分析…...

三、tsp学习笔记——屏幕移植

泰山派-6寸猫屏转接板 - 立创开源硬件平台 泰山派樱猫的教程&#xff0c;屏资料链接: https://pan.baidu.com/s/1pNAKH33r7LtZG6EwHJ-HNA?pwdnsde 提取码: nsde &#xff08;不要浪费时间下载&#xff0c;没有用&#xff0c;下载gitee上的&#xff09; leefei/tspi-disp-6…...

python全栈-python进阶

python进阶 文章目录 python进阶异常except自定义异常类 文件操作序列化和反序列化CSV文件os模块os.path模块shutil模块 拷贝压缩 模块--modulefrom 模块 import 成员包package库LibraryPIP库 GUI编程-tkinter版使用类定义的GUI界面设置控件的属性方式Label标签的常用属性Butto…...

SpringBoot如何配置开发环境(JDK、Maven、IDEA等)

目录 1. 安装JDK 一、JDK介绍JRE&#xff08;Java Runtime Envirnment&#xff09;&#xff1a;Java运行环境 二、下载JDK官网地址&#xff1a;Java Downloads | Oracle 三、安装JDK点击下载下来的安装包进行安装 四、配置JDK进入到环境变量中&#xff08;下面介绍两种进入…...

图片粘贴上传实现

图片上传 html demo 直接粘贴本地运行查看效果即可&#xff0c;有看不懂的直接喂给 deepseek 会解释的很清晰 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"…...

C++--STL库-List

目录 1.list 的基本使用 1.1 创建和初始化 1.2. 插入元素 1.3. 删除元素 1.4. 访问元素 1.5 遍历 1.6 总结 list是C标准库&#xff08;STL&#xff09;中的双向链表容器&#xff0c;属于<list>头文件。 它的特点是&#xff1a; 动态大小&#xff1a;可以随时插入…...

kubeadm拉起的k8s集群证书过期的做法集群已奔溃也可以解决

kubeadm拉起的k8s集群证书过期的做法 这个是很久之前遇到的了&#xff0c;今天有空&#xff08;心血来潮&#xff09;就都回忆回忆写在这里为爱发光&#xff0c;部分内容来自arch先生&#xff08;死党&#xff09;的帮助。有时候有很多部门提了建k8s的需求&#xff0c;有些是临…...

idea连接gitee(使用idea远程兼容gitee)

文章目录 先登录你的gitee拿到你的邮箱找到idea的设置选择密码方式登录填写你的邮箱和密码登录成功 先登录你的gitee拿到你的邮箱 具体位置在gitee–>设置–>邮箱管理 找到idea的设置 选择密码方式登录 填写你的邮箱和密码 登录成功...

Kafka 简介

Kafka 简介 Apache Kafka 是一个开源的分布式流处理平台&#xff0c;广泛应用于实时数据流处理、日志管理、消息传递等场景。Kafka 最初由 LinkedIn 开发&#xff0c;并于 2011 年捐献给 Apache 软件基金会。 Kafka 的设计目标是高吞吐量、低延迟和高可用性&#xff0c;它能够…...

Ubuntu22.04 Deepseek-R1本地容器化部署/内网穿透/OPENWEBUI,打造个人AI助手!

1. 前言 本地部署DeepSeek并实现内网穿透&#xff0c;为家庭成员提供强大的AI支持。通过使用Ollama、Docker、OpenWebUI和Nginx&#xff0c;内网穿透&#xff0c;我们可以轻松实现快速响应和实时搜索功能。 2.软硬件环境 系统&#xff1a;ubuntu22.04, cuda12GPU: RTX3080Ti …...

红蓝对抗之常见网络安全事件研判、了解网络安全设备、Webshell入侵检测

文章目录 ​​研判&#xff08;入侵检测&#xff09;​​ ​​设备​​ ​​经典网络​​​​云网络​​ ​​异常HTTP请求​​​​Webshell分析​​ ​​Webshell 的分类​​​​Webshell 的检测​​ ​​主机层面​​​​流量层面​​ ​​附录​​ ​​常见端口漏洞…...

Linux部署DeepSeek r1 模型训练

之前写过一篇windows下部署deepseekR1的文章&#xff0c;有小伙伴反馈提供一篇linux下部署DeepSeek r1 模型训练教程&#xff0c;在 Linux 环境下&#xff0c;我找了足够的相关资料&#xff0c;花费了一些时间&#xff0c;我成功部署了 DeepSeek R1 模型训练任务&#xff0c;结…...

【大模型】DeepSeek:AI浪潮中的破局者

【大模型】DeepSeek&#xff1a;AI浪潮中的破局者 引言&#xff1a;AI 新时代的弄潮儿DeepSeek&#xff1a;横空出世展锋芒&#xff08;一&#xff09;诞生背景与发展历程&#xff08;二&#xff09;全球影响力初显 探秘 DeepSeek 的技术内核&#xff08;一&#xff09;独特的模…...

寒假学习总结

整个寒假都走在数据结构与算法的路上&#xff0c;深入学习了其中多个板块&#xff0c;刷了一些与之对应的题目&#xff0c;下面来一期总结&#xff08;c&#xff09; &#xff08;emmm&#xff0c;主播在寒假试着去学习了几大语言的语法基础&#xff08;丢丢&#xff09; 如Ja…...

自愈网络的定义、其为用户带来的益处、具体的使用案例

在当今高度互联的世界中&#xff0c;网络稳定性和可靠性对于各种应用场景至关重要。无论是企业的日常运营、智能家居的便捷控制&#xff0c;还是工业网络的自动化管理&#xff0c;网络的任何中断都可能带来不可估量的损失和不便。正是基于这种需求&#xff0c;以太联—Intellin…...

NumPy的基本使用

在 Python 的数据科学与数值计算领域&#xff0c;NumPy 无疑是一颗耀眼的明星。作为 Python 中用于科学计算的基础库&#xff0c;NumPy 提供了高效的多维数组对象以及处理这些数组的各种工具。本文将带您深入了解 NumPy 的基本使用&#xff0c;感受它的强大魅力。 一、安装与导…...

HTTP 与 HTTPS:协议详解与对比

文章目录 概要 一. HTTP 协议 1.1 概述 1.2 工作原理 1.3 请求方法 1.4 状态码 二. HTTPS 协议 2.1 概述 2.2 工作原理 2.3 SSL/TLS 协议 2.4 证书 三. HTTP 与 HTTPS 的区别 四. 应用场景 4.1 HTTP 的应用场景 4.2 HTTPS 的应用场景 概要 HTTP&#xff08;Hy…...

从零开始构建一个语言模型中vocab_size(词汇表大小)的设定规则

从零开始构建一个语言模型就要设计一个模型框架,其中要配置很多参数。在自然语言处理任务中,vocab_size(词汇表大小) 的设定是模型设计的关键参数之一,它直接影响模型的输入输出结构、计算效率和内存消耗。 本文是在我前文的基础上讲解的:从零开始构建一个小型字符级语言…...

斐波那契数列模型:在动态规划的丝绸之路上追寻斐波那契的足迹(上)

文章目录 引言递归与动态规划的对比递归解法的初探动态规划的优雅与高效自顶向下的记忆化搜索自底向上的迭代法 性能分析与比较小结 引言 斐波那契数列&#xff0c;这一数列如同一条无形的丝线&#xff0c;穿越千年时光&#xff0c;悄然延续其魅力。其定义简单而优美&#xff…...

RT-Thread+STM32L475VET6——ADC采集电压

文章目录 前言一、板载资源二、具体步骤1.打开CubeMX进行配置1.1 使用外部高速时钟&#xff0c;并修改时钟树1.2 打开ADC1的通道3&#xff0c;并配置为连续采集模式(ADC根据自己需求调整&#xff09;1.3 打开串口1.4 生成工程 2. 配置ADC2.1 打开ADC驱动2.2 声明ADC2.3 剪切stm…...

基于Django快递物流管理可视化分析系统(完整系统源码+数据库+详细开发文档+万字详细论文+答辩PPT+详细部署教程等资料)

文章目录 基于Django快递物流管理可视化分析系统&#xff08;完整系统源码数据库详细开发文档万字详细论文答辩PPT详细部署教程等资料&#xff09;一、项目概述二、项目说明三、研究意义四、系统设计技术架构 五、功能实现六、完整系统源码数据库详细开发文档万字详细论文答辩P…...

【Pandas】pandas Series reindex_like

Pandas2.2 Series Computations descriptive stats 方法描述Series.align(other[, join, axis, level, …])用于将两个 Series 对齐&#xff0c;使其具有相同的索引Series.case_when(caselist)用于根据条件列表对 Series 中的元素进行条件判断并返回相应的值Series.drop([lab…...

Ollama安装和迁移,以及部署DeepSeek模型

什么是 Ollama Ollama 是大语言模型管理工具,它的主要作用是简化大语言模型的本地化部署和运行。如果你想调用本地模型,保护个人隐私,构建个人知识库,那你可以考虑使用 Ollama。 Ollama 的官网是 https://ollama.com/,正如官网所说,“Get up and running with large l…...

【数据挖掘】

数据挖掘 目录&#xff1a;1. 数据转换2. 属性选择3. 独立于方案的选择4. 探索空间5. 具体方案的选择6. 离散化数值属性无监督离散化基于熵的离散化其他离散化方法 k-means算法原理算法步骤优缺点优点缺点 代码示例&#xff08;使用Python和scikit-learn库&#xff09;代码解释…...

芝加哥学派(Chicago School):金融与经济学的创新力量(中英双语)

芝加哥学派&#xff1a;金融与经济学的创新力量 在经济学和金融学的历史上&#xff0c;有一个学派的影响力不容忽视&#xff0c;那就是芝加哥学派&#xff08;Chicago School&#xff09;。芝加哥学派不仅在学术界广受推崇&#xff0c;也深刻影响了全球的经济政策和金融市场。…...

web入侵实战分析-常见web攻击类应急处置实验1

场景说明&#xff1a; 某天运维人员发现在/opt/tomcat8/webapps/test/目录下&#xff0c;多出了一个index_bak.jsp这个文件&#xff0c; 并告诉你如下信息 操作系统&#xff1a;ubuntu-16.04业务&#xff1a;测试站点中间件&#xff1a;tomcat开放端口&#xff1a;22&#x…...

.NET SixLabors.ImageSharp v1.0 图像实用程序控制台示例

使用 C# 控制台应用程序示例在 Windows、Linux 和 MacOS 机器上处理图像&#xff0c;包括创建散点图和直方图&#xff0c;以及根据需要旋转图像以便正确显示。 这个小型实用程序库需要将 NuGet SixLabors.ImageSharp包&#xff08;版本 1.0.4&#xff09;添加到.NET Core 3.1/ …...

基于ffmpeg+openGL ES实现的视频编辑工具-字幕添加(六)

在视频编辑领域,字幕的添加是一项极为重要的功能,它能够极大地丰富视频内容,提升观众的观看体验。当我们深入探究如何实现这一功能时,FreeType 开源库成为了强大助力。本文将详细阐述借助 FreeType 库生成字幕数据的过程,以及如何实现字幕的缩放、移动、旋转、颜色修改、对…...

SpringMVC新版本踩坑[已解决]

问题&#xff1a; 在使用最新版本springMVC做项目部署时&#xff0c;浏览器反复500&#xff0c;如下图&#xff1a; 异常描述&#xff1a; 类型异常报告 消息Request processing failed: java.lang.IllegalArgumentException: Name for argument of type [int] not specifie…...

【科研绘图系列】R语言绘制SCI论文图合集

禁止商业或二改转载&#xff0c;仅供自学使用&#xff0c;侵权必究&#xff0c;如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载Load dataFigure 1Fig 1B: functional assays adhensionFIG 1C: Functional assays OPK Figure 2Fig 2C: Settings and function fo…...

间隔连续问题

间隔连续问题 1. 数据结构&#xff1a;某游戏公司记录的用户每日登录数据 表名&#xff1a;game_user 字段名&#xff1a;id&#xff08;用户id&#xff09;、dt&#xff08;日期&#xff09; 2. 需求&#xff1a; ① 创建表 ② 计算每个用户最大的连续登录天数&#xff0c…...

3月营销日历:开启春日盛宴,绽放生活魅力

关键营销节点∶惊蛰、女生节、妇女节、 植树节、315消费者权益日、春分 营销关键词 养生、女生魅力、感恩女性、环保、品质 01.重点关注品类 春季服饰&#xff1a;如轻薄外套、春装等&#xff0c;适合惊蛰后的市场需求&#xff1b; 美妆护肤&#xff1a;妇女节期间&#xf…...

网络工程师 (48)传输层概述

前言 传输层&#xff08;Transport Layer&#xff09;是计算机网络体系结构中的关键层次之一&#xff0c;主要负责在源端和目的端之间提供端到端的数据传输服务。 一、位置与功能 传输层位于OSI&#xff08;开放系统互连&#xff09;参考模型的第四层&#xff0c;介于网络层和应…...

字符串函数和结构题内存对齐

图下为函数使用&#xff1a; #include <ctype.h>int main() {int ret isdigit(Q);printf("%d\n", ret);return 0; }int main() {printf("%c\n", toupper(a));printf("%c\n", tolower(A));return 0; }...

同花顺C++面试题及参考答案

对 C 和 C++ 哪个更熟悉? 在编程语言的学习与实践中,我对 C++ 更为熟悉。C 语言作为一门经典的编程语言,以其高效、灵活和接近硬件的特性,在系统编程、嵌入式开发等领域占据着重要地位。它提供了丰富的底层操作能力,如指针操作、内存管理等,为开发者直接控制计算机资源提…...

Python JSON的深度解析:从基础到应用

Python JSON的深度解析&#xff1a;从基础到应用 flyfish 什么是JSON&#xff1f; JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式。它基于一个子集的JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999…...

创建三个节点

1. 节点克隆 根据教程Hadoop编译安装-CSDN博客将一台机器的hadoop的环境搭建好。 在虚拟机的列表中选中一台机器&#xff0c;右键—>管理—>克隆 填好【虚拟机名称】&#xff0c;选择本地存储位置&#xff0c;点击完成&#xff0c;就节点克隆完成了。 2. 修改IP地址 编…...

滤波器 | 原理 / 分类 / 特征指标 / 设计

注&#xff1a;本文为 “滤波器” 相关文章合辑。 未整理去重。 浅谈滤波器之 —— 啥是滤波器 原创 RF 小木匠 射频学堂 2020 年 03 月 25 日 07:46 滤波器&#xff0c;顾名思义&#xff0c;就是对信号进行选择性过滤&#xff0c;对不需要的信号进行有效滤除。按照其传输信…...

Flutter - 初体验

项目文件目录结构介绍 注&#xff1a;创建 Flutter 项目名称不要包含特殊字符&#xff0c;不要使用驼峰标识 // TODO 开发中运行一个 Flutter 三种启动方式 Run 冷启动从零开始启动Hot Reload 热重载执行 build 方法Hot Restart 热重启重新运行整个 APP 先看效果&#xff0c…...

OSPF(开放路径最短优先)

ospf优先级&#xff1a;内部优先级默认为10&#xff0c;外部优先级默认为150 1.ospf的三张表 &#xff08;1&#xff09;邻居表 <记录邻居状态和关系> &#xff08;2&#xff09;拓扑表 <链路状态数据库> &#xff08;3&#xff09;路由表 <对链路状态数据库进…...

SpringBoot 排除一些包的注入

文章目录 需求一、使用 ComponentScan 需求 在系统迭代的过程中&#xff0c;有一些 Controller 大批量的不再使用&#xff0c;或者有一些接口我们不想再提供给外界 一、使用 ComponentScan SpringBootApplication(scanBasePackages "com.zrb.excludeSomePkg") Comp…...

【Python爬虫(21)】从0到1:Python与MySQL的深度融合

【Python爬虫】专栏简介&#xff1a;本专栏是 Python 爬虫领域的集大成之作&#xff0c;共 100 章节。从 Python 基础语法、爬虫入门知识讲起&#xff0c;深入探讨反爬虫、多线程、分布式等进阶技术。以大量实例为支撑&#xff0c;覆盖网页、图片、音频等各类数据爬取&#xff…...

数据结构-----双向链表

一、双向循环列表 head.h #ifndef __head_h__ #define __head_h__ #include <stdio.h> #include <string.h>…...

idea 无法下载源码

作为一个程序猿&#xff0c;难免会跟源码打交道&#xff0c;可是在下载源码有时候&#xff0c;会提示找不到对象&#xff0c;这是什么原因呢&#xff1f;今天我们来解决这个问题。 问题&#xff1a;idea无法下载源码 Cannot download sources Sources not found for:org.sprin…...

计算机网络-OSI七层参考模型与数据封装,网络安全零基础入门到精通实战教程!

目录 一、网络 1、网络的定义 2、网络的分类 3、网络的作用 4、网络的数据传输方式 5、网络的数据通讯方式 二、OSI七层参考模型 1、网络参考模型定义 2、分层的意义 3、分层与功能 4、TCP\IP五层模型 三、参考模型的协议 1、物理层 2、数据链路层 3、网络层 4…...

洛谷 P2234 [HNOI2002] 营业额统计(详解)c++

题目链接&#xff1a;P2234 [HNOI2002] 营业额统计 - 洛谷 1.题目分析 输入输出样例&#xff1a;根据题目知第一天的最小波动值为第一天的营业额&#xff0c;所以第一天的最小波动值是5&#xff0c;算出第二天的最小波动值就说拿前面的数分别减当前的数&#xff0c;并且取一个…...

Go日期时间处理工具Carbon

**注意&#xff1a;**本文大部分内容摘抄自-https://github.com/dromara/carbon/blob/master/README.cn.md使用文档 一、简介 一个轻量级的、易于使用的、语义智能的日期时间处理库&#xff0c;支持链式调用&#xff0c;已被 awesome-go 收录&#xff0c;现已经捐赠给了 drom…...

【Bert】自然语言(Language Model)入门之---Bert

every blog every motto: Although the world is full of suffering&#xff0c; it is full also of the overcoming of it 0. 前言 对bert进行梳理 论文&#xff1a; BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding 时间&#xff1a;…...

鸿蒙NEXT开发-网络管理

注意&#xff1a;博主有个鸿蒙专栏&#xff0c;里面从上到下有关于鸿蒙next的教学文档&#xff0c;大家感兴趣可以学习下 如果大家觉得博主文章写的好的话&#xff0c;可以点下关注&#xff0c;博主会一直更新鸿蒙next相关知识 目录 1. 网络管理-应用权限 1.1 概述 1.2 配…...

ceph HEALTH_WARN clock skew detected on mon.f, mon.o, mon.p, mon.q

问题 ceph health detail[WRN] MON_CLOCK_SKEW: clock skew detected on mon.f, mon.o, mon.p, mon.qmon.f clock skew 0.243128s > max 0.05s (latency 0.000836159s)mon.o clock skew 16.249s > max 0.05s (latency 0<...