(15)Linux 进程创建与终止函数forkslab 分派器

前言:本章我们主要讲解进程的创建与终止,最后简单介绍一下 slab 分派器。

一、进程创建(Process creation)

1、分叉函数 fork 

在 \textrm{Linux} 中, fork 函数是非常重要的函数,它从已存在进程中创建一个新的进程。 

#include <unistd.h>
pid_t fork(void);

新进程为子进程 (child process) ,而原进程为父进程 (father process) 

返回值:子进程中返回 0,父进程返回子进程 id,出错返回 -1

为什么两个进程的pid不同呢,这与fork函数的特性有关。fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:
    1)在父进程中,fork返回新创建子进程的进程ID;
    2)在子进程中,fork返回0;
    3)如果出现错误,fork返回一个负值; 

 在fork函数执行完毕后,如果创建新进程成功,则出现两个进程,一个是子进程,一个是父进程。在子进程中,fork函数返回0,在父进程中,fork返回新创建子进程的进程ID。我们可以通过fork返回的值来判断当前进程是子进程还是父进程。

    引用一位网友的话来解释fpid的值为什么在父子进程中不同。“其实就相当于链表,进程形成了链表,父进程的fpid(p 意味point)指向子进程的进程id, 因为子进程没有子进程,所以其fpid为0.
    fork出错可能有两种原因:
    1)当前的进程数已经达到了系统规定的上限,这时errno的值被设置为EAGAIN。
    2)系统内存不足,这时errno的值被设置为ENOMEM。

 进程调用 fork,当控制转移到内核中的 fork 代码后,操作系统会做什么? 

①  将给子进程分配新的内存块和内核数据结构

  •     创建 task_struct 和进程地址空间 mm_struct

②  将父进程部分数据结构内容拷贝至子进程

  •     以父进程为模板,设置子进程的相关数据结构和父进程相关字段保持一致。
  •     task_struct、地址空间、区域划分很多东西都是一样的。
  •     但不是无脑拷贝!比如累计调度的时间片是不一样的。

③  添加子进程到系统进程列表当中

  •     取决于你进程是要做什么,创建后如果状态没问题就会直接链入运行队列中。

④  fork 返回,开始调度器调度

  •     当准备返回时,上面三个工作都有了,父进程继续执行开始 return,子进程也可能执行 fork 的返回值,然后就会得到两次返回。

 第一次返回的本质:通过寄存器向接收变量进行写入,写入的本质就是进行修改,所以就会发生写时拷贝,进而让同一个变量出现不同的值。至此就解释了 fork 的返回值为什么会有两个的问题。

当一个进程调用 fork 之后,就有两个二进制代码相同的进程,并且它们都运行到相同的地方。

但每个进程都可以开始它们自己的旅程,我们来看下面的代码:

代码演示:

 

结果:

我们可以看到,有三行输出,两行After,一行Before,为什么只有一个Before呢?30411的Before呢?

  • fork 之前:父进程独立执行(因为只有父进程)。
  • fork 之后:父子分道扬镳,父子两个执行流分别执行(因为 fork 之后有两个进程了)。

 fork 之后,谁先执行谁后执行完全由调度器决定!

那么 fork 之后,是否只有 fork 之后的代码是被父子进程共享的?

实际上,fork 之后代码共享这样的说法并不准确。一般情况 fork 之后,父子共享所有的代码

子进程执行的后续代码 != 共享的所有代码,只不过子进程只能从这里开始执行!

 2、写时拷贝(copy-on-write) 

 我们知道,进程具有独立性,代码和数据必须是独立的,代码只能读取 → 写时拷贝

通常,父子代码共享,父子在不让写入时数据也是共享的。当任意一方试图写入,就会按照写时拷贝的方式各自拷贝一份副本出来。写时拷贝本身由操作系统的内存管理模块完成的。

操作系统为什么要写时拷贝?创建子进程的时候就把数据分开不行吗?

  •     有浪费空间之嫌:父进程的数据,子进程不一定全用;即便使用,也不一定全部写入。
  •     最理想的情况,只有会被父子修改的数据,进行分离拷贝。不需要修改的数据,共享即可。但是从技术角度实现复杂。
  •     如果 fork 的时候,就无脑拷贝数据给子进程,会增加 fork 的成本(内存和时间)

最终采用写时拷贝:只会拷贝父子修改的、变相的,就是拷贝数据的最小成本。拷贝的成本依旧存在。

写时拷贝实际上以一种 延迟拷贝策略,延迟拷贝最大的价值:只有真正使用的时候才给你拷。

其最大的意义在于,你想要,但是不立马使用的空间,先不给你,那么也就意味着可以先给别人。

反正拷贝的成本总是要有,早给你晚给你都是一样。万一我现在给你你又不用,那其实不很浪费

所以我选择暂时先不给你,等你什么时候要用什么时候再给。这就变相的提高了内存的使用情况。

3、fork 的使用

最简单的方式就是 fork 之后利用 if-else 进行分流, 让父子执行不同的代码块。刚才通过实验我们也知道了,实际上 if-else 代码也是父进程,只不过子进程执行了父进程的代码罢了。所以,我们在 fork 之后让父子执行不同的代码段,这就是典型地 fork 创建出来让子进程执行类似的事。

一个父进程希望复制自己,使父子进程同时执行不同的代码段。我们做网络写服务器的时候会经常采用这样的编码方式,例如父进程等待客户端请求,生成子进程来处理请求。

还有一种用法就是 fork 之后创建子进程想做和父亲完全不一样的事情,比如子进程从 fork 返回后,调用 exec 函数。(我们本章下面会讲解的 "程序地址替换" 就和这个有关)

4、fork 调用失败的情况 

fork 肯定不是永远都成功的,fork 也是有可能调用失败的。

系统中有太多进程,导致内存资源不足,fork 不出。

代码演示:我们可以手动演示一下 fork 失败的场景

 

运行结果如下:

 

二、进程终止(Process Termination) 

 1、终止的认识

 C/C++ 的时侯,main 函数就是所谓的 入口函数

但是不知道大家是否关注过这个 return

下面我们思考两个问题:

这个 return 0 究竟给谁 return

 为何是 0 ?其他值可以吗?

#问:进程终止的常见方式?

  • 运行成功
    • 代码跑完,结果正确
    • 代码跑完,结果不正确
  • 运行失败
    • 代码没有跑完,程序崩溃了
退出码

#问:用代码,如何终结一个进程?什么是一个正确的终结?

  • 0:成功,正确。
  • 非0:标识的是运行的结果不正确。

2、进程退出码 

 写一个main函数return 0,并运行,可以发现:

命令:echo $?


最近(上一次)进程的退出码

 

因为对于运行结果我们关心的永远是:它错了究竟错在哪里、而不是它对了究竟对在哪里。所以用无数的非0值标识不同错误的原因。给我们的程序在运行结束之后,对于结果不正确时,方便定位错误的原因细节。 

 如果是再运行一下:

就变成0了

$? 表示在 \textrm{bash} 中,最近一次执行完毕时,对应进程的退出码。

我们随便显示一个不管他存不存在的文件

再反观我们之前学 C 时,代码都是无脑 return 0 的……

而这些指令代码的 return 都是设计好了的!

实际上,即使不会也没有关系,你无脑 return 0return 1,2,3,4...  都没有问题。

3、错误码 

C 语言当中有个的 string.h 中有一个 strerror 接口,是最经典的、将错误码表述打印出来的接口,输出错误原因定义归纳整理如下:

#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No child processes */
#define EAGAIN 11 /* Try again */
#define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device or resource busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File table overflow */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Not a typewriter */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Math argument out of domain of func */
#define ERANGE 34 /* Math result not representable */
#define EDEADLK 35 /* Resource deadlock would occur */
#define ENAMETOOLONG 36 /* File name too long */
#define ENOLCK 37 /* No record locks available */
#define ENOSYS 38 /* Function not implemented */
#define ENOTEMPTY 39 /* Directory not empty */
#define ELOOP 40 /* Too many symbolic links encountered */
#define EWOULDBLOCK EAGAIN /* Operation would block */
#define ENOMSG 42 /* No message of desired type */
#define EIDRM 43 /* Identifier removed */
#define ECHRNG 44 /* Channel number out of range */
#define EL2NSYNC 45 /* Level 2 not synchronized */
#define EL3HLT 46 /* Level 3 halted */
#define EL3RST 47 /* Level 3 reset */
#define ELNRNG 48 /* Link number out of range */
#define EUNATCH 49 /* Protocol driver not attached */
#define ENOCSI 50 /* No CSI structure available */
#define EL2HLT 51 /* Level 2 halted */
#define EBADE 52 /* Invalid exchange */
#define EBADR 53 /* Invalid request descriptor */
#define EXFULL 54 /* Exchange full */
#define ENOANO 55 /* No anode */
#define EBADRQC 56 /* Invalid request code */
#define EBADSLT 57 /* Invalid slot */
#define EDEADLOCK EDEADLK
#define EBFONT 59 /* Bad font file format */
#define ENOSTR 60 /* Device not a stream */
#define ENODATA 61 /* No data available */
#define ETIME 62 /* Timer expired */
#define ENOSR 63 /* Out of streams resources */
#define ENONET 64 /* Machine is not on the network */
#define ENOPKG 65 /* Package not installed */
#define EREMOTE 66 /* Object is remote */
#define ENOLINK 67 /* Link has been severed */
#define EADV 68 /* Advertise error */
#define ESRMNT 69 /* Srmount error */
#define ECOMM 70 /* Communication error on send */
#define EPROTO 71 /* Protocol error */
#define EMULTIHOP 72 /* Multihop attempted */
#define EDOTDOT 73 /* RFS specific error */
#define EBADMSG 74 /* Not a data message */
#define EOVERFLOW 75 /* Value too large for defined data type */
#define ENOTUNIQ 76 /* Name not unique on network */
#define EBADFD 77 /* File descriptor in bad state */
#define EREMCHG 78 /* Remote address changed */
#define ELIBACC 79 /* Can not access a needed shared library */
#define ELIBBAD 80 /* Accessing a corrupted shared library */
#define ELIBSCN 81 /* .lib section in a.out corrupted */
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
#define EILSEQ 84 /* Illegal byte sequence */
#define ERESTART 85 /* Interrupted system call should be restarted */
#define ESTRPIPE 86 /* Streams pipe error */
#define EUSERS 87 /* Too many users */
#define ENOTSOCK 88 /* Socket operation on non-socket */
#define EDESTADDRREQ 89 /* Destination address required */
#define EMSGSIZE 90 /* Message too long */
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
#define ENOPROTOOPT 92 /* Protocol not available */
#define EPROTONOSUPPORT 93 /* Protocol not supported */
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
#define EPFNOSUPPORT 96 /* Protocol family not supported */
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
#define EADDRINUSE 98 /* Address already in use */
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
#define ENETDOWN 100 /* Network is down */
#define ENETUNREACH 101 /* Network is unreachable */
#define ENETRESET 102 /* Network dropped connection because of reset */
#define ECONNABORTED 103 /* Software caused connection abort */
#define ECONNRESET 104 /* Connection reset by peer */
#define ENOBUFS 105 /* No buffer space available */
#define EISCONN 106 /* Transport endpoint is already connected */
#define ENOTCONN 107 /* Transport endpoint is not connected */
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
#define ETIMEDOUT 110 /* Connection timed out */
#define ECONNREFUSED 111 /* Connection refused */
#define EHOSTDOWN 112 /* Host is down */
#define EHOSTUNREACH 113 /* No route to host */
#define EALREADY 114 /* Operation already in progress */
#define EINPROGRESS 115 /* Operation now in progress */
#define ESTALE 116 /* Stale NFS file handle */
#define EUCLEAN 117 /* Structure needs cleaning */
#define ENOTNAM 118 /* Not a XENIX named type file */
#define ENAVAIL 119 /* No XENIX semaphores available */
#define EISNAM 120 /* Is a named type file */
#define EREMOTEIO 121 /* Remote I/O error */
#define EDQUOT 122 /* Quota exceeded */
#define ENOMEDIUM 123 /* Nomedium found */
#define EMEDIUMTYEP 124 /*Wrongmedium found */
#define ECANCELED 125 /* Operation Canceled */
#define ENOKEY 126 /* Required key not available */
#define EKEYEXPIRED 127 /* Key has expired */
#define EKEYREVOKED 128 /* Key has been revoked */
#define EKEYREJECTED 129 /* Key was rejected by service */
#define EOWNERDEAD 130 /* Owner died */
#define ENOTRECOVERABLE 131 /* State not recoverable */
#define ERFKILL 132 /* Operation not possible due to RF-kill */
#define EHWPOISON 133 /* Memory page has hardware error */

 我们可以在 \textrm{Linux} 下写个程式去把这些错误码给打印出来:

运行结果如下:

会出来很多。。。

其中,0 表示 success,1 表示权限不允许,2 找不到文件或目录。

我们刚才 ls 一个不存在的,再 echo $?  显示对应的错误码就是 2:

总结:错误码退出码可以对应不同的错误原因,方便我们定位问题出在哪里。

4、进程终止的常见方法

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

main 函数返回    调用 exit     ③ _exit

我们先思考两个问题:

1. 在 main 函数中的 return(为什么其他函数不行)?
2. 在自己的代码任意地点中,调用 exit() 都可以做到进程退出。

 该函数想必大家并不陌生,exit 并不是一个系统调用,而是用 C 写的。

代码演示:我们来用一下这个 exit 函数:

运行结果如下:

 

运行完之后,打印完hello func之后,直接结束了程序,并没有返回,就在函数内部结束了。

main 函数调了 func 函数,进去打印后执行了 exit,最后进程没有返回直接在函数内部直接终止进程,这就叫调 exit 直接终止进程。此时我们 echo $? 得到的结果是 111 。

exit 当然也是可以在 main 函数中使用的,这里就不演示了。

如果你以后想终止一个进程,只需要在任意地点调用 exit 去 "代表" 进程退出

注意,只有在 main 函数调 return 才叫做 进程退出,其他函数调 return 叫做 函数返回。

下面我们再来讲解一下 _exit 函数,_exit 也是一个系统调用,也是可以用来终止进程的。

exit 和 _exit 是调用和被调用的关系,exit 是调用了 _exit 的。
代码演示:_exit 函数

 运行结果如下:

 区别:exit 会清理缓冲区,关闭流等操作,而 _exit 什么都不干,直接终止,并返回了我们随意写的退出码100

5、内核数据结构缓冲池

我们知道: 进程 = 内核结构 + 进程代码和数据 。

内核结构最典型的就是 task_struct 和 mm_struct,定义对象后以此充当进程的内核结构。

对于操作系统,可能并不会释放该进程的内核数据结构!

实际上,创建进程我们从零开始构建对象,创建对象分为两个步骤,即开辟空间与初始化。

无论是开辟空间还是初始化都是要花费时间的,存在 cost 的……那该怎么办?

\textrm{Linux} 会维护一张废弃的数据结构链表,我们称之为\textrm{obj},它是我们链表的数据结构结点。

当进程1释放后,进程的相关数据结构会维护进链表中,该数据结构是已经被操作系统释放掉了,但是并没有把它把它空间释放掉,而是设置其为 "无效"。当你再次创建进程时,它会从该队列中把相应的 task_struct 和 mm_struct 取出来,这就节省了开辟空间所花费的时间,要做的也只是把新进程的代码和空间进行初始化,可谓非常的轻松。

这种做法我们称之为 内核的数据结构缓冲池,该策略在操作系统中称为 slab 分派器 

 

由于内核数据结构高频地使用,创建一个进程释放一个进程是特别高频率的事情。

每次开辟空间再初始化难免有些累,既然频率高,那么索性不再对结构进行重新申请。

直接把数据结构缓存起来,要就拿,不要就再放回去(便利店借雨伞),这就是 slab 分配器。

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

html引入react以及hook的使用

html引入react 效果代码注意 效果 分享react demo片段的时候&#xff0c;如果是整个工程项目就有点太麻烦了&#xff0c;打开速度慢&#xff0c;文件多且没必要&#xff0c;这个时候用html就很方便。 在html中能正常使用useState 和 useEffect 等hook。 代码 <!DOCTYPE htm…

助力成长的开源项目 —— 筑梦之路

闯关式 SQL 自学&#xff1a;sql-mother 免费的闯关式 SQL 自学教程网站&#xff0c;从 0 到 1 带大家掌握常用 SQL 语法&#xff0c;目前一共有 30 多个关卡&#xff0c;希望你在通关的时候&#xff0c;变身为一个 SQL 高手。除了闯关模式之外&#xff0c;这个项目支持自由选…

Redis(二)数据类型

文章目录 官网备注十大数据类型StringListHashSetZSetBitmapHyperLogLog&#xff1a;GEOStreamBitfield 官网 英文&#xff1a;https://redis.io/commands/ 中文&#xff1a;http://www.redis.cn/commands.html 备注 命令不区分大小写&#xff0c;key区分大小写帮助命令help…

阿里云服务器开放端口Oracle 1521方法教程

阿里云服务器ECS端口是在安全组设置的&#xff0c;Oracle数据库1521端口号开放是在安全组中添加规则来实现的&#xff0c;阿里云服务器网aliyunfuwuqi.com来详细说下阿里云服务器开放Oracle 1521端口方法教程&#xff1a; 阿里云服务器开放Oracle 1521端口 在阿里云服务器ECS…

前端Web系统架构设计

文章目录 1.目录结构定义2. 路由封装2.1 API路由定义2.2 组件路由定义 3. Axios请求开发4. 环境变量封装5. storage模块封装(sessionStorage, localStorage)6. 公共函数封装(日期,金额,权限..)7. 通用交互定义(删除二次确认,类别,面包屑...)8. 接口全貌概览 1.目录结构定义 2. …

mysql 单表 操作 最大条数验证 以及优化

1、背景 开车的多年老司机&#xff0c;是不是经常听到过&#xff0c;“mysql 单表最好不要超过 2000w”,“单表超过 2000w 就要考虑数据迁移了”&#xff0c;“你这个表数据都马上要到 2000w 了&#xff0c;难怪查询速度慢”。 2、实验 实验一把看看… 建一张表 CREATE TABL…

机器学习-基于Word2vec搜狐新闻文本分类实验

机器学习-基于Word2vec搜狐新闻文本分类实验 实验介绍 Word2vec是一群用来产生词向量的相关模型&#xff0c;由Google公司在2013年开放。Word2vec可以根据给定的语料库&#xff0c;通过优化后的训练模型快速有效地将一个词语表达成向量形式&#xff0c;为自然语言处理领域的应…

STC进阶开发(三)蜂鸣器、RTC时钟、I2C总线、外部中断、RTC闹钟设置、RTC计时器设置

前言 这一期我们首先学习如何让蜂鸣器响起来&#xff0c;并且如何让蜂鸣器发出简单的歌曲&#xff0c;然后我们介绍RTC时钟&#xff0c;要想明白RTC时钟&#xff0c;我们还需要先介绍I2C总线和外部中断。接下来就开始这一期的学习吧&#xff01; 蜂鸣器 简单介绍 蜂鸣器是一种…

论文笔记:CellSense: Human Mobility Recovery via Cellular Network Data Enhancement

1 intro 1.1 背景 1.1.1 蜂窝计费记录&#xff08;CBR&#xff09; 人类移动性在蜂窝网络上的研究近些年得到了显著关注&#xff0c;这主要是因为手机的高渗透率和收集手机数据的边际成本低蜂窝服务提供商收集蜂窝计费记录&#xff08;CBR&#xff09;用于计费目的&#xf…

哲学家进餐问题-第三十二天

目录 问题描述 解决问题 结论 问题描述 解决问题 1、 关系分析&#xff1a;找出题目中描述的各个进程&#xff0c;分析它们之间的同步、互斥关系 系统中有5个哲学家进程&#xff0c;5位哲学家与左右邻居对其中间筷子的访问是互斥关系 2、整理思路&#xff1a;根据各进程的操…

ubuntu terminator 非常好用的护眼配置

安装 sudo apt install terminator 配置文件&#xff1a;sudo gedit ~/.config/terminator/config &#xff08;如果没有就创建&#xff09; 配置如下&#xff1a; [global_config] handle_size -3 title_transmit_fg_color "#000000" title_trans…

KBDNO1.DLL文件缺失,软件或游戏无法启动运行,怎样快速修复

不少小伙伴&#xff0c;求助电脑报错“KBDNO1.DLL文件缺失&#xff0c;软件或游戏无法启动或运行”&#xff0c;应该怎么办&#xff1f; 首先&#xff0c;我们先来了解“KBDNO1.DLL文件”是什么&#xff1f; KBDNO1.DLL是Windows操作系统中的一个动态链接库文件&#xff0c;主…

Java基础进阶(学习笔记)

注&#xff1a;本篇的代码和PPT图片来源于黑马程序员&#xff0c;本篇仅为学习笔记 static static 是静态的意思&#xff0c;可以修饰成员变量&#xff0c;也可以修饰成员方法 修饰成员的特点&#xff1a; 被其修饰的成员, 被该类的所有对象所共享 多了一种调用方式, 可以通过…

MACOS Atrust服务异常

MAC版Atrust服务异常 点击进入办公后出现提示其一&#xff1a; 核心服务未启动&#xff0c;部分功能存在异常&#xff0c;确定重新启动吗&#xff1f; 可能的原因&#xff1a; 1.上次已完全退出客户端 2.核心服务被其他程序优化禁用 点击重新启动后&#xff0c;出现提示&#x…

Spring Boot 如何使用 Maven 实现多环境配置管理

Spring Boot 如何使用 Maven 实现多环境配置管理 实现多环境配置有以下几个重要原因&#xff1a; 适应不同的部署环境&#xff1a;在实际部署应用程序时&#xff0c;通常会有多个不同的部署环境&#xff0c;如开发环境、测试环境、生产环境等。每个环境可能需要不同的配置&…

虹科方案丨从困境到突破:TigoLeap方案引领数据采集与优化变革

来源&#xff1a;虹科工业智能互联 虹科方案丨从困境到突破&#xff1a;TigoLeap方案引领数据采集与优化变革 原文链接&#xff1a;https://mp.weixin.qq.com/s/H3pd5G8coBvyTwASNS_CFA 欢迎关注虹科&#xff0c;为您提供最新资讯&#xff01; 导读 在数字化工厂和智能制造时…

【新手小白的xsslab靶场学习】

第1关 最开始页面源代码 直接输入<script>alert(1)</script> 第2关 页面源代码 先尝试<script>alert(1)</script>看页面源代码 <h2>里面尖括号被编码&#xff0c;<input>里面没有编码,直接双引号闭合&#xff0c; 修改payload&…

Python 数据库(一):使用 mysql-connector-python 操作 MySQL 数据库

大家好&#xff0c;我是水滴~~ 当涉及到使用 Python 操作 MySQL 数据库时&#xff0c;mysql-connector-python 库是一个强大而常用的选择。该库提供了与 MySQL 数据库的交互功能&#xff0c;使您能够执行各种数据库操作&#xff0c;如连接数据库、执行查询和插入数据等。在本文…

Unity ShaderGraph 技能冷却转圈效果

Unity ShaderGraph 技能冷却转圈效果 前言项目场景布置代码编写ShaderGraph 连线总结 参考 前言 遇到一个需求&#xff0c;要展示技能冷却的圆形遮罩效果。 项目 场景布置 代码编写 Shader核心的就两句 // 将uv坐标系的原点移到纹理中心 float2 uv i.uv - float2(0.5, 0…

安装VS Code到AWS EC2 Linux 2

文章目录 小结问题及解决参考 小结 本文记录了安装VS Code到AWS EC2 Linux 2。 问题及解决 安装VS Code到AWS EC2 Linux 2采取了以下步骤&#xff1a; 更新VS Code的YUM源&#xff1a; [ec2-userip-100-92-28-119 ~]$ sudo rpm --import https://packages.microsoft.com/k…