Linux:进程控制
1.fork()函数初识
在linux中fork函数时非常重要的函数,它从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。
#include <unistd.h>
pid_t fork(void);
返回值:自进程中返回0,父进程返回子进程id,出错返回-1
进程调用fork,当控制转移到内核中的fork代码后,内核将:
---分配新的内存块(4GB大小地址空间)和内核数据结构(包括pcb...)给子进程
---将父进程部分数据结构内容拷贝至子进程(子进程继承父进程的环境变量等内容)
---添加子进程到系统进程列表当中(添加pcb...)
---fork返回,开始调度器调度
fork()的常规用法
---一个父进程希望复制自己,使父子进程同时执行不同的代码段。例如,父进程等待客户端请求,生成子进程来处理请求。
---一个进程要执行一个不同的程序。例如子进程从fork返回后,调用exec函数。
fork()调用失败的原因
---系统中有太多的进程
---实际用户的进程数超过了限制
2.进程终止
2.1进程退出码
echo $?:永远记录最近一个进程在命令行中执行完毕时对应的退出码(?变量名,$?取变量名)
strerror:通过标准错误的标号,获得错误的描述字符串 ,将单纯的错误标号转为字符串描述,方便用户查找错误。
#include<stdio.h>
#include<string.h>
int add(int from,int to)
{int sum = 0;for(int i=from;i<to;i++){sum+=i;}return sum;
}
int main()
{//写代码是为了完成某件事情,我如何得知我的任务完成的如何?---进程退出码for(int i = 0;i<200;i++){//打印0-200每返回的数值的情况printf("%d:%s\n",i,strerror(i));}
}
//一般而言,退出码,都必须有对应的退出码的文字描述。自定义/使用系统的映射关系
//退出码的意义:0success !0对应失败的每一种原因
2.2进程退出的情况
1.代码执行完毕,结果正确。 ——return 0;
2.代码执行完毕,结果不正确。 ——return !0;//退出码在这个时候起作用查找原因
3.代码没执行完,程序异常,退出码无意义。//除零、野指针、越界...
2.3进程如何退出?
1.从main函数返回。(其它函数返回只是函数调用结束)
2.exit(退出码)结束进程,return 退出码;程序退出。任意地方调用exit程序都会终止。
3._exit() ,终止进程,不会刷新缓冲区;exit在终止进程时,会主动刷新缓冲区。
缓冲区在哪里?
exit在操作系统上的系统调用层,exit在最上层的库函数层;exit调用的时_exit,但是能刷新缓冲区,用户级缓冲区......
#include <unistd.h>
void exit(int status);//库函数--C语言提供的,在系统调用接口之上。#include <unistd.h>
void _exit(int status);//系统调用--操作系统提供的
参数:status 定义了进程的终止状态,父进程通过wait来获取该值
3.进程等待
当子进程退出时,父进程如果不管不顾,就可能造成僵尸进程的问题,造成内存泄露。当进程一旦变成僵尸状态,就会杀不死,kill -9也不能杀死,因为系统或用户无法杀死一个已经死去的进程。并且,父进程派给子进程的任务完成的如何,我们也需要知道(子进程运行完成是否正常退出,退出码)。父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息。
#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int*status);
返回值:成功返回被等待进程pid,失败返回-1。
参数:输出型参数,获取子进程退出状态,不关心则可以设置成为NULL
pid_ t waitpid(pid_t pid, int *status, int options);
返回值:当正常返回的时候waitpid返回收集到的子进程的进程ID;
如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;
参数:
pid:
Pid=-1,等待任一个子进程。与wait等效。
Pid>0.等待其进程ID与pid相等的子进程。
status:
WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)
options:
WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进程的ID。
3.1利用wait()回收子进程资源 ---阻塞等待


int main()
{pid_t id = fork();if(id == 0){//子进程int cnt = 10;while(cnt){printf("我是子进程:%d,父进程:%d,cnt:%d\n",getpid(),getppid(),cnt--);sleep(1);}exit(0);}//父进程sleep(15);pid_t ret = wait(NULL);if(id > 0){printf("wait success:%d\n",ret);}sleep(5);
}
3.2 利用waitpid(id,status,0)获取子进程退出信息---阻塞等待
---程序正常终止,终止信号为0,退出状态为exit返回的退出码10:
pid_t id = fork();if(id == 0){//子进程int cnt = 5;while(cnt){printf("我是子进程:%d,父进程:%d,cnt:%d\n",getpid(),getppid(),cnt--);sleep(1);}exit(10);//程序正常执行完毕,返回退出码10}//父进程int status = 0;//不是被整体使用,有自己的位图结构pid_t ret = waitpid(id,&status,0);if(id > 0){printf("wait success:%d,sig number:%d,child exit code:%d\n",ret,(status & 0x7F),(status>>8) & 0xFF);}sleep(5);
---程序异常终止,被信号所杀,返回终止信号,kill -l可查明终止信号对应的原因。
pid_t id = fork();if(id == 0){//子进程int cnt = 5;while(cnt){printf("我是子进程:%d,父进程:%d,cnt:%d\n",getpid(),getppid(),cnt--);sleep(1);}int a = 3/0;//当子进程发生除零错误exit(10);}
---使用系统提供的宏通过拿到的进程的status来检测进程是否正常退出,以及退出的状态。
int status = 0;//不是被整体使用,有自己的位图结构pid_t ret = waitpid(id,&status,0);if(id > 0){//先检查是否是正常退出if(WIFEXITED(status)){//判断子进程运行结果是否Ok--退出码printf("exit code:%d\n",WEXITSTATUS(status));}else printf("child exit not normal!\n"); }return 0;
WIFEXITED(status): 若为正常终止子进程返回的状态,则为真(查看进程是否是正常退出);
WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码(查看进程的退出码)
当子进程正在运行时,使用kill -9杀死属于异常终止,不会返回退出码。
3.3非阻塞等待--轮询机制
pid_ t waitpid(pid_t pid, int *status, int options);当options不是0,设置成就是非阻塞等待。当返回值-1(出错),==0(子进程没有退出还在运行),>0(子进程退出返回id)的三种情况;几次非阻塞等待不一定子进程退出,所以使用轮询非阻塞等待,直到访问到子进程退出再结束非阻塞等待的检测。
pid_t id = fork();if(id == 0){//子进程int cnt = 3;//运行三秒while(cnt){printf("我是子进程:%d,父进程:%d,cnt:%d\n",getpid(),getppid(),cnt--);sleep(1);}exit(10);}//父进程int status = 0;while(1){pid_t ret = waitpid(id,&status,WNOHANG);//WNOHANG:非阻塞等待sleep(1);if(ret == 0) printf("wait done,but child is running...\n");else if(ret>0){printf("wait success:%d,sig number:%d,child exit code:%d\n",ret,(status & 0x7F),(status>>8) & 0xFF);break;}else {printf("error!");break;}}return 0;
非阻塞等待时不会占用父进程的所有时间,可以在轮询期间做其它的事情。例:在每次问询子进程还在运行时,可以调用别的函数任务。
进程等待是什么?为什么?怎么办?
进程等待是当子进程运行结束会释放代码和数据,但是pcb保存退出信息等不会回收,需要父进程去回收,一是避免子进程变成僵尸进程造成内存泄露,二是父进程需要拿到子进程得退出信息知道子进程是否正常结束退出码退出状态。父进程可以使用阻塞等待或者非阻塞等待两种方式进行回收。wait是等待任意一个子进程结束就可以进行回收,waitpid传入特定的Id等待特定的进程,同时waitpid的参数options可以使其选择是阻塞等待还是非阻塞等待。
4.进程程序替换
1.创建子进程的目的?
---想让子进程执行父进程代码的一部分。(执行父进程对应的磁盘代码中的一部分)
---想让子进程执行一个全新的程序。(让子进程想办法加载磁盘上指定的程序,执行新程序的代码/数据)->进程的程序替换。
2.快速搭建--写一个简易的代码
--execl替换本进程
--fork创建子进程excel替换子进程
#include <unistd.h>
int main()
{char *const argv[] = {"ps", "-ef", NULL};char *const envp[] = {"PATH=/bin:/usr/bin", "TERM=console", NULL};execl("/bin/ps", "ps", "-ef", NULL);// 带p的,可以使用环境变量PATH,无需写全路径execlp("ps", "ps", "-ef", NULL);// 带e的,需要自己组装环境变量execle("ps", "ps", "-ef", NULL, envp);execv("/bin/ps", argv);// 带p的,可以使用环境变量PATH,无需写全路径execvp("ps", argv);// 带e的,需要自己组装环境变量execve("/bin/ps", argv, envp);exit(0);
}
子进程被创建时有了自己的虚拟地址空间和页表,对应指向父进程的物理内存中的代码和数据;但当子进程发生进程程序替换时,会进行写时拷贝,将它原来指向父进程的代码数据拷贝到其它物理内存然后将这些代码数据替换掉,也就是子进程如果原来要执行父进程的一部分现在也不会再执行,程序和代码都被替换成了新的,但都不会影响到父进程。
3.理解原理
程序替换的本质,就是将指定的程序的代码和数据加载到指定的位置!覆盖自己的代码和数据。进程替换的时候,并没有创建新的进程,只是将指定程序的代码数据加载进内存物理地址。在调用execl之后的代码就无法执行了,因为已经被新的代码数据替换了。当execl调用失败时,不会替换成功,就会向后继续执行剩余的代码。一般用perror打印错误,exit终止程序。
4.分别实现对应调用的方式
#include <unistd.h>`
//exec*加载器,exec将程序加载到内存中,程序替换中execve系统调用,其他的都是封装,为了便于使用
int execl(const char *path, const char *arg, ...);//l:list,将参数一个一个传入
int execlp(const char *file, const char *arg, ...);//p:path,如何找到程序的功能,只需要知道文件名函数就可以自己在环境变量中找,疑问?只能在已有的路径下查找吗?
int execle(const char *path, const char *arg, ...,char *const envp[]);//e:环境变量,传入自定义环境变量
int execv(const char *path, char *const argv[]);//v:vector,可以将所有的执行参数,放入数组中,统一传递,而不用进行使用可变参数方案
int execvp(const char *file, char *const argv[]);//v,p
//出错返回-1,成功时没有返回值。不需要,调用成功时,它的返回值也不会被原代码拿上了。
5.应用场景
---1.进程程序替换当前进程
---2.进程程序替换子进程
---3.调用自定义的可执行程序替换
Makefile怎么同时形成多个可执行文件(默认只形成一个且是第一个)
调用系统指令/程序
调用我们自己写的可执行程序。(可以调用其它后端语言:C++/C/python/shell)
printf("processing is running...\n");pid_t id = fork();assert(id != 1);if(id == 0)//子进程{ sleep(1);//自定义环境变量char *const envp[] = {(char*)"MYENV = bfrbfrbfr",NULL};extern char **environ;putenv((char*)"MYENV = bfrbfrbfr");//将指定的环境变量导入到系>统中execle("./mybin","mybin",NULL,environ);exit(1);//must failed}int status = 0;pid_t ret = waitpid(id,&status,0);if(ret>0) printf("wait success:%d,sig number:%d,child exit code:%d\n",ret,(status & 0x7F),(status>>8) & 0xFF);return 0;
6.补充
先执行execl函数还是main()函数? --先用execl函数调用加载器exec*将程序加载进内存,给main函数传参,开始调用main函数。
为什么execl系列函数就算不传参数,子进程也能拿到默认的环境变量---通过初始化过的虚拟地址空间中的命令行参数环境变量区域拿到的,必要时也会将它传递给main函数。
5.实现一个shell命令行
实现一个我们自己的shell(有命令行、能输入指令、回车调用指令输出结果)
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<ctype.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/wait.h>
#include<assert.h>
#include<errno.h>
#define NUM 1024
#define OPT_NUM 64
#define NONE_REDIR 0 //没有重定向
#define OUTPUT_REDIR 1 //输出重定向
#define INPUT_REDIR 2 //输入重定向
#define APPEND_REDIR 3 //追加重定向
#define trimSpace(start) do{\while(isspace(*start)) ++start;\
}while(0)char lineCommand[NUM];
char *myargv[OPT_NUM];//指针数组,存储的是命令和选项部分
int lastCode = 0;
int lastSig = 0;
int redirType = NONE_REDIR;//重定向码初始化为零
char *redirFile = NULL;//重定向文件初始化为空void commandCheck(char *commands)
{assert(commands);//断言不为空char *start = commands;//指向命令行char *end = commands + strlen(commands);//使其指向命令行末尾while(start<end)//遍历查找是否指令存在重定向{if(*start == '>'){*start = '\0';//分割前面的指令部分start++;if(*start == '>')//判断是不是>>{redirType = APPEND_REDIR;//标注为追加重定向start++;//指向下一个字符}else{redirType = OUTPUT_REDIR;//标注为输出重定向}trimSpace(start);//跳过空格使start指向文件redirFile = start;//使文件指针指向当前break;}else if(*start == '<'){//"cat < file.txt"*start = '\0';start++;trimSpace(start);redirType = INPUT_REDIR;redirFile = start;break;}else{start++;}}
}
int main()
{while(1)//命令行输入的循环{int redirType = NONE_REDIR;//重定向码初始化为零redirFile = NULL;//重定向文件初始化为空errno = 0;//输出提示符printf("用户名@主机名~当前路径#");fflush(stdout);//获取用户输入,输入的时候用户会键入\nchar *s = fgets(lineCommand,sizeof(lineCommand)-1,stdin);//fgets从指定流FILE*中读取\n,n,末尾结束到lineCo中,���功返回line,失败返回空assert(s!=NULL);(void)s;//清除最后一个\n,abcd\nlineCommand[strlen(lineCommand)-1] = 0;commandCheck(lineCommand);//检查是否有重定向语句//字符串切割myargv[0] = strtok(lineCommand," ");//将字符串以空格切割int i = 0;if(myargv[0]!=NULL && strcmp(myargv[0],"ls")==0)//如果是ls命令{myargv[i++] = (char*)"——color-auto";//添加颜色}//如果没有子串了,strtok--NULL,myargc[end] = NULL;while(myargv[i++] = strtok(NULL," "));//设置分割的结束符为NULL//如果是cd命令,不需要创建子进程,让shell自己执行对应的命令,如果交给子进程执行shell的路径还是变不了,像这种不需要让我们的子进程来进行,而是让shell自己执行的命令--内建命令if(myargv[0]!=NULL && strcmp(myargv[0],"cd")==0)//如果是cd命令{if(myargv[1]!=NULL) chdir(myargv[1]);//chdir()改变当前工作目录的函数,myargv[1]cd后面紧跟的要改变的路径continue;//进入下次循环-->键入下一个指令}//创建子进程pid_t id = fork();assert(id!=-1);if(id == 0){switch(redirType){case NONE_REDIR:break;case INPUT_REDIR:{int fd = open(redirFile,O_RDONLY);if(fd<0){perror("open");exit(errno);}dup2(fd,0);}break;case OUTPUT_REDIR:case APPEND_REDIR:{umask(0);int flags = O_WRONLY | O_CREAT;if(redirType == APPEND_REDIR) flags |= O_APPEND;else flags |= O_TRUNC;int fd = open(redirFile,flags);if(fd<0){perror("open");exit(errno);}dup2(fd,1);}break;default:printf("bug?\n");break;}execvp(myargv[0],myargv);//execvp会在PATH中查找myargv[0]文件,找到后执行exit(1);//替换失败退出}int status = 0;pid_t ret = waitpid(id,&status,0);//等待成功返回子id,assert(ret>0);(void)ret;lastCode = ((status>>8) & 0xFF);//取次八位lastSig = (status & 0x7F);//取后七位}
}
相关文章:
Linux:进程控制
1.fork()函数初识 在linux中fork函数时非常重要的函数,它从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。 #include <unistd.h> pid_t fork(void); 返回值:自进程中返回0,父进程返回子进程id࿰…...
一些计算机零碎知识随写(25年1月)-1
我原以为世界上有技术的那批人不会那么闲,我错了,被脚本真实了。 今天正隔着画画呢,手机突然弹出几条安全告警通知。 急忙打开服务器,发现问题不简单,直接关服务器重装系统..... 首先,不要认为小网站&…...
spring mvc源码学习笔记之十
前面的文章介绍了用 WebApplicationInitializer 或者 AbstractAnnotationConfigDispatcherServletInitializer 来代替 web.xml 。 我们学 java web 的时候就知道,servlet 容器会自动加载 web.xml。 那么,疑问就来了,WebApplicationInitialize…...
网络安全-安全散列函数,信息摘要SHA-1,MD5原理
安全散列函数 单向散列函数或者安全散列函数之所以重要,不仅在于消息认证(消息摘要。数据指纹)。还有数字签名(加强版的消息认证)和验证数据的完整性。常见的单向散列函数有MD5和SHA 散列函数的要求 散列函数的目的是文件、消息或者其它数据…...
《解锁计算机视觉智慧:编程实现图片场景文字描述的开源宝藏》
《解锁计算机视觉智慧:编程实现图片场景文字描述的开源宝藏》 一、MiniGPT-4:小模型撬动大视觉理解(一)项目概览(二)核心亮点(三)上手体验 二、ClipCap-Chinese:中文场景…...
vue封装axios请求
在vue项目中我们发送请求一般是使用axios 我们可以封装axios来避免冗余代码 首先引入axios npm install axios创建环境配置文件 NODE_ENV development VITE_APP_TITLE dev VITE_APP_BASE_API /test VITE_SERVE "http://127.0.0.1"上面是创建dev配置文件 也可以…...
【前端动效】原生js实现拖拽排课效果
目录 1. 效果展示 2. 效果分析 2.1 关键点 2.2 实现方法 3. 代码实现 3.1 html部分 3.2 css部分 3.3 js部分 3.4 完整代码 4. 总结 1. 效果展示 如图所示,页面左侧有一个包含不同课程(如语文、数学等)的列表,页面右侧…...
Python Selenium库入门使用,图文详细。附网页爬虫、web自动化操作等实战操作。
文章目录 前言1 创建conda环境安装Selenium库2 浏览器驱动下载(以Chrome和Edge为例)3 基础使用(以Chrome为例演示)3.1 与浏览器相关的操作3.1.1 打开/关闭浏览器3.1.2 访问指定域名的网页3.1.3 控制浏览器的窗口大小3.1.4 前进/后…...
AI华佗?港中大、深圳大数据研究院提出医疗推理大模型HuatuoGPT-o1
编辑 | 白菜叶 OpenAI o1 的突破凸显了通过增强推理能力来提高自然语言大模型(LLM)的应用潜力。然而,大多数推理研究都集中在数学任务上,而医学等领域尚未得到充分探索。 医学领域虽然不同于数学,但鉴于医疗保健的高…...
openEuler22.03系统使用Kolla-ansible搭建OpenStack
Kolla-ansible 是一个利用 Ansible 自动化工具来搭建 OpenStack 云平台的开源项目,它通过容器化的方式部署 OpenStack 服务,能够简化安装过程、提高部署效率并增强系统的可维护性。 前置环境准备: 系统:openEuler-22.03-LTS-SP4 配置&…...
uni-app无限级树形组件简单实现
因为项目一些数据需要树形展示,但是官网组件没有。现在简单封装一个组件在app中使用,可以无线嵌套,展开,收缩,获取子节点数据等。 简单效果 组件TreeData <template><view class"tree"><te…...
初学stm32 --- ADC单通道采集
目录 ADC寄存器介绍(F1) ADC控制寄存器 1(ADC_CR1) ADC控制寄存器 2(ADC_CR2) ADC采样时间寄存器1(ADC_SMPR1) ADC采样时间寄存器2(ADC_SMPR2) ADC规则序列寄存器 1(ADC_SQR1) ADC规则序列寄存器 2(ADC_SQR2) ADC规则序列寄存器 3(ADC_SQR3) AD…...
css盒子水平垂直居中
目录 1采用flex弹性布局: 2子绝父相margin:负值: 3.子绝父相margin:auto: 4子绝父相transform: 5通过伪元素 6table布局 7grid弹性布局 文字 水平垂直居中链接:文字水平垂直居中-CSDN博客 以下为盒子…...
django基于Python的智能停车管理系统
1.系统概述 1.定义:Django 基于 Python 的智能停车管理系统是一个利用 Django 框架构建的软件系统,用于高效地管理停车场的各种事务,包括车辆进出记录、车位预订、收费管理等诸多功能。 2.目的:它的主要目的是提高停车场的运营效…...
Rabbit Rocket kafka 怎么实现消息有序消费和延迟消费的
在消息队列系统中,像 RabbitMQ、RocketMQ 和 Kafka 这样的系统,都支持不同的方式来实现消息的有序消费和延迟消费。下面我们分别探讨这些系统中如何实现这两种需求: 1. RabbitMQ:实现消息有序消费和延迟消费 有序消费࿱…...
Kafka 会丢消息吗?
目录 01 生产者(Producer) 02 消息代理(Broker) 03 消费者(Consumer) 来源:Kafka 会丢消息吗? Kafka 会丢失信息吗? 许多开发人员普遍认为,Kafka 的设计本身就能保证不会丢失消息。然而,Kafka 架构和配置的细微差别会导致消息的丢失。我们需要了解它如何以及何时…...
状态模式详解与应用
状态模式(State Pattern),是一种行为型设计模式。它允许一个对象在其内部状态改变时改变它的行为,使得对象看起来似乎修改了它的类。通过将不同的行为封装在不同的状态类中,状态模式可以避免大量的条件判断语句&#x…...
红队工具使用全解析:揭开网络安全神秘面纱一角
红队工具使用全解析:揭开网络安全神秘面纱一角 B站红队公益课:https://space.bilibili.com/350329294 学习网盘资源链接:https://pan.quark.cn/s/4079487939e8 嘿,各位网络安全爱好者们!在风云变幻的网络安全战场上&am…...
【Spring】Redis缓存+ehcache
文章目录 基于Spring的RedisehcacheRedis 缓存配置Cacheable 注解CacheEvict 注解缓存配置 基于Spring的Redisehcache Redis 缓存配置 在项目中添加 Redis 的依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot…...
【硬件介绍】Type-C接口详解
一、Type-C接口概述 Type-C接口特点:以其独特的扁头设计和无需区分正反两面的便捷性而广受欢迎。这种设计大大提高了用户的使用体验,避免了传统USB接口需要多次尝试才能正确插入的问题。Type-C接口内部结构:内部上下两排引脚的设计虽然可能不…...
网络传输层TCP协议
传输层TCP协议 1. TCP协议介绍 TCP(Transmission Control Protocol,传输控制协议)是一个要对数据的传输进行详细控制的传输层协议。 TCP 与 UDP 的不同,在于TCP是有连接、可靠、面向字节流的。具体来说,TCP设置了一大…...
Git 基础——《Pro Git》
⭐获取 Git 仓库 获取 Git 仓库有两种方式: 将未进行版本控制的本地目录转换为 Git 仓库。从其他服务器克隆一个已存在的 Git 仓库。 在已存在目录中初始化 Git 仓库 进入目标目录 在 Linux 上:$ cd /home/user/my_project在 macOS 上:$ c…...
数据结构与算法之二叉树: LeetCode 654. 最大二叉树 (Ts版)
最大二叉树 https://leetcode.cn/problems/maximum-binary-tree/ 描述 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点,其值为 nums 中的最大值递归地在最大值 左边 的 子数组前缀上 构建左子树递归地在最大值…...
学习记录:C++宏定义包含多条语句,使用注意事项
应该使用 do - while(0) 结构的情况 在条件语句(如 if - else、switch - case)或循环语句(如 for、while、do - while)中使用宏: 当宏定义包含多条语句且会在上述语句中使用时,使用 do - while(0) 可确保…...
PHP 使用 Redis
PHP 使用 Redis PHP 是一种广泛使用的服务器端编程语言,而 Redis 是一个高性能的键值对存储系统。将 PHP 与 Redis 结合使用,可以为 Web 应用程序提供快速的读写性能和丰富的数据结构。本文将详细介绍如何在 PHP 中使用 Redis,包括安装、连接、基本操作以及一些高级应用。 …...
项目开发实践——基于SpringBoot+Vue3实现的在线考试系统(五)
文章目录 一、学生管理模块功能实现1、添加学生功能实现1.1 页面设计1.2 前端功能实现1.3 后端功能实现1.4 效果展示2、学生管理功能实现2.1 页面设计2.2 前端功能实现2.3 后端功能实现2.3.1 后端查询接口实现2.3.2 后端编辑接口实现2.3.3 后端删除接口实现2.4 效果展示二、代码…...
下载并安装MySQL
在Linux系统上下载并安装数据库(以MySQL为例)的步骤如下: 一、下载MySQL 访问MySQL官网 打开浏览器,访问MySQL的官方网站:https://www.mysql.com/。 进入下载页面 在MySQL官网首页,找到并点击“Downloads…...
【C++入门】详解(中)
目录 💕1.函数的重载 💕2.引用的定义 💕3.引用的一些常见问题 💕4.引用——权限的放大/缩小/平移 💕5. 不存在的空引用 💕6.引用作为函数参数的速度之快(代码体现) Ǵ…...
计算机视觉算法实战——车道线检测
✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ 车道线检测是计算机视觉领域的一个重要研究方向,尤其在自动驾驶和高级驾驶辅助…...
基于http协议的天气爬虫
该系统将基于目前比较流行的网络爬虫技术, 对网站上的天气数据进行查询分析, 最终使客户能够通过简单的操作, 快速, 准确的获取目标天气数据。主要包括两部分的功能, 第一部分是天气数据查询, 包括时间段数…...
自然语言处理基础:全面概述
自然语言处理基础:全面概述 什么是NLP及其重要性、NLP的核心组件、NLU与NLG、NLU与NLG的集成、NLP的挑战以及NLP的未来 自然语言处理(NLP)是人工智能(AI)中最引人入胜且具有影响力的领域之一。它驱动着我们日常使用的…...
软件架构考试基础知识 002:进程的状态与其切换
进程状态转换的说明 在操作系统中,进程的状态表示其当前的执行情况和资源占用情况。进程状态的转换反映了操作系统如何管理和调度进程。以下是进程状态转换的说明: 1. 三态模型(Three-state Model) 三态模型是最基础的进程状态模…...
【Linux系列】Curl 参数详解与实践应用
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
VsCode对Arduino的开发配置
ps:我的情况是在对esp32进行编译、烧录时,找不到按钮,无法识别Arduino文件,适合已经有ini文件的情况。 1.在vscode中安装拓展 2.打开设置,点击右上角,转到settings.json文件 3.复制以下代码并保存 {"…...
【Pandas】pandas Series rtruediv
Pandas2.2 Series Binary operator functions 方法描述Series.add()用于对两个 Series 进行逐元素加法运算Series.sub()用于对两个 Series 进行逐元素减法运算Series.mul()用于对两个 Series 进行逐元素乘法运算Series.div()用于对两个 Series 进行逐元素除法运算Series.true…...
VUE3 自定义指令的介绍
自定义指令的概述 在 Vue 中,自定义指令是一种机制,允许开发者在模板中直接操作 DOM 元素,执行一些低级别的操作。Vue 提供了几个内置指令(如 v-if、v-for、v-model 等),但当我们需要一些特定功能时&#…...
RedisDB双机主从同步性能测试
安装redisDB 主节点 apt install redis-server修改配置 /etc/redis/redis.conf bind 0.0.0.0save "" # 禁止RDB持久化 #save 900 1 #save 300 10 #save 60 10000appendonly no # 禁止AOF持久化重启服务 systemctl restart redis-server从节点配置文件 bind 0.…...
【汇编】x86汇编编程寄存器资源心中有数
1. CPU状态及控制寄存器 TR,GDTR,LDTRcr0-cr3EFLAGS 等等 2. 业务计算寄存器(我起的名字) 业务寄存器用于访问内存、参数传递、数据传递、计算。 段寄存器6个: cs,ds,es,ss&…...
一.项目课题 <基于TCP的文件传输协议实现>
客户端代码 需要cJSON.c文件和cJSON.h文件 在这里插入代码片#include "myheadth.h" #include "myfun.h"#define TIME 10 int sockfd; void heartbeat(int signum) {cJSON* root cJSON_CreateObject();cJSON_AddStringToObject(root,"request"…...
【数据结构学习笔记】19:跳表(SkipList)
介绍 跳表是一个能在 O ( n l o g n ) O(nlogn) O(nlogn)时间完成查找、插入、删除的数据结构,相比于树形结构优点就是很好写(所以也用于实现Redis ZSet)。其核心思想就是维护一个元素有序的,能随机提升索引层数的链表。最下面一…...
Cocos Creator 3.8 修改纹理像素值
修改的代码: import { _decorator, Component, RenderTexture, Sprite, Texture2D, ImageAsset, SpriteFrame, Vec2, gfx, director, log, math, v2 } from cc;const { ccclass, property } _decorator;ccclass(GradientTransparency) export class GradientTrans…...
【Linux】网络层
目录 IP协议 协议头格式 网段划分 2中网段划分的方式 为什么要进行网段划分 特殊的IP地址 IP地址的数量限制 私有IP地址和公有IP地址 路由 IP协议 在通信时,主机B要把数据要给主机C,一定要经过一条路径选择,为什么经过路由器G后&…...
单片机Day1
目录 一.什么是单片机? 二.单片机的组成 三.封装形式 四.优势 五.分类 通用型: 专用型: 按处理的二进制位可以分为: 六.应用: 七.发展趋势 1.增加CPU的数据总线宽度。 2.存储器的发展。 3.片内1/0的改进 …...
django基于 Python 的考研学习系统的设计与实现
以下是对Django基于Python的考研学习系统的设计与实现: 一、系统概述 Django基于Python的考研学习系统是一个为考研学子提供一站式学习辅助的平台。它整合了丰富的学习资源、学习计划制定、学习进度跟踪以及交流互动等功能,旨在满足考生在备考过程中的…...
openCvSharp 计算机视觉图片找茬
一、安装包 <PackageReference Include"OpenCvSharp4" Version"4.10.0.20241108" /> <PackageReference Include"OpenCvSharp4.runtime.win" Version"4.10.0.20241108" /> 二、准备两张图片 三、编写代码 using OpenCv…...
深入学习 Python 爬虫:从基础到实战
深入学习 Python 爬虫:从基础到实战 前言 Python 爬虫是一个强大的工具,可以帮助你从互联网上抓取各种数据。无论你是数据分析师、机器学习工程师,还是对网络数据感兴趣的开发者,爬虫都是一个非常实用的技能。在本文中ÿ…...
【Web安全】SQL 注入攻击技巧详解:UNION 注入(UNION SQL Injection)
【Web安全】SQL 注入攻击技巧详解:UNION 注入(UNION SQL Injection) 引言 UNION注入是一种利用SQL的UNION操作符进行注入攻击的技术。攻击者通过合并两个或多个SELECT语句的结果集,可以获取数据库中未授权的数据。这种注入技术要…...
【DAPM杂谈之一】DAPM作用与内核文档解读
本文主要分析DAPM的设计与实现 内核的版本是:linux-5.15.164,下载链接: Linux内核下载 主要讲解有关于DAPM相关的知识,会给出一些例程并分析内核如何去实现的 /****************************************************************…...
计算机网络之---防火墙与入侵检测系统(IDS)
防火墙与入侵检测系统(IDS) 防火墙(Firewall) 和 入侵检测系统(IDS, Intrusion Detection System) 都是网络安全的关键组件,但它们的作用、功能和工作方式有所不同。 防火墙 防火墙是网络安全的一种设备或软件&#…...
HTML中meta的用法
学习网络空间安全专业,每个人有每个人的学法和选择。不论他选择什么,哪都是他自己的选择,这就是大多数视频教学的博主教学的步骤都不同原因之一。有人选择丢掉大部分理论直接学习网安,而我,选择了捡起大部分理论学习网…...