【Linux】进程通信 — 信号(上篇)
文章目录
- 📖 前言
- 1. 什么是信号
- 1.1 认识信号:
- 1.2 信号的产生:
- 1.3 信号的异步:
- 1.4 信号的处理:
- 2. 前后台进程
- 3. 系统接口
- 3.1 signal:
- 3.1 - 1 不能被捕捉的信号
- 3.2 kill:
- 3.2 - 1 killall
- 3.3 raise:
- 3.4 abort:
- 3.5 alarm:
- 4. 崩溃的本质是什么
- 4.1 Core Dump:
- 4.1 - 1 Core Dump打开方式
- 4.1 - 2 使用方式
- 4.1 - 3 默认关闭的原因
📖 前言
本章我们将讲解Linux信号这部分的内容,本章将介绍信号的产生,发送,信号的捕捉,屏蔽等操作,将对信号进行一些列系统的了解与学习。目标已经确定,接下来就要搬好小板凳,准备开讲了…🙆🙆🙆🙆
1. 什么是信号
1.1 认识信号:
- 在我们学习信号之前,我们先来回忆一下生活中的各种信号,例如:红绿灯、铃声、闹钟……
- 我们在能够认识这些场景下的信号以及所表示的含义:
-
- 即便这个信号还没有产生,我们就已经具备了处理这个信号的能力。
- 我们早就知道了信号产生后要做什么:
-
- 即便当前信号还没有产生,我们已经提前知道了这个信号的处理方法。
- 信号是给进程发送的,进程要具备处理信号的能力。
- 可以说程序员通过编写代码来利用操作系统提供的接口和功能,实现了处理信号的能力。
-
- 该能力一定是预先已经早就有了的。
-
- 进程能够识别对应的信号。
-
- 进程能够处理对应信号。
对于进程来讲,即便是信号还没有产生,我们进程已经具有识别和处理这个信号的能力了。
- 信号的种类:
使用kill -l
命令罗列出来的内容叫做信号,我们可以看到目前Linux系统下64种不同的类型:
- 没有32、33、0号信号。
- 第一批1 ~ 31(普通信号)
- 第二批34 ~ 64(实时信号)
信号左侧的数字和右侧的名称是一回事,其实都是宏,大写的字母是宏名称,宏的值就是左侧对应的编号。
这二者的差别是:早期有实时操作系统,我们现在用的是分时操作系统。
基于时间片轮转,基于优先级抢占的调度算法。
1.2 信号的产生:
有很多情况会产生信号:
- 系统接口(kill命令)
- 键盘产生(Ctrl + C,Ctrl + \ )
- 软件条件(进程停止,进程运行完退出)
- 硬件异常(比如除0错误)
信号发送的本质:
- 键盘是产生了信号,但是信号是操作系统发的。
- 在位图中,将对应的位置设置为1,就完成了信号的发送。
- 与其叫发送,不如叫操作系统向进程写入信号。
信号都是由操作系统向系统写入的:
- 计算机要是想向一个PCB进程发信号,本质上因为操作系统是进程的管理者。
- 可以直接以自身的身份来对进程的PCB数据结构的位图做任意修改。
崩溃现象就是底层代码引起了硬件的问题,进而被操作系统识别,然后操作系统将硬件问题识别成信号,然后向进程发送,然后终止进程。
1.3 信号的异步:
何为异步:
以点外卖为例,当外卖到了时,你可能正在忙着做其他事情,外卖员给你发了条取餐消息,但是你并不能立即去取。
此时我们知道自己的外卖到了(知道收到了信号),等手上的活忙完了再去取(过一会再去处理信号)。
同步和异步:
- 当节奏会受某个因素影响时,这叫同步。
- 当节奏不会受某个因素影响时,这叫异步。
信号可能在任何时候都能产生,可能是用户产生,也可能是操作系统产生的,这个产生对进程来讲是异步的。
因为信号产生是异步的:
- 当信号产生的时候,对应的进程可能正在做更重要的事情,我们进程可以暂时不处理这个信号!
- 也就是说进程可能不需要立即处理这个信号!
- 但是并不代表这个信号不会被处理!
1.4 信号的处理:
处理信号的三种行为:
- 默认动作。
- 忽略。
- 自定义动作。
信号的处理,也叫做信号的的捕捉,递达处理动作。
必须记住这个信号有没有,是什么信号:
- 信号被记录在了进程的PCB当中的:
-
- 有没有产生【比特位的内容1/0】
-
- 是什么信号产生【比特位的位置】
只有操作系统有这个权利,能直接修改这个
task_struct
内的数据位图!
OS
是进程的管理者,进程的所有的属性的获取和设置,只能由OS
来!!
无论信号怎么产生,最终一定只能是OS
帮我们进行信号的设置的!
2. 前后台进程
Ctrl + C
的本质是向前台进程发送信号。
我们死循环打印Hello World,在一直死循环期间,我们输入命令ls
并不会列出该目录下的文件名。
myproce跑起来之后,再输入其他指令是没用的,因为这个进程占用了前面bash所对应的终端。当前bash没法做命令行响应,此时这种进程叫做前台进程。
将进程放到后台:
26733是进程编号。
后台进程,可以执行命令行指令,但是用Ctrl + C终止不了了。
jobs查看后台进程:
fg 1
就将该进程提至前台了,再次Ctrl + C
就可以了。
补充:
- 前后端混打的时候,虽然会打印乱掉,混乱是很正常的因为缺少访问控制,信息交叉在一起。根据冯·诺依曼体系,我们输入的内容一定是先被进程拿到的,显示器之所以能看到,是因为给显示器也拷贝了一份,这叫回显。
- 不回显也可以的,就像Linux输入密码,不回显但是确实输进去了。
任务管理:
在Linux中,作业列表中的符号+
和-
表示了作业的状态。
- 符号"+"表示当前前台运行的作业。
- 符号"-"表示当前后台运行的作业。
如果没有"+“和”-"符号显示在作业列表中,则表示当前没有前台或后台运行的作业。作业列表可能是空的,也就是没有任何正在运行的作业。这通常发生在你没有在前台执行命令或
将任何作业放到后台时
。
bg指令:
要将一个正在前台运行的作业切换到后台运行,可以按下"Ctrl + Z",这会将该作业暂停,并返回到命令行界面。然后,可以使用"bg"
命令将作业放到后台继续运行,此时作业会继续执行,但不会再占用终端。
3. 系统接口
3.1 signal:
Ctrl + C
是向前台发送二号信号。
代码演示:
#include <iostream>
#include <unistd.h>
#include <signal.h>using namespace std;void handler(int signo)
{cout << "我是一个进程,刚刚获取了一个信号: " << signo << endl;
}int main()
{// 给该信号设置了回调捕捉,自定义动作// 这里不是调用handler方法,这里只是设置了一个回调,让SIGINT产生的时候,该方法才会被调用。// 如果不产生SIGINT,该方法不会被调用!// 当二号信号产生的时候,才调用后面的方法。signal(SIGINT, handler);signal(3, handler);sleep(3);cout << "进程已经设置完了" << endl; sleep(3);while (true){cout << "我是一个正在运行中的进程: " << getpid() << endl;sleep(1);}return 0;
}
注意:
- 给该信号设置了回调捕捉,自定义动作。
- 这里不是调用handler方法,这里只是设置了一个回调,让
SIGINT
产生的时候,该方法才会被调用。 - 如果不产生SIGINT,该方法不会被调用!!
- 当二号信号产生的时候,才调用后面的方法。
函数指针,回调函数:
- 函数指针类型,允许用户对信号自定义处理,忽略,自定义,默认。
- 大部分信号都有默认动作,而signal方法可以让进程对特定的信号自定义设置。
Ctrl + C
本质是给前台产生了2号信号,发送给目标进程,其中目标进程默认对2号信号的处理,是终止自己。- 更改了对二号信号处理,设置了用户自定义处理方法。
- 还有一种终止进程的方法是发送
3号信号
。
3.1 - 1 不能被捕捉的信号
- 到这里我们不禁思索一番,我们之前讲过
kill -9 + 进程ID
信号可以杀掉进程,那我们能否将kill -9 + 进程ID
的信号捕捉了呢?
- 经过实验,得到结论,
kill -9 + 进程ID
该信号并不能被捕捉,这是为了防止一些恶意进程杀不掉的情况。 - 因为9号信号不能被设置捕捉动作。永远都是默认动作,叫做管理员信号。
- 9号信号几乎可以杀掉所有进程,除了曾经讲的
D状态
的进程。进程状态复习-传送门
- 在Linux中,有一些信号被称为"不可捕捉信号",它们无法被用户进程捕捉或处理。这些信号是:
SIGKILL (信号编号为9)
:用于立即终止一个进程。无论进程是否希望接收该信号,都无法阻止或忽略它。SIGSTOP (信号编号为19或17)
:用于暂停一个进程的执行。与SIGKILL
类似,无法被捕捉或忽略。SIGCONT (信号编号为18或19)
:用于继续一个被暂停的进程的执行。与前两个信号不同,SIGCONT
是可以被捕捉的,但在默认情况下,它会立即恢复进程的执行。
这些不可捕捉信号通常由操作系统或其他系统级实体发送,用于管理进程的状态和行为。在正常情况下,用户进程无法阻止或修改这些信号的执行。
3.2 kill:
kill
不仅是命令而且也是系统调用接口:
- 向指定进程发送指定信号,成功了返回0,失败了返回-1。
- 支持向任意进程发送任意信号。
- 杀进程也是要有权限的。
不能杀掉不是自己的进程:
有了上述接口,再加上我们之前学的main函数的几个参数
,我们可以手搓一个kill
指令:
#include <iostream>
#include <string>
#include <cstdlib>
#include <cstring>
#include <cerrno>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>using namespace std;static void Usage(const string& proc)
{cout << "Usage:\n\t" << proc << "signo pid" << endl;
}// 自己实现一个kill命令
// mykill 9 1234
int main(int argc, char* argv[])
{if (argc != 3){Usage(argv[0]);exit(1);}if (kill(static_cast<pid_t>(atoi(argv[2])), atoi(argv[1])) == -1){cerr << "kill: " << strerror(errno) << endl;exit(2);}return 0;
}
3.2 - 1 killall
根据进程名字杀掉某个进程:killall + 进程名
。
- 在Linux中,killall命令用于终止同名进程。
killall
命令默认会发送SIGTERM
(信号编号为15)信号给目标进程。- 不过,你也可以使用参数"-s"或"–signal"来指定其他信号,例如
SIGKILL
(信号编号为9)。 - 这个命令非常有用,特别是当你想要快速终止所有同名进程时。
- 需要注意的是,使用
killall
命令要小心,确保只终止你想要终止的进程,以免造成意外的影响。
3.3 raise:
kill是给任意进程发任意信号,raise是给自己发任意信号:
进程不断地给自己发送2号信号:
#include <iostream>
#include <unistd.h>
#include <signal.h>using namespace std;void handler(int signo)
{cout << "我是一个进程,刚刚获取了一个信号: " << signo << endl;
}int main()
{// 这里没有调用对应的handler方法,仅仅是注册signal(2, handler);while (true){// 每次循环都给自己发送2号信号sleep(1);raise(2);}// 每隔1秒都会收到一个2号信号return 0;
}
3.4 abort:
向自己发送6号SIGABRT
信号:
#include <iostream>
#include <cstdlib>
#include <signal.h>
#include <unistd.h>using namespace std;void handler(int signo)
{cout << "我是一个进程,刚刚获取了一个信号: " << signo << endl;
}int main()
{// 这里没有调用对应的handler方法,仅仅是注册signal(6, handler);while (true){sleep(1);abort();// exit(), ahort();}return 0;
}
终止进程:
注意:
abort()
是即使捕捉了,但是依然会退出进程。- 除了9号信号不能被捕捉,对6号信号进行捕捉,但是依旧会退出。
硬件是在推着操作系统做一系列动作:
- 时钟硬件 —— 给操作系统发送时钟中断。
- CPU主频越高调度的频率就越高,效率就越高。
3.5 alarm:
#include <iostream>
#include <cstdlib>
#include <signal.h>
#include <unistd.h>using namespace std;int cnt = 0;void handler(int signo)
{cout << "我是一个进程,刚刚获取了一个信号: " << signo << "cnt: " << cnt << endl;exit(1);
}// 信号闹钟
int main()
{// 未来一秒钟之后会超时signal(SIGALRM, handler);alarm(1);// 如果没有自定义操作,默认alarm会自定义终止,会收到SIGALRM信号// 统计该进程一秒钟cnt++多少次while (1){cnt++;// cout << "hello: " << cnt++ << endl;}return 0;
}
相比于CPU独立做计算,IO
非常慢。
- 在Linux中,默认情况下,当alarm定时器到期时,会生成一个SIGALRM信号。 如果进程没有捕获和处理该信号,那么该进程会被终止。
SIGALRM
信号是用于告知进程某个定时器已经超时的信号。它通常由内核或通过使用alarm
函数设置的定时器触发。当定时器超时时,内核向进程发送SIGALRM
信号,进程可以选择捕获和处理该信号,或者使用默认操作(即终止进程)。- 如果进程没有显式地设置对
SIGALRM
信号的处理方式(通过信号处理函数或信号处理器),那么SIGALRM
信号将以默认操作的方式处理,即终止进程。这意味着如果定时器超时并且进程没有捕获该信号,进程会被终止。
4. 崩溃的本质是什么
在Linux中越界访问都叫段错误。
所谓的崩溃,本质是什么呢?
- 是该进程收到了异常信号,应该叫进程崩溃了。
进程崩溃是因为收到了异常信号,那么为什么会收到异常信号呢?
- 除零问题:计算是在CPU内部,内有状态寄存器,该寄存器是用来表征该本次计算是否出现问题。
- 如果有问题,状态寄存器中特定标志位会被计位。
C++ try catch:
- 崩溃了,一定会导致进程终止吗?不一定!!
-
- 崩溃,本质是什么呢?
-
- 进程崩溃的本质,是该进程收到了异常信号!
- 为什么呢?
- 因为硬件异常,而导致OS向目标进程发送信号,进而导致进程终止的现象!
-
- 除零: CPU内部,状态寄存器,当我们除0的时候,CPU内的状态寄存器会被设置成为,有报错:浮点数越界,CPU的内部寄存器(硬件),OS就会识别到CPU内有报错啦:
-
-
- 1.谁干的?2.是什么报错(OS -> 构建信号) -> 目标进程发送信号 -> 目标进程在合适的时候 -> 处理信号 -> 终止进程。
-
-
- 越界 && 野指针: 我们在语言层面使用的地址(指针),实都是虛拟地址 -> 物理地址 -> 物理内存 -> 读取对应的数据和代码的。
-
- 如果虚拟地址有问题,地址转化的工作是由(MMU(硬件) + 页表(软件)),转化过程就会引起问题 -> 表现在硬件MMU上 -> OS发现硬件出现了问题:
-
-
- 1.谁干的?2.是什么报错(OS -> 构建信号) -> 目标进程发送信号 -> 目标进程在合适的时候 -> 处理信号 -> 终止进程。
-
MMU是内存管理单元(Memory Management Unit)的简称。
实操注意:
- 当进程崩溃时,对某个信号进行时捕捉时:
-
- 要将自定义的handler函数最后exit(1);退出进程,不然会一直发信号,就会一直调用handler函数。
-
- 因为一般进程崩溃时,操作系统会给进程发送对应的信号并终止进程。
- 如果不加上最后的退出进程,会一直打印刷屏。
- 一旦我们不进行信号捕捉,会直接终止。
- 而我们捕捉之后如果没有对信号做处理,没有终止进程的话,会一直刷屏,进程没有被终止。
因为没有解决这个问题,这个异常一直都在,所以操作系统一直给进程发信号,所以刷屏了。
4.1 Core Dump:
Core Dump
会把进程在运行中,对应的异常上下文数据,core dump到磁盘上,方便调试。
发上云服务器是设置成0的,禁止发生core dump
(一般是关掉的),但是可以打开。
4.1 - 1 Core Dump打开方式
Core不光光要终止,还要发生Core dump。
8号信号本身就要产生core
文件的,然后指令发现多了一个文件,里面是乱码。
当一个进程异常退出时,收到了某些信号,系统为了便于用户调试,会告诉用户触发core dump
机制,core dump
机制叫做核心转储
。
4.1 - 2 使用方式
代码演示:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>using namespace std;int main()
{ pid_t id = fork();if (id == 0){// 子进程int *p = nullptr;*p = 1000; // 野指针问题exit(1);}// 父进程int status = 0;// nullptr, NULL, 0, '\0' == 0;waitpid(id, &status, 0); // nullptr// core dump表明当前进程在退出时,是否发生core dumpprintf("exitcode: %d, signo: %d, core dump flag: %d\n",(status >> 8) & 0xFF, status & 0x7F, (status >> 7) & 0x1);return 0;
}
核心转储(Core Dump)是指在程序运行过程中发生了严重错误导致程序崩溃时,系统将程序内存的完整快照保存到一个核心转储文件中。
- 这个文件包含了程序崩溃时的内存状态、寄存器的内容以及其他相关的调试信息。
- 核心转储文件主要用于程序崩溃分析和调试目的。通过分析核心转储文件,开发人员可以了解程序崩溃时的内存状态,定位错误的原因,并进行问题排查和修复。
- 核心转储文件通常具有可读性较低的二进制格式,需要使用调试工具或分析器来解析和分析。
- 在许多操作系统上,默认情况下,当程序崩溃时会自动生成核心转储文件。开发人员也可以在程序中通过设置相应的参数或使用调试工具来控制核心转储的生成及其行为。
- 需要注意的是,由于核心转储文件可能会包含敏感信息,如内存中的数据,因此在进行排查和分析时需要遵守相应的隐私保护规定,并确保核心转储文件的安全性。
生成的Core Dump
文件很大:
Core Dump一般配台gdb使用:
每次执行出错都会产生core dump文件,这种调试策略叫做事后调试。
4.1 - 3 默认关闭的原因
云服务器关掉的原因:
因为如果大型程序,一旦代码有问题,会自动重启程序,如果一重启就挂掉,就会产生core文件,所以一直重启就会产生大量的core文件,就很大概率将磁盘空间被打满,此时就会危及到操作系统正常工作了。
相关文章:

【Linux】进程通信 — 信号(上篇)
文章目录 📖 前言1. 什么是信号1.1 认识信号:1.2 信号的产生:1.3 信号的异步:1.4 信号的处理: 2. 前后台进程3. 系统接口3.1 signal:3.1 - 1 不能被捕捉的信号 3.2 kill:3.2 - 1 killall 3.3 ra…...

JS弃之可惜食之无味的代码冷知识
JS代码冷知识大全 1. 变量提升与暂死 在JavaScript中,变量提升是一个有趣且容易让人误解的概念。在代码中,变量和函数声明会在其所在作用域的顶部被提升,但是初始化并不会被提升。这可能导致在声明之前就使用变量,结果为undefin…...

数据结构初阶--排序
目录 一.排序的基本概念 1.1.什么是排序 1.2.排序算法的评价指标 1.3.排序的分类 二.插入排序 2.1.直接插入排序 2.2.希尔排序 三.选择排序 3.1.直接选择排序 3.2.堆排序 重建堆 建堆 排序 四.交换排序 4.1.冒泡排序 4.2.快速排序 快速排序的递归实现 法一&a…...

赴日IT 如何提高去日本做程序员的几率?
其实想去日本做IT工作只要满足学历、日语、技术三个必要条件,具备这些条件应聘就好,不具备条件你就想办法具备这些条件,在不具备条件之前不要轻易到日本去,日本IT行业虽然要求技术没有国内那么高,但也不是随便好进入的…...

c# 使用了 await、asnync task.run 三者结合使用
在 C# 异步编程中,await 和 async 关键字结合使用可以让你更方便地编写异步代码,而无需直接使用 Task.Run。然而,有时候你可能仍然需要使用 Task.Run 来在后台线程上执行某些工作,这取决于你的代码逻辑和需求。 await 和 async 关…...

C#获取屏幕缩放比例
现在1920x1080以上分辨率的高分屏电脑渐渐普及了。我们会在Windows的显示设置里看到缩放比例的设置。在Windows桌面客户端的开发中,有时会想要精确计算窗口的面积或位置。然而在默认情况下,无论WinForms的Screen.Bounds.Width属性还是WPF中SystemParamet…...

Rn实现省市区三级联动
省市区三级联动选择是个很频繁的需求,但是查看了市面上很多插件不是太老不维护就是不满足需求,就试着实现一个 这个功能无任何依赖插件 功能略简单,但能实现需求 核心代码也尽力控制在了60行左右 pca-code.json树型数据来源 Administrative-d…...

SpringCloud学习笔记(十)_SpringCloud监控
今天我们来学习一下actuator这个组件,它不是SpringCloud之后才有的,而是SpringBoot的一个starter,Spring Boot Actuator。我们使用SpringCloud的时候需要使用这个组件对应用程序进行监控与管理 在SpringBoot2.0版本中,actuator可以…...

测试理论与方法----测试流程的第二个环节:测试计划
二、软件测试分类与测试计划 1、软件测试的分类(理解掌握) 根绝需求规格说明书,在设计阶段会产出的两个文档: 概要设计(HLD):设计软件的结构,包含软件的组成,模块之间的层次关系,模块与模块之间的调用关系…...

postgresql-子查询
postgresql-子查询 简介派生表IN 操作符ALL 操作符ANY 操作符关联子查询横向子查询EXISTS 操作符 简介 子查询(Subquery)是指嵌套在其他 SELECT、INSERT、UPDATE 以及 DELETE 语句中的 查询语句。 子查询的作用与多表连接查询有点类似,也是为…...

Linux 系统运维工具之 OpenLMI
一、前要 OpenLMI(全称 Open Linux Management Infrastructure)即开放式的 Linux 管理基础架构。OpenLMI 是一个开源项目,用于管理 Linux 系统管理的通用基础架构。它建立在现有工具基础上,充当抽象层,以便向系统管理…...

8天长假快来了,Python分析【去哪儿旅游攻略】数据,制作可视化图表
目录 前言环境使用模块使用数据来源分析 代码实现导入模块请求数据解析保存 数据可视化导入模块、数据年份分布情况月份分布情况出行时间情况费用分布情况人员分布情况 前言 2023年的中秋节和国庆节即将来临,好消息是,它们将连休8天!这个长假…...

【HSPCIE仿真】输入网表文件(5)基本仿真输出
仿真输出 1. 概述1.1 输出变量1.2 输出分析类型 2. 显示仿真结果2.1 .print语句基本语法示例 2.2 .probe 语句基本语法示例 2.3 子电路的输出2.4 打印控制选项.option probe.option post.option list.option ingold 2.5 .model_info打印模型参数 3. 仿真输出参数的选择3.1 直流…...

uni-app中使用iconfont彩色图标
uni-app中使用iconfont彩色图标 大家好,今天我们来学习一下uni-app中使用iconfont彩色图标,好好看,好好学,超详细的 第一步 首先,从iconfont官网(iconfont-阿里巴巴矢量图标库)选择自己需要的图…...

Hystrix: Dashboard流监控
接上两张服务熔断 开始搭建Dashboard流监控 pom依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocat…...

iconfont 图标在vue里的使用
刚好项目需要使用一个iconfont的图标,所以记录一下这个过程 1、iconfont-阿里巴巴矢量图标库 这个注册一个账号,以便后续使用下载代码时需要 2、寻找自己需要的图标 我主要是找两个图标 ,一个加号,一个减号,分别加入到…...

QT登陆注册界面练习
一、界面展示 二、主要功能界面代码 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QMainWindow(parent), ui(new Ui::Widget) {ui->setupUi(this);this->setFixedSize(540,410); //设置固定尺寸th…...

MySQL DATE_SUB的实践
函数简介DATE_SUB()函数从DATE或DATETIME值中减去时间值(或间隔)。 下面说明了DATE_SUB()函数的语法: DATE_SUB(start_date,INTERVAL expr unit); DATE_SUB()函数接受两个参数: start_date是DATE或DATETIME的起始值。 expr是一个字符串,用于确…...

OpenCV最常用的50个函数
Python版:OpenCV提供了众多图像处理算子和函数,涵盖了各种任务和技术。以下是OpenCV中一些常用的50个算子和函数: cv2.imread:用于读取图像文件。cv2.imshow:用于显示图像。cv2.imwrite:用于保存图像。cv2…...

Android AGP8.1.0组件化初探
Android AGP8.1.0组件化初探 前言: 前面两篇完成了从AGP4.2到 AGP8.1.0的升级,本文是由于有哥们留言说在AGP8.0中使用ARouter组件化有问题,于是趁休息时间尝试了一下,写了几个demo,发现都没有问题,跳转和传…...

文件修改时间能改吗?怎么改?
文件修改时间能改吗?怎么改?修改时间是每个电脑文件具备的一个属性,它代表了这个电脑文件最后一次的修改时间,是电脑系统自动赋予文件的,相信大家都应该知道。我们右击鼠标某个文件,然后点击弹出菜单里面的…...

2023年下半年软考报名注意事项!
考试注意事项: 分数线:所有科目成绩全部在45分以上(含45分)通过考试;三科目的话,必须每科目都及格才算通过考试,只有一个不合格的,本次考试其他两个无效。 出成绩时间:预…...

【LeetCode每日一题】——274.H指数
文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【解题思路】八【时间频度】九【代码实现】十【提交结果】 一【题目类别】 排序 二【题目难度】 中等 三【题目编号】 274.H指数 四【题目描述】 给你一个整数数组 ci…...

网络编程 day 4
1、多进程并发服务器根据流程图重新编写 #include <myhead.h>#define ERR_MSG(msg) do{\fprintf(stderr, "__%d__:", __LINE__); \perror(msg);\ }while(0)#define PORT 8888 //端口号,范围1024~49151 #define IP "192.168.11…...

【Java架构-版本控制】-Git基础
本文摘要 Git作为版本控制工具,使用非常广泛,在此咱们由浅入深,分三篇文章(Git基础、Git进阶、Gitlab搭那家)来深入学习Git 文章目录 本文摘要1.Git仓库基本概念1.1 远程仓库(Remote)1.2 本地库(Repository) 2. Git仓库…...

ubuntu 挂载硬盘操作
1. 查看磁盘 sudo fdisk -l 2. 查看UUID sudo blkid记录下待挂载硬盘的UUID, 后面要使用 ps. 如果报错,检查是否已格式化硬盘 查看新硬盘的盘符,我的是/dev/sda,用下述命令格式化 sudo mkfs -t ext4 /dev/sda3. 创建挂载点 我的是在/mnt…...

关于商品活动的H5页面技术总结
背景 在单个html文件里面使用vue3、jquery等其他第三方js库,实现规定的页面效果,其中主要功能是从商品json数据中读取数据,然后可以通过搜索框、下拉框、左侧菜单来筛选商户信息。 页面布局 技术要点: 1、通过路由来进行页面布…...

前端:横向滚动条,拖动进行左右滚动(含隐藏滚动条)
效果 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width, i…...

Android JNI Bitmap指定颜色值替换
#include <jni.h> #include <string> #include <android/bitmap.h> #include <cmath> #include <android/log.h> //定义TAG之后,我们可以在LogCat通过TAG过滤出NDK打印的日志 #define TAG "BitmapOperationNative" // 定义…...

测试理论与方法----测试流程的第四个步骤:执行测试,提出缺陷
8、执行测试—–>提交缺陷报告 测试流程:执行测试—–>提交缺陷报告 1、缺陷的概述(回顾) 结果角度:实际结果和预期结果不一致 需求角度:所有不满足需求或超出需求的,都是缺陷 2、缺陷的相关属性…...