4.进程相关 2

8.内存映射

8.1 内存映射相关定义

创建一个文件,将保存在磁盘中的文件映射到内存中,后期两个进程之间对内存中的数据进行操作,大大减少了访问磁盘的时间,也是一种最快的 IPC ,因为进程之间可以直接对内存进行存取

image-20211113112315578

8.2 内存映射相关的系统调用

代码地址:lesson25

8.2.1 mmap & munmap 函数–内存的映射与释放

1.API

image-20211113120051909 image-20211113120531666

mmap : 将一个文件映射到内存中

这个函数返回的是内存映射出来的内存首地址

munmap : 解除一个文件和内存的映射

内存映射和管道不一样,内存映射不会发生阻塞

2.代码

通过内存映射的方法实现两个关系进程之间的通信

①导入相应的库文件

#include <sys/mman.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <wait.h>

②将一个文件映射到内存区

int fd = open("test.txt",O_RDWR);
int size = lseek(fd,0,SEEK_END); // 获取文件大小:从index0 到 index_end
// 创建映射
void* ptr = mmap(NULL,size,PROT_READ | PROT_WRITE,MAP_SHARED,fd,0); // prot :内存映射区域的权限,一般读写都有;flag:本地文件是否和盘文件同步
if(ptr==MAP_FAILED){perror("mmap");exit(0);
}

③父进程:等待子进程写入数据并读出来;子进程:将数据写入到内存中

// 创建子进程
pid_t pid = fork();
if(pid>0){ // 父进程读取文件wait(NULL); // 等待子进程写完内存映射区后再去读文件char buf[64];strcpy(buf,(char*)ptr); //拷贝字符串printf("read data:%s\n",buf);
}else if(pid==0){// 子进程向映射区写入数据strcpy((char*)ptr,"xuboluo");}

④关闭映射

munmap(ptr,size);

3.代码演示

最后可以看到这里在对内存映射时文件中的文字是进行覆盖的

image-20211113123424599

8.2.2 mmap & munmap 内存的映射与释放 中常见问题

image-20211113125008844

可以对其 ++ 操作更改内存映射的开始地址,这样在写文件时就可以从指定的位置开始写

但是在进行释放内存时要传入正确的释放地址,也就是一开始系统给分配的地址

image-20211113125229391

映射的权限要小于等于文件 open 时的权限

3.

image-20211113130902882

文件偏移量的作用就是:指明从文件的哪个地方开始映射,如下图:

image-20211113125555251

一般页面大小为 4K ,虚拟内存空间的大小也为 4K

image-20211113130019986
image-20211113130436495

映射的文件大小必须要 >0 ,这样在分配虚拟内存时才能保证能分配到空间。可以使用相应的方法扩展内存

image-20211113130733355

创建映射区时会对文件描述符进行一个拷贝,即使文件被关闭也不会有影响

image-20211113131017747

8.2.3 使用内存映射实现文件拷贝

代码保存在 lesson25 copy.c 中

1.基本思路

image-20211113131247503

现在硬盘中有两个文件 A 和 B ,A 文件和 B 文件分别映射到内存当中,并获得相应的 map_ptr ,两个 ptr 之间进行通讯

image-20211115103234035

2.代码实现

#include <string.h>
#include <stdlib.h>int main(){// 1.得到两个文件的文件描述符int fd_a = open("a.txt",O_RDWR);int fd_b = open("b.txt",O_RDWR | O_CREAT,0664);// 2.得到文件大小int len = lseek(fd_a,0,SEEK_END);// 对新建的文件进行扩展truncate("b.txt",len);write(fd_b," ",1);// 3.得到文件映射int* ptr_a = mmap(NULL,len,PROT_WRITE | PROT_READ,MAP_SHARED,fd_a,0);int* ptr_b = mmap(NULL,len,PROT_WRITE | PROT_READ,MAP_SHARED,fd_b,0);//4.内存拷贝memcpy(ptr_b,ptr_a,len); // 目标文件,源文件,长度// 5.释放资源munmap(ptr_a,len);munmap(ptr_b,len);// 6.关闭两个文件流close(fd_a);close(fd_b);return 0;
}

3.代码演示

b.txt 文件原本是不存在的空文件,拷贝后有了 a.txt 的内容

image-20211115111459381

image-20211115111316090

8.2.4 文件的匿名映射

代码保存在 lesson25 mmap-anon.c

有时候不存在真正的文件实体,不需要文件这个中介进行通信。比如说进程将读到的内容直接传递给子进程

文件的匿名映射只能存在于有关系的两个进程之间

1.代码实现

创建一个父进程将读到的 string 中的信息直接传递给子进程。关键代码是需要在 mmap 映射时添加匿名映射的属性

MAP_ANONYMOUS
#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>
int main(){// 1.定义内存映射区的大小。以往都是根据文件大小来int len = 4096;void* ptr = mmap(NULL,len,PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANONYMOUS,-1,0);// 2.父子间进程通信pid_t pid = fork();if(pid>0){// 父进程向内存缓冲区写入内容strcpy((char*)ptr,"hello world");wait(NULL);}else if(pid ==0){// 子进程读取内存映射的内容sleep(1); // 先等父进程写完printf("%s\n",(char*)ptr);}//3.释放映射int ret = munmap(ptr,len);return 0;
}

2.代码演示

最后可以看到虽然没有创建文件但还是实现了两个进程之间的通信

image-20211115114929119

9.信号

9.1 信号的基本概念

1.定义

软件中断就是指当有另一个进程到达时此进程暂停当前任务去执行另一个进程的任务。等待另一个进程执行完毕再返回到刚才的任务继续执行,是一种异步通信方式。

信号 == 软件中断

image-20211115120011525

2.中断发生的场景

  • 对于前台进程用户输入了特殊的符号比如 Ctrl+c ,这时就向进程发了一个中断信号
  • 硬件发生异常,硬件检测到一个错误条件并通知内核,随即硬核再发送相关信号通知进程。比如执行了一条异常的机器指令或者被 0 除,或者访问了一块无法访问的内存区域
  • 系统状态的变化,定时器到期引起 SIGALRM 信号,进程执行的 CPU 时间超限或者该进程的某个子进程退出
  • 执行 kill 命令或者调用 kill 函数

信号主要是软中断,告诉另一个进程可以执行了,所以说信号(软中断)也是一种进程通讯的方式

3.信号特点

简单,不能携带大量信息,满足某个特定条件才发送,优先级高

9.2 信号介绍

使用 kill -l 就可以看到所有的信号

前 31 个为常规信号,其余为实时信号

image-20211115121613069

只看红色部分

image-20211115121641643 image-20211115121700250 image-20211115121729367 image-20211115121751672

-9 SIGKILL

SIGCHLD:子进程结束时,父进程会收到这个信号

下图中的 Core 文件是指我们在终止进程时对于中止进程保存的相关信息

image-20211115122917978
man 7 signal // 查看信号指令

可以发现有的信号用三个数字表示,这是因为不同的系统架构造成的,我们在使用这些信号时选择中间的数字即可

SIGKILL and SIGSTOP 不能被捕捉,不能被阻塞,也不能被忽略

image-20211115122434497

9.2.1 Core 文件保存中断中间变量

2.代码

这里定义一个会报错的代码,定义一个 string ,但是不将这个 string 进行初始化,直接对其赋值,那么最终也会导致一个 “段错误” 的出现


3.代码演示

这里会爆出一个段错误,主要是因为没有进行一个争取的段地址映射而产生的

image-20211115124210107

4.添加 Core 文件

首先使用下面的指令查看和更改 Core 文件的大小,并且看到系统分配的 core 文件大小为 0

ulimit -a
image-20211115124835872

使用下面代码更改生层的 Core 文件大小

ulimit -c 1024 // 定义 Core 文件的大小为 1024
image-20211115125045580

因为我的代码没有显示对应的效果,所以这里用了视频中的演示

image-20211115130718582 image-20211115130835667

我们通过 gdb 的方式对 core 文件进行查看,里面说他是在执行 a.out 文件时产生的,执行了进程的终止并且是因为段错误发送了 SIGSEGV 信号

image-20211115130920338

9.3 发送信号的相关函数

image-20211115123141496

9.3.1 Kill–给指定进程发送信号

1.API

image-20211115132612396

2.代码

实现 kill -9 操作

关键代码:

kill(pid, SIGINT);
#include<stdio.h>
#include<sys/types.h>
#include<signal.h>
#include<unistd.h>int main(){pid_t pid = fork();if(pid == 0) {// 子进程int i = 0;for(i = 0; i < 5; i++) {printf("child process\n");sleep(1);}} else if(pid > 0) {// 父进程printf("parent process\n");sleep(2);printf("kill child process now\n");kill(pid, SIGINT);}return 0;
}

3.代码演示

image-20211115134817081

9.3.2 raise --给当前进程发送信号

1.API

man 3 raise 中查看相关文档

这个函数可以由 kill 函数实现

image-20211115132806197

9.3.3 abort–杀死当前进程

1.API

这个函数可以由 kill 函数实现

image-20211115132909178

9.3.4 alarm 定时器–在一定的时长之后发送信号

1.API

定时器只能设置一次,后面再设置定时器还是按照第一次的时间进行倒计时

而且不管进程是什么状态 alarm 都会执行

image-20211115135754550

2.代码

设置一个定时器

#include<stdio.h>
#include<unistd.h>
int main(){int seconds = alarm(5); // 设置一个 5 s 是定时器sleep(2);seconds = alarm(1); // 这个闹钟无效printf("second=%d\n",seconds); // 3while(1){}return 0;
}

3.代码演示

虽然在 5 秒的闹钟后加闹钟加快,但是最后得到的闹钟还是 3 秒的剩余时间,也就是按照第一次闹钟定时

image-20211115140736980

4.计数器代码实现

计数器实现电脑 1s 可以数多少个数

#include<stdio.h>
#include<unistd.h>int main(){alarm(1); // 1s 之后杀死自己int i = 0;while(1){printf("%i\n",i++);}return 0;
}
image-20211115141644689

5.程序的运行时间

程序真正的运行时间 = 内核时间+用户时间(程序真正的运行时间)+消耗的时间(比如文件 IO 操作打开关闭消耗的时间)

9.3.5 setitimer–实现周期性定时

1.API

这个定时器可以根据周期设置在多少时间之后启动,每隔多少秒启动一次

image-20211116104853148

2.代码

关键代码:

如何定义结构体 new_value

int ret = setitimer(ITIMER_REAL,&new_value,NULL);

#include<sys/time.h>
#include<stdlib.h>
#include<stdio.h>
int main(){// 定义结构体属性参数struct itimerval new_value;// 过3秒后每隔2秒进行一次定时new_value.it_interval.tv_sec=2; // 每隔 2s 唤醒一次定时器new_value.it_interval.tv_usec = 0;new_value.it_value.tv_sec = 3; // 3 秒之后在设置这个定时器new_value.it_value.tv_usec = 0;// 设置一个周期定时器int ret = setitimer(ITIMER_REAL,&new_value,NULL);printf("定时器开始了");if(ret==-1){perror("setitimer");exit(0);}getchar(); // 防止进程提前终止return 0;
}

3.代码实现

首先是先打印:定时器开始了

在 3s 之后打印 Alarm clock

image-20211116093952705

9.4信号捕捉函数

9.4.1 signal 捕捉信号

1.API

在定义信号之前定义捕捉信号的函数

捕捉到信号,然后执行自己想执行的事情

image-20211116095343888

在形参中需要传入一个 sighandler ,通过前面定义发现这是一个回调函数

image-20211116095837103

2.代码

signal(SIGALRM,SIG_IGN);  // 忽略信号

3.代码演示

忽略信号:

刚才使用 setitimer 定义了一个信号,这里使用 signal 对信号忽略,可以看到它就一直在要求用户输入的地方,不会终止程序

image-20211116103347686

默认信号执行:

时隔3s后执行 Alarm clock

image-20211116103708238

执行回调函数:

在 3s 之后 signal 捕捉到第一个信号;然后每隔 2s 就会捕捉到另一个信号,捕捉到信号后执行相应的 handler 函数。执行完 handler 函数后程序继续执行下一个信号的发送(并没有终止程序)

image-20211116104502130

9.4.2 信号集的捕捉

1.API

(1)什么是信号集

PCB 中有两个信号集:阻塞信号集和未决信号集。我们可以借助信号集操作函数对这两个信号集进行操作

阻塞信号集:

将某些信号加⼊集合,对他们设置屏蔽,当屏蔽x信号后,再收到该信号,该信号的处理将推后(处理发⽣在解除屏蔽后)

未决信号集:

这个信号还没有被处理。信号产⽣,未决信号集中描述该信号的位⽴刻翻转为1,表示信号处于未决状态。当信号被处理对应位翻转回为0。这⼀时刻往往⾮常短暂。

(2)如何处理信号

根据信号集中的值处理信号,1 代表这个信号被阻塞不能执行(未决),0 代表信号可以抵达,未决信号集中的值根据阻塞信号集中信号的变化而变化

e.g. : 当前的处理的信号 index 为 2 也就是 SIGINT 信号:

阻塞信号集中的值为 0 ,未决信号集看到阻塞信号集他的值为 0 ,也就是说不阻塞,则未决信号集中的值也变成 0

阻塞信号集中的值为 1 ,未决信号集看到阻塞信号集他的值为 1 ,先暂时将这个信号进行挂起,直到信号不阻塞了,未决信号的值再变为0

如果有更多的阻塞信号到达只能被丢弃

image-20211116112326615

信号集

(3)操控信号集的常见函数

image-20211116113405201
#include <signal.h> 
int sigemptyset(sigset_t *set); // 将set集合置空
int sigfillset(sigset_t *set); // 将所有信号加⼊set集合
int sigaddset(sigset_t *set, int signo); // 将signo信号加⼊到set集合
int sigdelset(sigset_t *set, int signo); // 从set集合中移除signo信号
int sigismember(const sigset_t *set, int signo); // 判断信号是否存在

信号集的数据结构

sigset_t

2.代码

#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>int main(){// 1.定义一个信号集sigset_t set;// 2.清空信号集中的内容sigemptyset(&set);// 3. 判断信号是否还在信号集 set 中,即它是否被阻塞int ret = sigismember(&set,SIGINT);if(ret==1){printf("设置阻塞成功\n");}else if(ret==0){printf("设置阻塞失败\n");}// 4. 添加几个信号到信号集中sigaddset(&set,SIGINT);sigaddset(&set,SIGQUIT);// 5.判断添加的信号是否在信号集中ret = sigismember(&set,SIGINT);if(ret==1){printf("被阻塞了\n");}else if(ret==0){printf("没有被阻塞\n");}return 0;
}

3.代码演示

根据上面的代码可以看出,我们先对信号集中的信号进行清空,然后查看信号集中的成员。然后再设置信号再次查看信号集中的成员

image-20211116121318103

9.4.3 sigaction—信号捕捉函数

代码保存在 lesson26 sigaction.c 中

1.API

类似于 signal 函数捕捉信号

#include <signal.h>
/**
* 检查或修改指定信号的设置(或同时执⾏这两种操作).
* @param signum 要操作的信号.
* @param act 要设置的对信号的处理⽅式(传⼊参数).
* @param oldact:一般不用:原来对信号的处理⽅式(传出参数) . *
* 如果 act 指针⾮空,则要改变指定信号的处理⽅式(设置),
* 如果 oldact 指针⾮空,则系统将此前指定信号的处理⽅式存⼊ oldact.
*
* @return 成功: 0; 失败: -1.
*/
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

数据结构:

struct sigaction {
void(*sa_handler)(int); // 信号处理函数指针
void(*sa_sigaction)(int, siginfo_t *, void *); // 一般不用:新的信号处理函数指针
sigset_t sa_mask; // 临时信号阻塞集,在信号捕捉函数执行过程中,临时阻塞某些信号
int sa_flags; // 使用哪个信号处理函数处理信号,0:sa_handler,SA_SIGINFO :sa_sigaction
void(*sa_restorer)(void); //已弃⽤
};

sigaction 讲解

2.代码

首先设置一个定时器不断的发送信号,然后使用 sigaction 捕捉信号,捕捉到信号后执行相应的操作,操作结束后程序继续执行

关键代码:

定义信号捕捉函数,重点在于如何定义结构体变量

// 定义 act
struct sigaction act;
act.sa_flags = 0;// 使用 handelr 进行处理
act.sa_handler = my_alarm;
sigemptyset(&act.sa_mask); // 清空临时信号集
// 注册信号捕捉函数
sigaction(SIGALRM,&act,NULL);

捕捉到信号后进行的操作

// 捕捉信号后处理的函数
void my_alarm(int num){printf("捕捉到一个信号%d\n",num);printf("进行相应的处理\n");}

3.代码演示

image-20211117113446070

9.4.5 信号捕捉流程及特性

1.流程

image-20211117114739079

(1)程序在 main 函数中执行,运行到某一行时发现需要中断然后程序就运行到内核

(2)内核使用 do_signal 函数处理递送的信号

(3)内核判断信号处理函数是否是用户自定义的,如果是用户自定义的函数则再返回到用户区执行相应的信号处理函数

(4)信号处理函数处理完成后调用 sigreturn 返回到内核

(5)从内核再返回用户区,继续刚才没有执行完的 main 程序执行

2.特性

(1)内核中有一个阻塞信号集,信号捕捉时也有一个临时信号集,当信号捕捉结束后会返回到系统中的阻塞信号集

(2)当两个信号同时发生,后面的阻塞信号要等前面的阻塞信号处理完毕才能接着处理

(3)阻塞的常规信号是不支持排队的,因为信号集的个数只能由 01表示,其他来的阻塞信号要全部被丢弃

9.4.6 SIGCHLD 信号

代码保存在 lesson26 sigchld.c 中

1.子进程什么时候会向父进程发送 SIGCHLD 信号

子进程会向父进程发送 SIGCHLD 信号,以下三种情况发生时子进程就会想父进程发送 SIGCHLD 信号,默认情况下父进程会忽略该信号

image-20211117120333156

1.子进程终止时

2.代码

首先注册阻塞信号集,并将其添加到系统阻塞信号集中。其次开启子进程,子进程执行相应方法。当子进程执行完毕后父进程对子进程进行回收,回收完毕接着执行自己的代码

调用相应的库文件:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <sys/wait.h>

注册信号阻塞集,将其添加到系统信号阻塞集中

// 提前设置好阻塞信号集阻塞 SIGCHLD ,有可能因为子进程结束父进程还没有注册阻塞信号集就没有办法阻塞子进程
sigset_t set; // 定义信号集
sigemptyset(&set); // 将信号集中的信号清空
sigaddset(&set,SIGCHLD); // 添加对子进程阻塞的监听
sigprocmask(SIG_BLOCK,&set,NULL); // 将定义的阻塞信号集添加到系统的阻塞信号集中

信号处理函数,即回收子进程

void my_handler(int num){printf("捕捉到的信号:%d\n",num);// 回收子进程 pcb 资源,防止有漏掉的子进程while(1){int ret = waitpid(-1,NULL,WNOHANG); // 进程回收if(ret>0){printf("child die ,pid=%d\n",ret);}else if(ret==0){ // 还有子进程没有完全回收break;}else if(ret==-1){ // 完全回收break;}}
}

创建子进程

// 创建子进程
pid_t pid;
for(int i=0;i<5;i++){pid = fork();if(pid==0) break;
}

父进程不断执行,并不断监听子进程发出的 SIGCHLD 信号

if(pid>0){// 捕捉子进程死亡时 SIGCHLD 信号struct sigaction act;act.sa_flags = 0;act.sa_handler = my_handler;sigemptyset(&act.sa_mask); // 将临时阻塞进程集设置为空sigaction(SIGCHLD,&act,NULL);// 注册完信号捕捉后解除阻塞sigprocmask(SIG_UNBLOCK,&set,NULL);while(1){ // 父进程保持执行状态printf("parent process pid:%d\n",getpid());sleep(2);}}

子进程的相关函数

else if(pid==0){printf("child process pid:%d\n",getpid());}

3.代码演示

image-20211117134750357

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

面试经典算法系列之双指针1 -- 合并两个有序数组

面试经典算法题1 – 合并两个有序数组 LeetCode.88 公众号&#xff1a;阿Q技术站 问题描述 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中&#…

【讲解下Fiddler的安装和使用】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

宠物救助系统|基于Springboot和vue的流浪猫狗救助救援系统设计与实现(源码+数据库+文档)

宠物救助目录 基于Springboot和vue的流浪猫狗救助救援系统设计与实现 一、前言 二、系统设计 三、系统功能设计 1、前台&#xff1a; 2、后台 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌…

面试经典算法系列之链表2 -- 环形链表

面试经典算法8-环形链表 LeetCode.141 公众号&#xff1a;阿Q技术站 问题描述 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&am…

【C++成长记】C++入门 |函数重载、引用、内联函数

&#x1f40c;博主主页&#xff1a;&#x1f40c;​倔强的大蜗牛&#x1f40c;​ &#x1f4da;专栏分类&#xff1a;C❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、函数重载 1、函数重载概念 二、引用 1、引用概念 2、引用特性 3、常引用 4、使用场景 5、…

数据库之DCL操作(用户、访问权限。)

DCL英文全称是Data control language(数据控制语言)&#xff0c;用来管理数据库用户、控制数据库的访问权限。 1.管理用户 1.1查询用户 select * from mysql.user; 其中 Host代表当前用户访问的主机&#xff0c;如果为localhost&#xff0c;仅代表只能够在当前本机访问&…

深入浅出 -- 系统架构之微服务中OpenFeign最佳实践

前面我们讲了一下 Ribbon 和 RestTemplate 实现服务端通信的方法&#xff0c;Ribbon 提供了客户端负载均衡&#xff0c;而 RestTemplate 则对 http 进行封装&#xff0c;简化了发送请求的流程&#xff0c;两者互相配合&#xff0c;构建了服务间的高可用通信。 但在使用后也会发…

谁在投资“元素周期表”? 顶级芯片制造商“军备竞赛”

有色和商品基金的大买家何在 投资A股&#xff0c;有时候投资的也是一种“玄妙”的境界。 你需要复习金融知识、复习经济知识&#xff0c;复习科技知识&#xff0c;学习财政学、学习人口学、学习传染病学。 但这些可能还不够。 你能想象么有朝一日&#xff0c;你会回头复习中…

Flask项目如何在测试环境和生产环境部署上线

前言 最近在使用Flask框架&#xff0c;写一个小项目&#xff0c;在项目部署启动后&#xff0c;出现了以下这段提示&#xff0c;这段提示的意思是&#xff0c;该启动方式适用于开发环境中&#xff0c;生产环境要使用WSGI服务器。 WARNING: This is a development server. Do no…

OSCP靶场--Zino

OSCP靶场–Zino 考点(CVE-2019-9581 RCE 定时任务脚本可写提权) 1.nmap扫描 ##┌──(root㉿kali)-[~/Desktop] └─# nmap 192.168.173.64 -sV -sC -Pn --min-rate 2500 -p- Starting Nmap 7.92 ( https://nmap.org ) at 2024-04-10 04:18 EDT Nmap scan report for 192.…

自定义注解进行数据转换

前言&#xff1a; Java注解是一种元数据机制&#xff0c;可用于方法&#xff0c;字段&#xff0c;类等程序上以提供关于这些元素的额外信息。 以下内容是我自己写的一个小测试的demo,参考该文章进行编写&#xff1a;https://blog.csdn.net/m0_71621983/article/details/1318164…

【linux】基础IO(四)

在上一篇基础IO中我们主要讲述了文件再磁盘中的存储&#xff0c;当然我们说的也都只是预备知识&#xff0c;为这一篇的文件系统进行铺垫。 目录 搭文件系统的架子&#xff1a;填补细节&#xff1a;inode&#xff1a;datablock[]: 更上层的理解&#xff1a; 搭文件系统的架子&a…

uniapp 2.0可视化工具:创建与管理Vue文件的实践之旅

引言 在前端开发领域中&#xff0c;Vue以其简洁、易上手的特点&#xff0c;受到了广大开发者的青睐。随着uniapp的不断发展&#xff0c;越来越多的开发者开始利用uniapp的可视化工具来创建和管理Vue文件&#xff0c;以提高开发效率。本文将详细介绍如何使用uniapp 2.0可视化工…

bytetrack复现

一,环境安装 创建虚拟环境 conda create -n bytetrack python=3.8 安装requirements pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple 可能报错,解决办法,安装numpy 安装 pytorch pip install torch==1.12.0+cu113 torchvision==0.13.0+cu1…

H5动效开发之CSS3动画

动画效果是情感设计的重要手段,在H5开发中,实现动效需要综合利用 JavaScript、CSS(3)、SVG、Canvas 等多种 Web 技术手段才能开发出动人的网页动态效果。 接下来,我们把重心放在 CSS3 动画上面,因为 CSS3 在现如今的网页动效开发中占据着最为重要的一席,作为老大哥 CSS 的…

基于SSM+Jsp+Mysql的超市管理系统

开发语言&#xff1a;Java框架&#xff1a;ssm技术&#xff1a;JSPJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包…

SuperMap GIS基础产品FAQ集锦(202403)

一、SuperMap GIS基础产品桌面GIS-FAQ集锦 问题1&#xff1a;【iDesktop】安装了idesktop 11i&#xff0c;现想进行插件开发&#xff0c;根据安装指南安装SuperMap.Tools.RegisterTemplate.exe&#xff0c;运行多次均失败 【问题原因】该脚本是之前老版本针对VS2010写的&…

uniapp开发小程序,点击右上角<重新进入小程序>进行刷新时,设置开屏加载页面

一、需求及问题 问题&#xff1a;使用uniapp开发小程序时&#xff0c;有【学生端】和【企业端】两个入口&#xff0c;一进入小程序默认进入【学生端首页】&#xff0c;但是当前处于【企业端】时&#xff0c;点击右上角<重新进入小程序>进行刷新时&#xff0c;页面默认进…

国内如何实现GPT升级付款

本来想找国外的朋友代付的&#xff0c;但是他告诉我他的信用卡已经被绑定了他也升级了所以只能自己想办法了。就在一位博主下边发现了这个方法真的可以。只是需要与支付宝验证信息。刚开始不敢付款害怕被骗哈哈&#xff0c;我反诈骗意识绝对杠杠的 该方法就是我们办理一张虚拟…

每天五分钟深度学习PyTorch:面对Tensorflow,为何我选择PyTorch

这篇专栏文章不是为了挑起tenserflow和pytorch中哪个更好&#xff0c;众所周知tensorflow诞生以来&#xff0c;已经成为最流行的深度学习框架&#xff0c;可以说github中大多数的深度学习代码实现是以tensorflow实现的&#xff0c;也就是说资源众多&#xff0c;社区强大&#x…