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

进程控制(详解)

进程控制

上篇文章介绍了进程的相关概念,形如进程的内核数据结构task_struct 、进程是如何被操作系统管理的、进程的查看、进程标识符、进程状态、进程优先级、已经环境变量和进程地址空间等知识点;

本篇文章接着上篇文章继续对进程的控制进行展开,主要包括进程的创建fork,进程的退出和终止、写时拷贝、进程等待(防止僵尸进程的产生使得内存泄漏),进程替换的相关知识!

文章目录

      • 进程创建
        • fork()的使用场景
        • fork()调用失败的原因
        • 子进程的数据和代码默认是与父进程共享的
        • 创建子进程的操作系统需要干什么
        • 父子进程是具有独立性的
        • 父子进程既然共享代码和数据如何实现独立性
      • 写时拷贝详解
      • 进程终止
        • 进程退出的场景有哪几种?
        • 进程退出的方式
        • exit()和_exit()的区别
        • 如何获取一个进程的退出码或者退出信号
        • 方法一:通过位运算来获取
        • 方法二:通过宏来获取
      • 进程等待
        • 进程等待的用处是什么?
        • 进程等待的方式
        • wait()函数
        • waitpid()函数
        • 阻塞等待
        • 非阻塞等待
      • 进程替换
        • 为什么要有程序替换呢?
        • 原理是什么?
      • 六种程序替换函数
        • execl()
        • execlp
        • execle
        • execv()
        • execvp
        • execvpe
        • execve
        • exec系列函数用法总结:

进程创建

进程的创建在上篇文章中也有介绍过,进程创建的方式有两种,一种是我们将一个程序跑起来它就会变成一个进程,还有一种就是通过fork()函数创建子进程,主要的创建方式就是通过fork函数,所以我们再来回顾一下fork()函数吧.

fork()函数是一个系统调用接口

//fork()
pid_t fork(void);
返回值: pid_t 类型(实际上是无符号整数) 如果创建子进程成功,返回新创建的子进程的pid(大于0的)给它的父进程,返回0给它自己,如果创建失败就返回-1

注意:fork()成功创建了子进程后就会有父子两个进程,那么也就是说会有两个执行流,fork()会返回两次,分别对父进程和创建出来的子进程进行返回,给父进程返回子进程的pid,因为父进程和子进程的关系是一对多的,所以父进程需要去唯一标识子进程,而进程的pid是天然的标识一个进程的标志,所以fork()返回给父进程的是新创建出来的子进程的pid!而子进程他自己是被创建的时候就知道了自己的pid和其父进程的pid的,所以它不需要fork()函数对他返回任何值,所以fork()就默认给它返回0意思意思一下。上面是创建成功的情况,如果创建失败就会返回-1给当前进程!!!

在这里插入图片描述

fork()的使用场景

  • 一个进程希望将自己分身,可以一个人做多份工作,那么一个进程就可以通过创建子进程的方式来实现这个目的,可以将自己要干的事分担给子进程,让子进程去帮自己完成。
  • 一个进程需要执行别的可执行程序,就可以通过创建子进程的方式,让子进程通过程序替换去帮自己完成程序的执行,我们使用的shell就是这样的,我们执行命令(命令也是可执行程序)的时候,bash就会创建子进程,然后通过程序替换去执行可执行程序。

fork()调用失败的原因

原因非常简单,类比你的手机下来太多东西,容量不够了就不能在下载东西了!

所以fork()创建子进程失败的原因无非就是操作系统中存在太多的进程,内存不够了。

子进程的数据和代码默认是与父进程共享的

我们学习语言的时候了解过继承,子类会继承父类的成员变量,这个理念在进程中同样被使用!

一个进程如果通过fork()函数创建子进程成功,那么它的子进程就会以它的父进程为模板,拷贝它的代码和数据。

创建子进程的操作系统需要干什么

fork()是系统调用,那么就必须要由操作系统来完成子进程的创建工作,那么os会做什么事情呢?

  • 根据上篇文章的知识,进程是被操作系统管理起来的,一个进程就是一个task_struct结构体,该结构体包括所有的进程的属性,比如进程的pid、进程的代码对应的地址,数据对应的地址,进程的退出状态,退出信号,进程地址空间等等;

  • 操作系统用task_struct 结构体 将进程描述好,再对这些结构体管理,实现对进程的管理工作;

  • 知道了上面这些,那么我们就很容易猜到 创建一个进程操作系统就肯定会先创建一个新的task_struct 结构体,该结构体就是那个新新创建的子进程,创建好结构体还没完,还需要对其进行初始化,根据继承的理念,子进程会默认继承父进程的代码和数据,那么操作系统就会把父进程的task_struct中的代码和数据的地址拷贝给子进程;

父子进程是具有独立性的

进程之间是具有独立性的,即使是父子进程也是如此,各个进程之间都是独立运行的!

父子进程既然共享代码和数据如何实现独立性

既然子进程创建出来后是和父进程共享的代码和数据,那么子进程对继承自父进程的数据或代码进行修改,岂不是会对父进程造成影响吗?那怎么还说进程是具有独立性的呢?

  • 子进程是和父进程共享的代码和数据没错,进程间具有独立也没有错,错的是子进程修改和父进程共享的数据和代码是不可能会影响到父进程的!因为操作系统考虑到了这个问题,并且让父子进程之间具有写时拷贝的机制,使得在父子一方对共享的资源进行修改是就会将修改的资源分离使得父子各有一份,从而实现进程的独立性!!!

下面具体介绍写时拷贝~

写时拷贝详解

未发生写时拷贝:

未发生写时拷贝的时候,父子是共享这数据和代码的。 它们通过各自的页表将相同的虚拟地址映射到相同的物理地址。

在这里插入图片描述

发生写时拷贝后:

当子进程对父子共享的数据或者代码进行修改时,因为进程之间要有独立性,操作不可能直接让子进程将共享的数据给改掉,那样会直接影响到父进程!

所以操作系统会在子进程对父子共享的代码或者数据进行修改的时候,会开辟出一块新的物理空间,将要被修改的代码或者数据拷贝一份之后,让父子中先对共享资源修改的一方去修改新拷贝出来的数据,再让先修改共享资源的一方的页表去重新映射新开辟出来的物理空间实现父子进程的资源分离,互不影响!这就是写时拷贝的基本原理~ (当有一方要对共享资源修改时,为其开要修改的资源开辟新空间,再对该空间的值进行修改,使得二者都有对应的资源,但是被修改的资源不是同一块物理空间了!)

请添加图片描述

注:写时拷贝的相关操作是由操作系统的内存管理模块完成的!

为什么要有写时拷贝?直接在创建子进程的时候就为其数据和代码开辟新的空间,将其和父进程的数据和代码分离开不好么?

  • 1.父子进程的数据,子进程不一定全用,即使使用,也不一定全都会写入(修改)----------存在空间浪费
  • 2.最理想的情况是,只有会被父子修改的数据,才会进行分离拷贝,不会修改修改的共享即可 ------理论可以技术角度上无法实现,父子对数据的修改是不可提前预测的
  • 3.如果fork的时候就无脑的将父进程的数据拷贝给子进程,就会增加fork的成本(内存和时间层面上)

所以既然写时拷贝存在就有它存在的原因,存在即合理!

写时拷贝是解决上述问题的较为合理的方法,所以才会被采用。写时拷贝是一种演示拷贝的策略,只有当你会对数据进行修改的时候才会给你开辟新的空间,将数据分离,当你不修改的时候,就不会给你新开辟空间,这样省下来的空间就可以被其他进程使用了!体现了os良好的内存管理方案

进程终止

进程退出的场景有哪几种?

  • 第一种:代码运行完毕,结果正确
  • 第二种:代码运行完毕,结果不正确
  • 第三种:代码都没执行完,发生了异常,操作系统直接终止进程

进程退出的方式

  • 第一种:通过main函数返回
  • 第二种:通过调用exit()函数或系统调用_exit()退出进程
  • 第三种:给进程发信号,将进程终止(kill)

上面提到了exit()和_exit(),它们的功能都是让进程退出,两者之间有什么区别呢?

exit()和_exit()的区别

exit()是封装_exit()的函数, _exit()是系统调用。exit() 最终也还是会去调用 _exit() , exit()在 _exit()的基础上增加了新的功能,就是:

  • 执行用户通过atexit或on_exit定义的清理函数
  • 关闭所有打开的流,所有的缓存数据都会被写入(刷新)
    请添加图片描述

如何获取一个进程的退出码或者退出信号

  • exit(int status)和 _exit(int status)中的参数status就是进程的退出状态码

  • status只有低16位才有价值,它的0-7位是存储着进程的退出信号,8-15位是存的进程的退出码

  • 进程正常终止时的退出信号是为0的,退出码为进程设置的退出码

  • 进程被信号所终止时,退出码为0,退出信号为进程所收到的信号

在这里插入图片描述

方法一:通过位运算来获取

//获取退出码
status>>8&0xFF
//获取退出信号
status&0x7F
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
int main()
{pid_t id=fork();if(id==0){//childint n=10;while(n--){printf("i am child! i am running pid:%d   ppid:%d\n",getpid(),getppid());sleep(1);}exit(110);}else if(id>0){sleep(10);int status=0;waitpid(id,&status,0);if(id>0){sleep(3);printf("等待子进程成功\n");printf("子进程退出码:%d   退出信号:%d  子进程pid:%d \n",status>>8&0xFF,status&0x7f,id);//位运算获取退出码和退出信号的方式}printf("父进程退出!\n");}else {printf("fork error!\n");}return 0;
}

运行结果:

在这里插入图片描述

方法二:通过宏来获取

操作系统提供对应的宏来协助我们获取对应的退出信息

说明
WIFEXITED(int status)子进程正常终止则返回真,可以通过WEXITSTATUS(int status)获取子进程退出码
WIFSIGNALED(int status)子进程异常终止返回真,若为真可通过WTERMSIG(int status)获取子进程的终止信号
WIFSTOPPED(int status)子进程若为暂停状态返回真
WIFCONTINUED(int status)子进程被暂停后将其继续的状态,返回真
WEXITSTATUS(int status)获取子进程退出码 status的次低8位
WTERMSIG(int status)获取子进程终止信号 stauts的低7位
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<fcntl.h>
#include<unistd.h>
int main()
{pid_t id=fork();if(id==0){while(1){printf("i am child pid:%d \n",getpid());sleep(1);//exit(110);}}else {int status=0;int ret=waitpid(id,&status,0);//阻塞式等待子进程if(ret>0){// if(WIFEXITED(status)||WIFSIGNALED(status))if(WIFEXITED(status)){printf("子进程退出! 退出码:%d\n",WEXITSTATUS(status));}if(WIFSIGNALED(status)){printf("子进程退出!退出信号:%d\n",WTERMSIG(status));}}}return 0;
}

在这里插入图片描述

进程等待

进程等待的用处是什么?

我们知道子进程退出时如果父进程未读取其相关的退出信息那么该子进程就会变成僵尸进程,僵尸进程会有内存泄漏浪费系统资源,且操作系统无法回收,就算是kill 也不能将它怎么样,因为它已经僵尸了,kill可以杀死在运行的进程,但是它做不到杀死一个已经死去的进程!

  • 所以进程等待就是防止产生僵尸进程的处理方式。通过让父进程等待子进程退出,然后再读取它的退出信息,那么子进程就不再僵尸,会变成终止状态,随时等待被系统回收资源!
  • 创建子进程一般都是让子进程去完成父进程给它分配的任务,那么父进程就需要知道子进程最终完成的如何,所以父进程有必要等待子进程退出,读取它的退出状态!

进程等待的方式

wait()函数

pid_t wait(int *stauts)

wait会等待任意一个子进程

参数:

status是输出型参数,可以通过status获取退出子进程的退出状态(退出码或终止信号)

返回值:

成功返回对应子进程pid,失败返回-1

waitpid()函数

pid_t waitpid(pid_t pid,int* status,int options)

waitpid相对wait的可选性更多

参数:

pid : 为-1时,代表着等待任意一个子进程;大于0时,代表等待指定pid的子进程

status:输出型参数,可以通过它获取子进程的退出状态(退出码或终止信号)

options:等待方式,当options为0 时代表父进程阻塞式的等待子进程退出;当options为WNHANG时代表着非阻塞等待,当waitpid返回值为0时,说明子进程还未退出,父进程不会一直在那等待,而是会去干别的事,父进程会以轮询的方式来获取子进程是否退出。

返回值:等待成功返回等待的子进程的pid 失败返回-1

阻塞等待

笼统的理解

所谓的阻塞式等待就是将waitpid中的参数options设置为0,那么父进程就会一直停留在waitpid()这条语句这里,什么也不干就是干等着子进程退出,之后再往下执行后续代码。

系统的理解

父进程阻塞式等待子进程就是当子进程未退出时,操作系统会将父进程的PCB(task_sttuct)放到子进程的等待队列当中,根据前面的进程状态知识可以知道,一个进程等待着某种资源就绪的状态叫做阻塞状态,子进程在等待着父进程退出就是父进程等待着资源就绪,只要子进程不退出,那么父进程就会一直再其等待队列中,直到子进程退出,操作系统才会将父进程继续放回运行队列往下运行后续代码!!!
在这里插入图片描述

非阻塞等待

设置非阻塞等待的方式就是将waitpid()中的options设置为WNOHANG即可,那么父进程就会去询问子进程是否退出,如果退出了就返回子进程的pid,未退出返回0,出错返回-1;

通过这种返回就可以让父进程去以轮询的方式去询问子进程是否退出,如果退出就将其回收,否则父进程就可以去干其他事情,而不是一直在原地阻塞着硬等着子进程退出,非阻塞等待的方式可以解放父进程的时间!!!

进程替换

为什么要有程序替换呢?

子进程被创建出来是共享着父进程的代码的,并且会从fork()之后的代码处开始往后执行,那么执行的是和父进程一样的代码,这是没有什么意义的! 我们通常是创建子进程去让子进程去完成其他的工作,比如让子进程去执行其他的可执行程序,那么这里就需要用到进程的替换。

原理是什么?

进程替换的原理就是当进程调用exec系列的进程替换函数后,当前进程的用户空间的代码和数据就会全部被新的程序所替换,接下来就会执行的是新的程序的代码!

注意:进程替换只是将一个进程的用户空间代码和数据用新的程序的代码及数据来替换,整个过程中是没有创建新的进程的,原进程的pid是不变的,变的只有代码和数据!

请添加图片描述

六种程序替换函数

在这里插入图片描述

execl()

int execl(const char *path, const char *arg, ...);

函数名中的l代表list,指代传执行程序的方式是按列表的方式传参的

参数列表

path:代表着要执行的程序的绝对路径

arg:执行该程序的方式,这里的arg是一个可变参数列表。(执行指令方式的多个字符串都可以被arg接收),但是传给arg的最后一个字符串必须是NULL

例如:执行ls 命令时 我们敲的是 ls -a -l

那么让ls去替换子进程时,首先path 就是传的ls的绝对路径(/usr/bin/ls),剩下的就是我们的执行方式 ls -a -l 那么arg就得是“ls" “-a” “-l”,当然最后得串一个空代表执行命令结束了,所以传给arg的是"ls",“-a”,“-l”,NULL

在这里插入图片描述

执行结果:子进程执行了ls(ls是一个命令 ,也是一个程序!)
在这里插入图片描述

execlp

int execlp(const char *file, const char *arg, ...);

解释

函数名中的p代表着PATH的意思,带p的替换函数就会自动去搜索环境变量PATH;

所以在带p的替换函数中执行某个程序的时候就可以不用传某个程序的绝对路径,只需传其程序名即可,程序替换函数会自己去环境变量中去找这个程序。

参数列表

第一个就是替换的程序路径(不用写全),第二个就是可变参数列表,接收的是执行的方式,同execl.

在这里插入图片描述

execle

int execle(const char *path, const char *arg,..., char * const envp[]);

解释

  • 函数名带l,说明传参方式是列表;

  • 函数名中的e代表着environment的意思,也就是环境变量了。execle函数可以自己组装环境变量。

在这里插入图片描述

在这里插入图片描述

execv()

int execv(const char *path, char *const argv[]);

解释

path代表着执行的程序的绝对路径;

argv代表着执行替换程序的方式,用数组的方式传参。

在这里插入图片描述

execvp

解释

execvp和execlp只相差了一个字母,一个是l,一个是v,l代表list(列表),v代表vecor(数组)

也就是带l的执行程序的方式是以列表的方式传递的,带v的则以数组的方式传递!

在这里插入图片描述

execvpe

解释

类比execle和execlp,带v可知execvp的程序的执行方式以数组形式传递,带p可知其会自己搜索环境变量PATH,带e可知该函数可以自己组装环境变量。

在这里插入图片描述

execve

上面的六个函数都是语言封装的execve函数 execve是系统调用

注意:

  • exec系列的函数的参数args,是接收的程序执行的方式,其必须以NULL结尾!

exec系列函数用法总结:

函数名args(执行方式)的传参形式是否带路径(PATH)是否使用当前环境变量
execl(list)列表
execlp列表
execle列表自己组装环境变量
execv(vector)数组
execvp数组
execvpe数组自己组装环境变量
execve数组自己组装环境变量

相关文章:

进程控制(详解)

进程控制上篇文章介绍了进程的相关概念&#xff0c;形如进程的内核数据结构task_struct 、进程是如何被操作系统管理的、进程的查看、进程标识符、进程状态、进程优先级、已经环境变量和进程地址空间等知识点&#xff1b; 本篇文章接着上篇文章继续对进程的控制进行展开&#x…...

瓜子大王稳住基本盘,洽洽食品做对了什么?

2月24日&#xff0c;洽洽食品披露2022年业绩快报,公司预计实现营收总收入68.82亿元&#xff0c;同比增长14.98%, 实现归母净利润9.77 亿元&#xff0c;同比增长5.21%&#xff0c;业绩基本符合市场预期。来源&#xff1a;洽洽食品2022年度业绩快报2022年&#xff0c;瓜子大王洽洽…...

【音视频安卓开发 (十一)】jni基础

要使用jni开发需要包含jni.h头文件JNIEXPORT JNI : 是一个关键字&#xff0c;不能少&#xff08;编译能通过&#xff09;&#xff0c;标记为该方法可以被外部调用jstring : 代表java中的stringJNICALL: 也是一个关键字&#xff0c;可以少的jni callJNIENV : 这是c和java相互调用…...

通过FRP搭建内网穿透,实现域名访问局域网本机

1我的目标&#xff1a;实现通过域名访问局域网tomcat服务&#xff0c;域名访问方便本地微信调试2思路&#xff1a;&#xff08;1&#xff09;用服务器搭建内网穿透利用FRP实现穿透&#xff0c;frp 是一个专注于内网穿透的高性能的反向代理应用&#xff0c;支持 TCP、UDP、HTTP、…...

Pytorch 代码复现终极指南【收藏】

修改自&#xff1a;https://zhuanlan.zhihu.com/p/532511514我在刚接触pytorch的时候搜到了这个大佬的文章&#xff0c;当时最后天坑部分没有看的太明白&#xff0c;直到今天我也遇到的相同的问题&#xff0c;特来做一点点补充&#xff0c;方便大家理解。上述大佬文章的简版内容…...

iOS 后台运行

背景&#xff1a;app有在后台运行的需求 常用的后台常驻实现方法 1.Audio&#xff08;音乐播放软件&#xff09; 应用在后台播放无声的音频文件&#xff0c;只要播放不断&#xff0c;后台可一直活着&#xff0c;苹果审核人员如果发现&#xff0c;会被拒&#xff0c;有可能会…...

软设下午题第一大题--数据流图(做题)

软设下午第一大题一、数据流图&#xff08;Data Flow Diagram,简称DFD&#xff09;1、基本图形元素元素&#xff08;1&#xff09;外部实体&#xff08;External Agent&#xff09;&#xff08;2&#xff09;数据存储&#xff08;Data Store&#xff09;&#xff08;3&#xff…...

springboot内嵌Tomcat 安全漏洞修复

漏洞扫描提示的是tomcat-embed-core[CVE-2020-1938]&#xff0c;解决方式是升级tomcat的版本。 该漏洞影响的版本&#xff1a; Apache Tomcat 9.x < 9.0.31 Apache Tomcat 8.x < 8.5.51 Apache Tomcat 7.x < 7.0.100 Apache Tomcat 6.x 其余的安全漏洞也可以通过…...

Android OTA 相关工具(三) A/B 系统之 bootctl 工具

文章目录1. bootctl 的编译2. bootctl 的帮助信息3. bootctl 的用法1. hal-info2. get-number-slots3. get-current-slot4. mark-boot-successful5. set-active-boot-slot6. set-slot-as-unbootable7. is-slot-bootable8. is-slot-marked-successful9. get-suffix10. set-snaps…...

【Flink】org.apache.flink.table.api.ValidationException: SQL validation failed

遇到问题如下 Exception in thread "main" org.apache.flink.table.api.ValidationException: SQL validation failed. From line 1, column 15 to line 1, column 17: Object aaa not found at org.apache.flink.table.planner.calcite.FlinkPlannerImpl.orgat org.…...

宏基因组鉴定病毒流程中需要的生物信息工具

谷禾健康 许多流行病的爆发都是病毒引起的&#xff0c;面对新的传染性基因组出现的最佳策略是及时识别&#xff0c;以便于在感染开始时立即实施相应措施。 目前可用的诊断测试仅限于检测新的病理因子。适用于同时检测存在的任何病原体的高通量方法可能比使用基于当前方法的大量…...

Doris入门篇-分区分桶实验

简介 测试分区分桶效果。 分区的基本操作 添加分区 ALTER TABLE v2x_olap_database.government_car ADD PARTITION p20221203 VALUES LESS THAN ("2022-12-04");动态分区表不能添加分区&#xff0c;需要转为手动分区表。 查看分区 show partitions from <表…...

Spring-Xml配置

一、Spring 简介 1.简介 文档下载地址&#xff1a;Index of /spring-framework/docs 1.简介 Spring framework 是 Spring 基础框架 学习Spring 家族产品 Spring framework SpringBoot SpringCloud Spring 能用来做什么 开发 WEB 项目 微服务 分布式系统 Spring framew…...

设计模式-工作线程 创建多少线程池合适

1、定义 让有限的工作线程(Worker Thread)来轮流异步处理无限多的任务。也可以将其归类为分工模式&#xff0c;它的典型实现就是线程池&#xff0c;也体现了经典设计模式中的享元模式&#xff08;重用对象&#xff09;。 例如&#xff0c;海底捞的服务员(线程)&#xff0c;轮流…...

【算法基础】深度优先搜索(DFS) 广度优先搜索(BFS)

一、DFS & BFS 1. 深度优先搜索DFS 深度优先搜索属于图算法的一种,英文缩写为DFS即Depth First Search.其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。 2. 广度优先搜索BFS 广度优先搜索较之深度优先搜索之不同在于,深度…...

【分布式】ProtocolBuffer平滑升级原则

原文链接&#xff1a;https://blog.csdn.net/nash_cyk/article/details/99549719 关于Protocol Buffer优势这里就不详细介绍了&#xff0c;如便于不同开发语言的交互通信&#xff0c;便于服务器上线的平滑升级等。 但Protocol Buffer的Message协议升级是需要注意一些细节&…...

第四阶段17-关于Redis中的list类型,缓存预热,关于Mybatis中的`#{}`和`${}`这2种格式的占位符

关于Redis中的list类型 Redis中的list是一种先进后出、后进先出的栈结构的数据。 在使用Redis时&#xff0c;应该将list想像为以上图例中翻转了90度的样子&#xff0c;例如&#xff1a; 在Redis中的list数据&#xff0c;不仅可以从左侧压入&#xff0c;也可以选择从右侧压入…...

stringstream用法

stringstream是 C++ 提供的另一个字串型的串流(stream)物件,和之前学过的iostream、fstream有类似的操作方式。包含在头文件sstream中(#include <sstream>)。 实例: 1、C++标准库中的<sstream>提供了比ANSI C的<stdio.h>更高级的一些功能,即单纯性、类…...

2022年下半年系统集成项目管理工程师综合知识真题及答案解析

2022年下半年系统集成项目管理工程师综合知识真题及答案解析 1、()不属于“提升云计算自主创新能力”的工作内容。A.加强云计算相关基础研究、应用研究、技术研发、市场培育和产业政策密衔接与统筹协调B.引导大型云计算中心优先在能源充足、气候适宜、自然灾害较少的地区部…...

【洛谷 P2089】烤鸡(搜索)

烤鸡 题目背景 猪猪 Hanke 得到了一只鸡。 题目描述 猪猪 Hanke 特别喜欢吃烤鸡&#xff08;本是同畜牲&#xff0c;相煎何太急&#xff01;&#xff09;Hanke 吃鸡很特别&#xff0c;为什么特别呢&#xff1f;因为他有 101010 种配料&#xff08;芥末、孜然等&#xff09;…...

Mac item2 配置免密登录开发机

1、配置 vi ~/.ssh/config 内容如下&#xff1a; Host * ControlMaster auto ControlPath ~/.ssh/master-%r%h:%p ControlPersist yes ServerAliveInterval 60 学习&#xff1a; ControlMaster #连接共享 ControlPath #与ControlMaster一起使用&#xff0c;指定连接共享的路径…...

vue 解决问题:Webpack安装不成功,webpack -v无法正常显示版本号

目录 一、解决问题&#xff1a;Webpack安装不成功&#xff0c;webpack -v无法正常显示版本号 二、解决问题&#xff1a; ERROR Error: Cannot find module webpack-log 三、 解决报错&#xff1a;error:03000086:digital envelope routines::initialization error 四、解决…...

07-1【openEuler】系统及进程管理(网络管理的补充实验及说明)

文章目录说在前面关于nmcli命令的使用使用nmcli命令修改主机IP地址1、运行ip addr列出openEuler20.03上的以太网卡2、列出当前活动的以太网卡3、开始分配静态IP地址&#xff08;1&#xff09;命令语法&#xff08;2&#xff09;将 IPv4 地址192.168.74.175分配给 ens33 网卡上&…...

【Linux】磁盘结构、文件系统、软硬链接、动静态库链接

文章目录1、磁盘结构1.1 磁盘的物理结构1.2 磁盘的存储结构1.3 磁盘的逻辑结构2、文件系统2.1 4KB加载到内存2.2 文件系统结构3、软硬链接3.1 软链接3.2 硬链接4、动静态库4.1 什么是库&#xff1f;4.2 静态库和静态库链接4.3 动态库和动态库链接4.4 动静态库的加载下面了解到&…...

交换机电口、光口、网络速率的基本概念总结

电口和光口千兆网 & 万兆网&#xff1a;POE&#xff1a;包转发率&#xff1a;背板带宽/交换容量&#xff1a;)电口和光口 电口&#xff1a; 电口也即RJ45口&#xff0c;插双绞线的端口&#xff08;网线&#xff09;&#xff0c;一般速率为10M或100M&#xff0c;即为百兆工…...

【面试题 05.02. 二进制数转字符串】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 二进制数转字符串。给定一个介于0和1之间的实数&#xff08;如0.72&#xff09;&#xff0c;类型为double&#xff0c;打印它的二进制表达式。如果该数字无法精确地用32位以内的二进制表示&#xff0…...

webpack - webpack的基本使用和总结

文章目录1&#xff0c;webpack概念2&#xff0c;为什么学webpack3&#xff0c;webpack特点4&#xff0c;相对于其他工具优点5&#xff0c;准备工作6&#xff0c;webpack的核心介绍7&#xff0c;webpack使用 - 打包js代码8&#xff0c;打包css代码9&#xff0c;生成html文件10&a…...

【蓝桥杯嵌入式】定时器实现按键单击,双击,消抖以及长按的代码实现

&#x1f38a;【蓝桥杯嵌入式】专题正在持续更新中&#xff0c;原理图解析✨&#xff0c;各模块分析✨以及历年真题讲解✨都在这儿哦&#xff0c;欢迎大家前往订阅本专题&#xff0c;获取更多详细信息哦&#x1f38f;&#x1f38f;&#x1f38f; &#x1fa94;本系列专栏 - 蓝…...

基于SSM的Javaweb爱心扶贫捐赠系统

文章目录 项目介绍主要功能截图:后台登录首页个人中心用户管理扶贫物资管理扶贫产品管理留言板管理前台前台首页扶贫产品新闻资讯留言板部分代码展示设计总结项目获取方式🍅 作者主页:Java韩立 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,…...

Spring Cloud(微服务)学习篇(三)

Spring Cloud(微服务)学习篇(三) 1 nacos中使用openFeign(调用方式)实现短信发送 1.1 在shop-sms-api中创建com.zlz.shop.sms.api.service/vo/dto/util,目录结构如下所示 1.2 在pom.xml(shop-sms-api)中加入如下依赖 <dependencies><dependency><groupId>…...

做外贸网站要花多少钱/seo软件推广哪个好

ios打包和调试 Mac系统安装XCode方便调试 在App Store下载并安装Xcode。注意&#xff0c;xcode版本低的话&#xff0c;也会影响打包的。推荐使用XCode9. 如果你的OS版本不满足安装xcode的版本要求&#xff0c;你可以寻找对应版本的xcode下载链接&#xff0c;然后在safari打开…...

wordpress自定义页面创建专辑/seo是网络优化吗

一种商品需要用多个产品组成就需要运用抽象工厂模式。 概念&#xff1a; 抽象工厂&#xff1a;声明一个用于完成抽象商品对象创建操作的接口 具体工厂&#xff1a;实现创建具体产品对象的操作 抽象产品&#xff1a;声明一个用于一类产品对象的接口 具体产品&#xff1a;定义有相…...

大连甘井子区教育公共服务平台/德兴网站seo

编程本来并不难&#xff0c;但是你没有基础&#xff0c;缺乏计算机基础知识&#xff0c;那就非常困难&#xff0c;难于上青天。 尚学堂给同学们带来全新的Java300集课程啦!java零基础小白自学Java必备优质教程作为自学党&#xff0c;不知道一开始要学些什么&#xff0c;学到什么…...

空间网站建设/百度推广登陆后台

ping命令是一种测试两台设备之间网络连通性的命令。在Linux操作系统中&#xff0c;使用ping命令可以测试本机与其他设备之间的网络连通性。 基本语法&#xff1a; ping [options] [destination] 常用选项&#xff1a; -c count&#xff1a;指定ping命令的发送次数&#xff…...

券妈妈网站是如何做的/百度数据网站

HTTPS&#xff08;全称&#xff1a;HyperText Transfer Protocol over Secure Socket Layer&#xff09;&#xff0c;其实 HTTPS 并不是一个新鲜协议&#xff0c;Google 很早就开始启用了&#xff0c;初衷是为了保证数据安全。 近两年&#xff0c;Google、Baidu、Facebook 等这…...

软件开发和网站建设/微信平台推广方法

命令简介&#xff1a; 该命令用来识别文件类型&#xff0c;也可用来辨别一些文件的编码格式。它是通过查看文件的头部信息来获取文件类型&#xff0c;而不是像Windows通过扩展名来确定文件类型的。 执行权限 &#xff1a;All User 指令所在路径&#xff1a;/usr/bin/file 命令语…...