【linux】进程理解

🔥个人主页:Quitecoder
🔥专栏:linux笔记仓

目录
- 01.进程的基本概念
- 进程的组成部分
- 进程的特性
- 进程的状态
- 02.PCB
- PCB的组成部分
- task_struct
- `task_struct` 的主要组成部分
- 03.进程属性
- 查看进程
- 04.通过系统调用创建进程-fork初识
- 工作原理
- 返回值
- 使用示例
- 用途和重要性
- fork返回值
- 一次创建多个进程
01.进程的基本概念
在计算机科学中,进程是操作系统中的一个基本概念,代表了计算机程序的一次执行实例。进程不仅包括正在执行的程序代码,还包括程序的当前活动,包括程序计数器的当前位置、处理器的寄存器和变量的值。简而言之,进程是一个具有自己独立功能的程序在某个数据集上的运行过程,它可以分配和管理资源。
进程的组成部分
- 程序代码(文本段):这是静态的程序指令,是进程执行的实际代码。
- 当前活动:
- 程序计数器:指示接下来要执行的指令位置。
- 寄存器集:存储指令执行前后的中间值。
- 堆栈(栈段):用于存储执行期间的局部变量、函数参数、返回地址等。
- 数据段:包括全局变量和静态变量,它们在程序启动时被初始化,程序结束时销毁。
- 堆:用于动态内存分配,即程序运行时根据需要进行分配和释放的内存。
进程的特性
- 动态性:进程是程序的一次执行过程,它有创建、运行、等待、终止等多种状态。
- 并发性:多个进程可以在一个或多个处理器上并发执行。
- 独立性:进程是资源分配和调度的独立单位,具有独立的地址空间和系统资源。
- 结构性:进程可以拥有子进程,形成进程的层次结构。
进程与线程的区别
虽然进程和线程都是独立调度的执行单位,但进程拥有完全独立的地址空间,而线程则是进程内的一个相对独立的、可调度的执行单元,与同属一个进程的其他线程共享地址空间和资源。
进程的状态
进程在其生命周期中可能会经历几种状态:
- 新建状态:进程正在被创建。
- 就绪状态:进程已准备好运行,等待CPU时间。
- 运行状态:进程正在CPU上执行。
- 等待/阻塞状态:进程等待某个事件发生(如输入/输出操作完成)。
- 终止状态:进程完成执行或被终止。
02.PCB
在操作系统中,进程控制块(Process Control Block, PCB) 是一个关键的数据结构,它用来存储和管理与特定进程相关的所有信息。每当操作系统创建一个新的进程时,都会为这个进程分配一个PCB,作为管理该进程的核心。PCB是操作系统内核用于进程调度和管理的主要工具。
PCB的组成部分
PCB通常包括以下几个关键的组成部分,以便于完整描述一个进程的状态和属性:
-
进程标识符(Process Identifier, PID):
- 每个进程都有一个唯一的标识符(PID),用于在系统中唯一地标识该进程。
-
处理器状态信息:
- 包括程序计数器(PC),指明当前正在执行或下一个要执行的指令地址。
- 包括CPU寄存器的内容(如通用寄存器、累加器等),它们需要在进程切换时被保存和恢复。
-
进程调度信息:
- 包括进程优先级、进程调度状态(如就绪、运行、等待等),以及其他与调度相关的信息。
- 处理器时间片(时间片调度情况下)和其他调度参数。
-
内存管理信息:
- 包括指向进程地址空间的信息,如基址寄存器、边界寄存器、页表信息或段表信息。
- 描述进程内存使用情况,如用户栈指针等。
-
会计信息(Accounting Information):
- 包括CPU使用时间、进程创建时间、用户时间和系统时间等统计信息。
- 可能还包括系统资源使用情况(如I/O操作次数、使用内存页的数量等)。
-
I/O状态信息:
- 包括与进程相关的I/O设备、I/O请求列表和状态。
- 进程使用的I/O文件相关信息,如文件描述符表。
-
进程上下文信息:
- 用于保存进程在切换时的上下文,以便后来可以恢复进程的状态。
- 包含中断处理代码所需的信息。
PCB的重要性
- 进程调度:PCB是操作系统进行进程调度的关键依据。调度程序根据PCB中的信息决定哪个进程将获得CPU执行时间。
- 状态切换:在多任务操作系统中,CPU在不同进程之间切换时,需要保存和恢复进程的状态,这由PCB完成。
- 资源管理:通过PCB,操作系统可以跟踪和管理进程所使用的所有资源,从内存到I/O设备。
PCB是操作系统核心的一部分,它把进程的执行信息与调度、资源管理密切结合。在进程间切换时,操作系统通过保存和恢复PCB中的信息,使不同进程能够即时停下和继续执行,从而保证系统的多任务操作能力。

简单总结,进程=PCB+代码和数据,操作系统对于系统的管理,本质是对PCB的管理
task_struct
在Linux操作系统中,task_struct 是一种实现进程控制块(PCB)的数据结构,它详细记录了进程的所有信息。作为 Linux 内核中最关键的结构之一,task_struct 用于进程管理和调度,它存储了与进程状态、数据、调度、地址空间、打开的文件等相关的所有信息。
task_struct 的主要组成部分
-
进程状态:
state:表示进程的状态,如可运行、不可运行(阻塞)或停止。
-
调度信息:
priority和static_prio:动态优先级和静态优先级,用于调度决策。sched_entity:包含用于 CFS 调度器(完全公平调度器)的运行时统计信息。
-
内存管理:
mm:指向mm_struct的指针,该结构包含虚拟内存区域和页表等信息。
-
进程标识符:
pid:进程的唯一标识符。tgid:线程组ID,用于标识线程组(即与主进程共享同一地址空间的所有线程)中的所有线程。
-
进程关系:
parent、children、sibling:指向父进程、子进程列表和兄弟进程的指针。
-
进程执行上下文:
thread:包含执行时所需的寄存器、栈指针、程序计数器等信息。
-
文件系统:
files:指向打开的文件描述符数组的指针。fs:指向文件系统特定信息的指针。
-
信号处理:
signal:管理信号状态,如挂起的信号、信号处理函数等。blocked、real_blocked、saved_sigmask:与信号屏蔽相关的字段。
-
时间信息:
start_time:进程开始的时间。utime和stime:用户态和核心态消耗的 CPU 时间。
-
链接列表:
tasks:使用 Linux 的双向链表机制,将所有task_struct连接在一起。
task_struct 的重要性
- 进程管理和调度:Linux 使用
task_struct管理所有与进程相关的数据。调度器使用这些数据来做出调度决策,实现有效的进程调度和管理。 - 系统资源管理:
task_struct记录了进程使用的所有系统资源,包括文件、内存和信号。这有助于操作系统有效地管理资源和实施安全策略。 - 多任务处理:
task_struct允许 Linux 操作系统实现真正的多任务处理能力,通过时间共享机制允许多个进程并发执行。
在 Linux 内核中,task_struct 结构由于其包含了操作系统管理进程所需的几乎所有信息而成为非常重要的核心部分。内核开发者和系统程序员经常需要直接或间接地与 task_struct 交互,以实现高级功能或调试。

03.进程属性
- 启动
- ./XXX,本质就是让系统创建进程并运行—我们自己写的代码形成的可执行=系统命令=可执行文件。在linux中运行的大部分执行操作,本质都是运行进程!!!
- 每—个进程都要有自己的唯—标识符,叫做进程pid
- 一个进程,想知道自己的pid:

构建一个无限循环的文件,让其进程一直运行


ps ajx | head -1 && ps ajx | grep mytest
首先打印出进程列表的列标题。然后搜索和显示所有包含mytest的进程条目

查看进程

通过系统调用获取进程标示符(操作系统提供,自己不能直接调用pid)
- 进程id(PID)
- 父进程id(PPID)
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{printf("pid: %d\n", getpid());printf("ppid: %d\n", getppid());return 0;
}


验证:


ctrl +C.就是在用户层面终止进程,kill -9 pid可以用来直接杀掉进程



进程每次启动的pid不一样,但是父进程是不变的

这里的 -bash 表示的是一个 Bash shell 的实例,是一个命令行界面,用户可以在其中输入和执行命令。
04.通过系统调用创建进程-fork初识

在 Unix 和类 Unix 系统(如 Linux)中,fork() 是一种系统调用,用于创建一个新的进程,这个新的进程被称为子进程。这个子进程是调用它的父进程的一个副本。fork() 是进程复制和进程创建最基本的方式,它在很多类型的软件应用中都非常重要,尤其是在操作系统和并发计算领域。
工作原理
当程序调用 fork() 时,操作系统会创建一个与调用它的进程(称为父进程)几乎完全相同的新进程。这个新创建的子进程将会:
- 复制父进程的地址空间,包括代码段、数据段、堆和栈。这意味着父进程和子进程的变量和程序的运行环境在物理内存中是分开的,但初始值相同。
- 继承父进程的文件描述符。如果父进程打开了文件,则子进程也将拥有这些文件的打开副本,共享同样的文件位置指针。
- 继承父进程的环境设置和任何其它相关的上下文信息。
返回值
fork() 函数调用后会有两次返回:
- 在父进程中,
fork()返回新创建的子进程的进程 ID。 - 在子进程中,
fork()返回 0。
如果出现错误,如内存不足,fork() 只会在父进程中返回一个负值,并且不会创建子进程。
使用示例
#include <unistd.h>
#include <stdio.h>int main() {int pid = fork();if (pid == 0) {// 这是子进程printf("This is the child process. PID = %d\n", getpid());} else if (pid > 0) {// 这是父进程printf("This is the parent process. PID = %d, Child PID = %d\n", getpid(), pid);} else {// fork失败perror("fork failed");}return 0;
}
用途和重要性
- 并发:
fork()允许程序并发运行多个进程。这是创建多进程应用程序的基础,如 Web 服务器和网络服务。 - 资源共享:通过
fork()创建的进程可以共享某些资源,如文件描述符,这可以用于进程间通信。 - 程序复杂性管理:通过将任务分配给子进程,可以简化复杂应用程序的设计,使得代码更容易理解和维护。
- 安全性和隔离:在某些应用中,
fork()可以用来隔离不同的任务,例如在安全关键的应用中隔离不信任的代码。
下面我们来看:

while :; do ps ajx |head -1 && ps axj |grep mytest |grep -v grep ; sleep 1; done
每隔一秒打印一次进程

刚开始只有一个进程在跑,后面两个进程跑最后退出
- fork之后,父子代码共享
- 创建一个进程,本质是系统中多了一个进程,多了1.内核task_struct 2.有自己的代码和数据
- 父进程的代码和数据是从磁盘加载来的,子进程的代码和数据默认情况继承父进程的代码和数据


执行的两个打印流,一个是父进程,一个是子进程
我们创建子进程的目的,是为了让子进程和父进程执行不一样的代码,上面的代码执行相同,没有太大意义
fork返回值
上面提到fork() 函数调用后会有两次返回:
- 在父进程中,
fork()返回新创建的子进程的进程 ID。 - 在子进程中,
fork()返回 0。
如果出现错误,如内存不足,fork() 只会在父进程中返回一个负值,并且不会创建子进程。

使用 fork() 系统调用来创建子进程,并分别在父子进程中实现了无限循环,打印各自的状态信息。父子进程的行为及如何使用 fork()。下面是该程序的逐行解析及行为说明:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main() {// 输出当前进程的状态,表明只有这一个进程在运行printf("process is running, only me! pid:%d\n", getpid());sleep(3); // 让进程暂停3秒pid_t id = fork(); // 创建子进程if (id == -1)return 1; // 如果fork失败,程序返回1并退出else if (id == 0) {// 子进程执行的代码块while (1) {// 持续打印子进程的信息:子进程中fork()返回0printf("id:%d, I am child process, pid: %d, ppid: %d\n", id, getpid(), getppid());sleep(1); // 每隔1秒重复打印}}else {// 父进程执行的代码块while (1) {// 持续打印父进程的信息:在父进程中fork()返回子进程的PIDprintf("id:%d, I am parent process, pid: %d, ppid: %d\n", id, getpid(), getppid());sleep(2); // 每隔2秒重复打印}}return 0;
}
-
程序开始:
- 打印初始进程信息,只有主进程在运行。
getpid()返回当前进程的PID。sleep(3)暂停3秒以便观察初始状态。
-
进程分叉(fork):
- 调用
fork()创建一个新的子进程。 - 在父进程中,
fork()返回子进程的PID。 - 在子进程中,
fork()返回0。

- 调用
-
错误处理:
- 如果
fork()返回-1,表示创建子进程失败,程序返回1并终止。
- 如果
-
子进程行为:
- 子进程进入无限循环,每秒打印一次自己的状态信息(ID为0,当前PID,以及父进程的PID)。
-
父进程行为:
- 父进程也进入无限循环,每2秒打印一次自己的状态信息(包括子进程的PID,当前PID,以及父进程的PID)。

我们以前写过的代码,全都是单进程
这里会有疑问:
- 同一个id,怎么可能,即是=0,又是>0?这里和后面要学的虚拟地址空间和父子写实拷贝有关系
- fork函数为什么会返回两次?
fork() 函数之所以会返回两次,是因为它在被调用时负责创建一个新的进程(子进程)。在调用 fork() 时,操作系统会通过复制发出 fork() 调用的进程(父进程)来创建子进程。这一过程生成了两个几乎完全相同的进程:原有的父进程和新创建的子进程,从而使得 fork() 看似返回了两次,但实际上是在两个不同的进程中返回:
-
在父进程中返回:对于父进程,
fork()返回新创建的子进程的进程ID(PID)。这使得父进程能够识别和管理其子进程。例如,如果所返回的PID是正数n,则表明创建成功,n即为子进程的PID。 -
在子进程中返回:对于子进程,
fork()返回0。这一返回值通常用于让子进程执行不同于父进程的代码。子进程通过区分fork()的返回值来决定其工作逻辑。 -
错误返回:如果
fork()调用失败(例如,由于系统资源不足或超过了系统允许的进程数),则它只会在父进程中返回-1,并且不会创建子进程。在此情况下,通常使用errno获取错误的具体信息。
进程具有独立性,我们杀掉其中一个不影响另一个,父子进程有独立的PCB
一次创建多个进程

代码解析
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>void RunChild()
{// 子进程的无限循环输出while(1){printf("I am child, pid:%d, ppid:%d\n", getpid(), getppid());sleep(1); // 每隔一秒打印一次}
}int main()
{const int sum = 5; // 要创建的子进程数量// 在父进程中进行循环创建子进程for(int i = 0; i < sum; i++){pid_t id = fork(); // 创建新的子进程if (id == 0){RunChild(); // 如果是子进程,调用 RunChild 函数}// 父进程会继续循环,不会被 RunChild 调用所阻塞}// 父进程的无限循环输出while(1){printf("I am parent, pid:%d, ppid:%d\n", getpid(), getppid());sleep(1); // 每隔一秒打印一次}return 0; // 虽然永远不会到达这里,因为有无限循环
}
-
进程创建:
- 主进程通过
for循环调用fork()五次,这将原始父进程派生出五个子进程。 - 在每次调用
fork()后,系统生成两条执行路径:父进程继续循环,子进程跳转到RunChild()。
- 主进程通过
-
子进程行为:
- 一旦
fork()返回 0,这个进程即为子进程,它会调用RunChild()函数。 - 在
RunChild()中,子进程进入无限循环,持续输出其 PID 和其父进程的 PID,暂停 1 秒,确保不会占用太多 CPU 时间。
- 一旦
-
父进程行为:
- 原始父进程(从不进入
RunChild()的分支)继续for循环执行五次fork(),然后进入自己的无限循环。 - 在这个无限循环中,父进程以 1 秒的间隔输出其 PID 和父进程 PID。
- 原始父进程(从不进入

进程的信息可以通过 /proc 系统文件夹查看


进程中的PCB会记录自己对应的可执行程序的路径
相关文章:
【linux】进程理解
🔥个人主页:Quitecoder 🔥专栏:linux笔记仓 目录 01.进程的基本概念进程的组成部分进程的特性进程的状态 02.PCBPCB的组成部分task_structtask_struct 的主要组成部分 03.进程属性查看进程 04.通过系统调用创建进程-fork初识工作…...
文件IO练习1
题目一: 1、使用fread和fwrite完成两个文件的拷贝,要求源文件和目标文件由外界输入 实现代码: #define LEN_BUF 256int main(int argc, const char *argv[]) {if(argc ! 3){fprintf(stderr,"程序入参输入有误\n");return -1;}FILE…...
c++ std::future 和 std::promise 的实现工作原理简介
为了便于理解 std::future 和 std::promise 的实现工作原理,我们可以创建一个简化的版本。这包括共享状态、Promise 设置值、Future 获取值的核心机制。我们的示例代码将实现 SimplePromise 和 SimpleFuture 两个类,二者通过一个共享状态实现线程间的通信…...
MATLAB(Octave)混电动力能耗评估
🎯要点 处理电动和混动汽车能耗的后向和前向算法模型(simulink),以及图形函数、后处理函数等实现。构建储能元数据信息:电池标称特性、电池标识符等以及静止、恒定电流和恒定电压等特征阶段。使用电流脉冲或要识别的等效电路模型类型配置阻抗…...
opencv学习:人脸识别器特征提取BPHFaceRecognizer_create算法的使用
BPHFaceRecognizer_create算法 在OpenCV中,cv2.face.LBPHFaceRecognizer_create()函数用于创建一个局部二值模式直方图(Local Binary Patterns Histograms,简称LBPH)人脸识别器。LBPH是一种用于人脸识别的特征提取方法࿰…...
HTML+CSS总结【量大管饱】
文章目录 前言HTML总结语义化标签常用标签H5新的语义元素H5的媒体标签\<embed> 元素(少用)\<object>元素(少用)\<audio>\<video> 元素包含关系iframe元素嵌入flash内容常用表单inputselect CSS总结权重样…...
Android开发之Broadcast Receive(广播机制)其实开发如此简单
什么是BroadcastReceiver BroadcastReceiver(广播接收器)用于响应来自其他应用程序或者系统的广播消息。这些消息有时被称为事件或者意图。本质上来讲BroadcastReceiver是一个全局的监听器,隶属于Android四大组件之一。 使用场景 1、 不同…...
Chromium 中chrome.cookies扩展接口c++实现分析
chrome.cookies 使用 chrome.cookies API 查询和修改 Cookie,并在 Cookie 发生更改时收到通知。 更多参考官网定义:chrome.cookies | API | Chrome for Developers (google.cn) 本文以加载一个清理cookies功能扩展为例 https://github.com/Google…...
excel筛选多个单元格内容
通常情况下,excel单元格筛选时,只筛选一个条件,如果要筛选多个条件,可以如下操作: 字符串中间用空格分隔就行。...
Instant 和 Duration 类(进行时间处理)
Instant Instant 类是 Java 8 中引入的,用于表示一个具体的时间点,它基于 UTC(协调世界时)时区。以下是 Instant 类的一些常用方法及其简要说明: now():获取当前的 Instant 对象,表示当前时间…...
Java每日面试题(Spring)(day19)
目录 Spring的优点什么是Spring AOP?AOP有哪些实现方式?JDK动态代理和CGLIB动态代理的区别?Spring AOP相关术语Spring通知有哪些类型?什么是Spring IOC?Spring中Bean的作用域有哪些?Spring中的Bean什么时候…...
【多线程】线程池(上)
文章目录 线程池基本概念线程池的优点线程池的特点 创建线程池自定义线程池线程池的工作原理线程池源码分析内置线程池newFixedThreadPoolSingleThreadExecutornewCachedThreadPoolScheduledThreadPool 线程池的核心线程是否会被回收?拒绝策略ThreadPoolExecutor.AbortPolicyT…...
ansible 语句+jinjia2+roles
文章目录 1、when语句1、判断表达式1、比较运算符2、逻辑运算符3、根据rc的返回值判断task任务是否执行成功5、通过条件判断路径是否存在6、in 2、when和其他关键字1、block关键字2、rescue关键字3、always关键字 3、ansible循环语句1、基于列表循环(whith_items)2、基于字典循…...
【Docker项目实战】使用Docker部署HumHub社交网络平台
【Docker项目实战】使用Docker部署HumHub社交网络平台 一、HumHub介绍1.1 HumHub简介1.2 HumHub特点1.3 主要使用场景二、本次实践规划2.1 本地环境规划2.2 本次实践介绍三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本四、下载HumHub镜…...
“医者仁术”再进化,AI让乳腺癌筛查迎难而上
世卫组织最新数据显示,我国肿瘤疾病仍然呈上升趋势,肿瘤防控形势依然比较严峻。尤其是像乳腺癌等发病率较高的疾病,早诊断和早治疗意义重大,能够有效降低病死率。 另一方面,中国地域广阔且发展不平衡,各地…...
安卓流式布局实现记录
效果图: 1、导入第三方控件 implementation com.google.android:flexbox:1.1.0 2、布局中使用 <com.google.android.flexbox.FlexboxLayoutandroid:id"id/baggageFl"android:layout_width"match_parent"android:layout_height"wrap_co…...
-bash gcc command not found解决方案(CentOS操作系统)
以 CentOS7 为例,执行以下语句 : yum install gcc如果下载不成功,并且网络没有问题。 执行以下语句 : cp -r /etc/yum.repos.d /etc/yum.repos.d.bakrm -f /etc/yum.repos.d/*.repocurl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.…...
(二)Python输入输出函数
一、输入函数 input函数:用户输入的数据,以字符串形式返回;若需数值类型,则进行类型转换。 xinput("请入你喜欢的蔬菜:") print(x) 二、输出函数 print函数 输出单一数值 x666 print(x) 输出混合类型…...
从调用NCCL到深入NCCL源码
本小白目前研究GPU多卡互连的方案,主要参考NCCL和RCCL进行学习,如有错误,请及时指正! 内容还在整理中,近期不断更新!! 背景介绍 在大模型高性能计算时会需要用到多卡(GPU…...
深入理解Transformer的笔记记录(精简版本)NNLM → Word2Vec
文章的整体介绍顺序为: NNLM → Word2Vec → Seq2Seq → Seq2Seq with Attention → Transformer → Elmo → GPT → BERT 自然语言处理相关任务中要将自然语言交给机器学习中的算法来处理,通常需要将语言数学化,因为计算机机器只认数学符号…...
铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
