【Linux】进程的概念 + 查看进程

前言:
在前面我们学习了Liunx的基本指令和权限相关知识,还有基本工具的使用,有了以上的基础知识我们本章将正式接触Linux操作系统。

目录

    • 1.冯诺依曼体系结构
      • 1.1 内存存在的意义
      • 1.2 程序加载到内存的含义
      • 1.3 程序的预加载:
    • 2 .认识进程
      • 2 .1 如何理解管理
      • 2 .2 什么叫是进程:(初步理解)
        • 2 .2.1 PCB
      • 2.3 简单认识操作系统
        • 2.3 .1 操作系统如何提供服务
      • 2.4 查看进程
        • 2. 4 .1 第一种查看进程的方式:
        • 2. 4 .2 第二种查看进程的方式:
      • 2.5 对进程的当前工作路径的理解
    • 3 .进程的系统调用
      • 3 .1 父进程与子进程
      • 3 .2 fork函数创建子进程
      • 3 .2 .1 **fork函数的返回值:**
      • 3 .2 .2 fork函数两个返回值的原因:
    • 4 .进程的状态
      • 4 .1 运行状态(R)
      • 4 .2 死亡状态(X dead)
      • 4 .3 阻塞状态(s)
      • 4 .4 深度睡眠状态(D)
      • 4 .5 僵尸状态(Z)
      • 4 .5.1 模拟僵尸进程
      • 4 .5.2 长时间僵尸的危害
      • 4 .6 暂停状态(T/t)
    • 5 .进程状态的整体总结

1.冯诺依曼体系结构

我们常见的计算机,如笔记本。我们不常见的计算机,如服务器,大部分都遵守冯诺依曼体系。
在这里插入图片描述

  • 这里的存储器: 就是内存,不是磁盘!

  • CPU(运算器+控制器)

  • 运算器:算术运算,逻辑运算

  • 控制器:CPU是可以响应外部事件。比如:拷贝数据到内存

  • 输入设备: 键盘,话筒,摄像头,磁盘,网卡……

  • 输出设备: 显示器,音响,磁盘,网卡,显卡……

补充内容:

  1. CPU读取数据(数据+代码),都是要从内存中读取,站在数据的角度,我们认为CPU不和外设直接交互。
  2. CPU要处理数据,需要先将外设中的数据,加载到内存,站在数据的角度,外设直接只和内存打交道。

程序要运行,必须先被加载到内存中

1.1 内存存在的意义

为什么要有内存?
a. 技术角度
存储速度的差别: 寄存器的存取速度 > cpu的运算速度 > L1 ~ L3Cache(各种缓存Cache) > 内存 >> 外设(磁盘) >> 光盘磁带
b. 数据角度
外设不和CPU直接交互,而是和内存交互,CPU也是如此
c. 成本角度
造价: 寄存器 >> 内存 >> 磁盘(外设)

如果冯诺依曼体系结构中没有内存的话:

  • 那么整个体系的效率是很低下,因为是由最慢的设备决定的。

  • 计算CPU速度够快,但是还是要等外设,这既是著名的木桶原理。

  • 内存的意义:

有存储器的存在,让软件的存在具有了更大的意义,开机的时候,就是将操作系统加载到存储器当中
内存对应的最大意义:使用较低的钱的成本,能够获得较高的性能

  • 补充:
  • 中央处理器CPU也会和外设有交互,协调数据流向。
  • 中央处理器CPU只是个具有运算和控制能力的体现木偶,真正让中央处理器去完成计算和某些控制的是整个计算机的大脑,叫做软件,最具有代表性的就是操作系统,是操作系统来控制CPU的。

1.2 程序加载到内存的含义

  • 在我们之前学习编程语言例如:C/C++时,我们都听过这样一句话:编译好之后的软件/程序,要运行,必须先加载到内存
  • 为什么呢?
    答案就是由体系结构(冯·诺依曼体系结构)决定的
    具体解释:

C/C+编译好的程序就必须从磁盘加载到内存要让CPU能够读取。
我们编译好的程序是个文件是在磁盘上(外设),CPU读取数据(数据+代码),都是要从内存中读取,所以也就要求要运行程序,就必须将程序先加载到内存,因为CPU只会从内存当中读取指令代码和数据。

1.3 程序的预加载:

  • 几乎所有的硬件,只能被动的完成某种功能,不能主动的完成某种功能,一般都是要配合软件完成的。
  • 开机等待的本质,就是将操作系统加载到内存当中,因为体系结构规定,CPU要执行代码,执行的可不仅仅是我们写的代码,还有操作系统的代码,所以必须先把操作系统加载到内存,这就是预加载。
  • 操作系统一旦被加载之后,在软件层面上,就可以预先把将来要访问的数据或文件,可以提前加载到内存中。

数据在流动的时候------》输入到内存---------》从内存到CPU--------》CPU计算处理完---------------》将结果写回内存,然后定期再刷新到外设。

补充:

内存的存在可以去适配外设和CPU之间速度不匹配的问题,因为内存的存在可以去预先装载一些常见的内存管理软件,数据管理软件。

2 .认识进程

2 .1 如何理解管理

  • 管理的本质是:对数据的管理
    管理的本质:不是对被管理对象进行直接管理,而是只要拿到被管理对象的所有的相关数据,我们对数据的管理,就可以体现对对象的管理。
  • 管理的核心理念:先描述,再组织
    用C语言或C++描述,用数组结构组织数据。管理的本质是对数据做管理—对某种数据结构的管理--------》对数据结构的各种操作,增删查改。

重点:操作系统是一款软件,是一款专门搞管理的软件,软件可以管理软件,就像人可以管理人一样

2 .2 什么叫是进程:(初步理解)

  • 进程是一个运行起来的程序。
  • 程序是个文件,是存在磁盘上的,不能简单的认为,将程序从磁盘加载到内存,这个程序就是进程。
  • 操作系统里面,可能同时存在大量的进程
  • 对进程的管理,是先描述,再组织

进程=对应的代码和数据 +进程对应的PCB结构体。

2 .2.1 PCB
  • 描述起来,用struct结构体
  • 组织起来,用链表或其他高效的数据结构
  • 而Linux中的task_struct是一款具体的PCB
    在这里插入图片描述

有大量的进程就必须把进程先描述再组织起来,把进程组织起来实际上是把描述进程的进程控制块组织起来。

task_ struct内容分类

  • 标示符: 描述本进程的唯一标示符,用来区别其他进程。

  • 状态: 任务状态,退出代码,退出信号等。

  • 优先级: 相对于其他进程的优先级。

  • 程序计数器: 程序中即将被执行的下一条指令的地址。

  • 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。(mm_struct–> 虚拟地址空间

  • 上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]。

  • I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。(文件信息

  • 记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。

  • 其他信息

那我们学习进程到底学的是什么呢?

  • 我们学习的是进程控制块里面有什么属性!

第一阶段对进程的理解总结:

  • 当一个程序从磁盘加载到内存,将代码和数据加载到内存只是第一步,第二步,操作系统为了管理这个进程,需要为该进程创建对应的描述该进程的进程控制块PCB,Liunx下叫task struct。
  • 只要在内存当中被操作系统管理,操作系统实际管的根本不是代码和数据,而是管的则是进程的PCB结构体。
  • 第一阶段进程的理解:程序加载到内存之后的代码和数据,以及操作系统为了管理进程,所生成的描述进程的进程控制块PCB结构体(内核数据结构 +代码和数据,这二者合起来,叫做进程)。
  • 一个进程有一个PCB描述起来了,系统中有大量的PCB,只需要将系统中的PCB用数据结构组织起来,对应的对进程的管理就变成了对数据结构的增删查改。

2.3 简单认识操作系统

在这里插入图片描述

2.3 .1 操作系统如何提供服务

计算机和OS设计出来就是为了给人们服务的,那么是如何给我们提供服务的呢?

  • 所有的应用程序都没有资格直接访问硬件,因为硬件的管理者是操作系统
  • 操作系统是不相信任何人的!不会直接暴露自己的任何数据结构,代码逻辑,其他数据相关的细节!
  • 操作系统是通过给用户提供接口的方式为用户提供服务的~
  • Linux操作系统是用C语言写的,这里所谓的“接口”,本质就是C函数
  • 学习系统编程本质就是在学习这里的系统接口。

补充:
一门语言跨平台可移植,在Windows和Linux下都能选择其对应的接口,上层提供的都是printf(),原因标准库中用了多态,同个接口在不同的平台下实现同一个或者不同的功能

2.4 查看进程

  • 我们自己写的代码,编译成为可执行程序,启动之后就是一个进程。
  • 别人写的程序,启动之后也是进程。
2. 4 .1 第一种查看进程的方式:

在这里插入图片描述
a:all
j:jobs
x:以特定格式显示

显示出前五行:
在这里插入图片描述
Windows下是通过双击打开一个进程, 而Linux则是通过./启动,在系统中找到可执行程序启动。

2. 4 .2 第二种查看进程的方式:

Linux的根目录下有个 proc目录里面放的就是实时的进程:
在这里插入图片描述
proc:内存文件系统,里面放的是当前系统实时的进程信息。

  • 要想获得PID为26746的进程信息,你需要查看 /proc/26746这个文件夹。
  • 在proc中打开这个进程,可以查看它的详细属性
    在这里插入图片描述

2.5 对进程的当前工作路径的理解

我们之前学习C / C++语言的时候,我们就只是肤浅的理解,当前工作路径就是源文件或程序所在的路径。

事实上,并不是。

  • 我们使用ls -al选项来在 proc目录中对应的进程中看一下它的更详细的属性:

在这里插入图片描述

  • 当前路径并不是源文件所在的路径,而是运行进程时所处的路径。
  • 换句话说,就是Bin运行时所处的路径。

3 .进程的系统调用

3 .1 父进程与子进程

  • 父进程:指已创建一个或多个子进程的进程。常使用**Fork()**来创建多个子进程。
  • 通过getpid函数来获取当前进程的ID,也可以通过getppid来获取父进程的ID
    在这里插入图片描述
    代码演示:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main()
{
    while(1)
    {
        printf("I am a process! pid: %d ppid: %d\n",getpid(), getppid());
        sleep(1);
    }

    return 0;
}
  • 每次执行一个可执行程序之后,进程的ID都会改变,上图也验证了这一点,但是我们惊奇的发现,为啥父进程的ID始终都是一个值,一直都是不变的呢?
    在这里插入图片描述
    几乎我们在命令行上所执行的所有的指令(你的cmd),都是bash进程的子进程

衍生问题:

  • bash怎么创建的子进程
  • bash怎么让子进程执行我的程序
  • bash的父进程又是谁

3 .2 fork函数创建子进程

  • fork函数是用来创建子进程的,它有两个返回值。
  • 子进程代码共享,数据各自开辟空间,私有一份
    在这里插入图片描述

3 .2 .1 fork函数的返回值:

在这里插入图片描述

  • 成功的话:将子进程的pid返回给父进程,0被返回给子进程。
  • 失败的话:-1直接返回给父进程,没有子进程没创建。

代码演示:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
    pid_t id  = fork();

    printf("Hello World!  id = %d\n", id);

    return 0;
}
  • 一条打印语句竟然有两个打印结果,因为Fork之后产生新的进程。
    fork 之后通常要用 if 进行分流
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
    pid_t id = fork();
    //id == 0 : 子进程 , id > 0 : 父进程
    
    if(id == 0)
    {
        while(1)
        {
            printf("我是子进程,我的pid:%d,我的父进程是:%d\n", getpid(), getppid());
            sleep(1);
        }
    }
    else  
    {
        while(1)
        {
            printf("我是父进程,我的pid:%d,我的父进程是:%d\n", getpid(), getppid());
            sleep(1);
        }
    }

    return 0;
}

3 .2 .2 fork函数两个返回值的原因:

如何解释呢?fork如何做到会有不同的返回值?

答:fork之后,OS做了什么?是不是系统多了一个进程
父进程是:task_struct + 数据和代码
子进程也是:task_struct + 子进程的数据和代码

  • 子进程的task_ stuct对象内部的数据基本是从父进程继承下来的。
  • 子进程和父进程共享代码,fork之后,父子进程执行同样的代码。
  • 父进程return一次,子进程return一次,不就是两次返回吗
  • Fork之后,父进程和子进程返回值不同,可以通过不同的返回值,判断让父子执行不同的代码块

补充:

  • 进程是由task_struct 和 对应的数据和代码组成。
  • 那么我们平时用的指令的执行后,它的进程对应的代码在哪呢?

以ls为例: ls变成进程之后,该进程的代码就是从磁盘/usr/bin/ls路径下读取数据代码。

  • 父子进程被创建出来,哪一个进程先运行呢??

不一定!! 谁先运行,不一定,这个是由操作系统的调度器决定的!!
操作系统和CPU运行某一个进程,本质从task_struct 形成的队列中挑选一个task_struct,来执行它的代码。

4 .进程的状态

操作系统就像是计算机里的哲学一样,因为操作系统这门学科讲的范围很宽泛,它的理论内容适用于各个操作系统,而我们要具体的学习某一款操作系统,那就是Linux

凡是说进程,就必须先想到进程的task_ struct。

  • 进程状态本质上是个uint8 整数,整数在进程的task struct中
  • task_ struct中会包含进程的相关的信息。
    在这里插入图片描述
    在这里插入图片描述

4 .1 运行状态(R)

  • 运行状态 是进程在CPU上运行,就叫运行态吗?

答:不是的,操作系统当中每个CPU,都会创建一个runqueue,所以一个进程想被调动,说白了就是将自己的进程放到运行队列当中。

进程只要在运行队列中叫做运行态,不代表正在运行,代表我已经准备好了,随时可以调度!
在这里插入图片描述

4 .2 死亡状态(X dead)

死亡状态又叫做终止状态:这个状态只是一个返回状态,你不会在任务列表里看到这个状态。

  • 进程终止状态:进程已完成执行,
  • 终止就是最终资源释放,但是PCB控制块至少还在,要让操作系统来释放
  • X状态,瞬时性非常强。

4 .3 阻塞状态(s)

  • 进程运行可能需要申请更多的资源:磁盘,网卡,显示器资源,声卡/音响等
    -我们申请资源时,如果该资源暂时没有准备好,当前进程要从runqueue中移除。
    重点:
  • 当我们的进程此时在等待外部资源的时候,该进程的代码,不会被执!!
  • 我的进程卡住了 — 进程阻塞!上层看来就是某些任务卡住了。

补充知识点

  • CPU运行的速度非常快,但是运行队列的周转周期非常短,看起来所有进程都在运行。
  • 单核CPU在任意时间点都只能运行一个进程。

在这里插入图片描述
疑问:为什么我们一直向显示器打印,但却是S状态?

  • 因为CPU足够快,外设又很慢,CPU速度的速度是远大于外设的
  • 所以大部分时间都是S状态,都是睡眠阻塞状态

虽然一直在刷屏,但是还是S状态,原因也是在printf上,不断地往显示器上打印,但是显示器是个外设速度非常慢,即便是闲着准备好被刷新也需要花费时间。这个进程90%的情况都是在等,在等显示器就绪。
只有光是一个死循环,不调用外设的时候才是一直处于R状态。

4 .4 深度睡眠状态(D)

  • D状态,可以理解为磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状
  • 在这个状态的进程通常会等待IO的结束
  • 是Linux中特有的状态。

假设场景:

当一个进程向磁盘写文件的时候,由于要写的文件很大,所以进程要在那里等,如果等的时间太长了的话,操作系统见到一个进程在那里很悠闲直接把它干掉了,那等磁盘将文件写完之后,回头一看,傻眼了,进程不见了,那写入的文件怎么处理呢??如果该文件写入失败了,结果返回的时候发现进程不见了,那么数据就丢了,后果很严重。
尽然进程要等,就是要等一个返回值,就是为了判断文件写成功了没!!

所以这个进程不能随便杀掉,所以操作系统就将该进程设置成了D状态

  • 凡是D状态的进程,操作系统无权杀掉该进程,只能等该进程自己醒来。
  • D状态的进程操作系统没权利将其杀掉,只能通过关机重启 or 拔掉电源的方式来强制杀掉该进程。
  • 如果一个系统当中存在大量的D状态进程,关机都关不掉
  • 一般而言,linux中,如果我们等待的是磁盘资源,我们进程阻塞所处的状态就是D
    不过这种情况不多见,很难能见到~

补充:

有时候闪退的问题,是服务器压力过大,OS是会终止用户进程的!

4 .5 僵尸状态(Z)

  • 一个进程已经退出,但是还不允许被OS释放处于一个被检测的状态----僵尸状态。
  • 维持僵尸状态,是为了让该进程被操作系统或父进程回收。
  • 当一个linux中的进程退出的时候,一般不会直接进入X(终止)状态,而是进入Z状态。

我们不禁发出疑问,为什么?

  • 首先我们知道,子进程被创建出来,一定是要执行任务的
  • 当子进程退出的时候,一般需要将进程的执行结果,告知到父进程os.

进程Z,就是为了维护退出信息,可以让父进程或者os读取的。
僵尸进程存在的意义,就是说明这个进程退出的时候,是因为什么原因退出的。

4 .5.1 模拟僵尸进程

如果创建子进程,子进程退出了,父进程不退出,也不等待子进程,子进程退出之后所处的状态就是Z状态。(ps:所谓等待子进程就是回收)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> 

int main()
{
    pid_t id = fork();
    
    if(id == 0)
    {
        //child
        int cnt = 5;
        while(cnt)
        {
            printf("我是子进程,我剩下 %d S\n", cnt);
            cnt--;
            sleep(1);
        }
        printf("我是子进程,我已经僵尸了,等待被检测\n");
        exit(0);
    }
    else 
    {
        while(1)
        {
            sleep(1);
        }
    }

    return 0;
}

子进程5秒后退出,父进程一直在跑,也不回收子进程,我们代码没有写回收,所以子进程就是没有回收

4 .5.2 长时间僵尸的危害

  • 如果没有人回收子进程的僵尸,该状态会一直维护!该进程的相关资源(task_struct) 不会被释放!一个很严重的问题那就是 — 内存泄漏
  • 什么情况会一直僵尸?

父进程不回收它,会一直僵尸状态。

  • 一个进程僵尸了,是不可被杀死的。都已经成僵尸了还怎么杀死

1.使用wait()或waitpid():父进程可以调用wait()或waitpid()函数来等待子进程终止,并获取它的终止状态
此方法父进程会被挂起

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
 
int main() {
    pid_t pid = fork();
    if (pid == 0) {
        // 子进程代码
        _exit(0);
    } else if (pid > 0) {
        // 父进程代码
        wait(NULL); // 等待子进程终止
    } else {
        // fork失败
        perror("fork");
    }
    return 0;
}

2.父进程忽略SIGCHLD信号:如果不想让子进程编程僵尸进程,可在父进程中加入:signal(SIGCHLD,SIG_IGN);
如果将此信号的处理方式设为忽略,可让内核把僵尸子进程转交给init进程去处理

signal(SIGCHLD,SIG_IGN);

3.注册SIGCHLD信号处理函数: 父进程可以通过捕获SIGCHLD信号来处理子进程终止事件,并调用waitpid()来避免僵尸进程的产生

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
 
void sigchld_handler(int signum) {
    // 使用非阻塞方式调用waitpid(),防止阻塞父进程
    while (waitpid(-1, NULL, WNOHANG) > 0);
}
 
int main() {
    struct sigaction sa;
    sa.sa_handler = sigchld_handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART;
    sigaction(SIGCHLD, &sa, NULL);
 
    pid_t pid = fork();
    if (pid == 0) {
        // 子进程代码
        _exit(0);
    } else if (pid > 0) {
        // 父进程代码
        sleep(10); // 模拟父进程的工作
    } else {
        // fork失败
        perror("fork");
    }
    return 0;
}

4.daemon进程: 将父进程设计成守护(后台)进程(daemon),这样孤儿进程会被init进程(PID 1)领养,而init进程会自动回收孤儿进程,避免僵尸进程的产生。

状态后面有S+的,代表这个进程是个前台进程,能在键盘ctr/ + C的是前台进程; 后台进程ctr/ + C干不掉。

孤儿进程没有那个S+,它是个后台进程。

4 .6 暂停状态(T/t)

  • 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程 通过发送SIGCONT 信号让进程继续运行。

在这里插入图片描述

  • 暂停状态主要用于调试场景中。

5 .进程状态的整体总结

  • 系统中一定是存在各种资源的(不仅仅是CPU)网卡,磁盘,显卡都是资源;所以,系统中不只是只存在一种队列

在这里插入图片描述

  • 理解操作系统中的进程状态:
    a.新建
    b.运行:task_struct 结构体在运行,队列中排队,就叫做运行态
    c.阻塞:等待非CPU资源就绪,阻塞状态
    d.挂起:当内存不足的时候,Os通过适当的置换进程的代码和数据到磁盘,进程的状态就叫做挂起!
    在这里插入图片描述
    尾声
    看到这里,相信大家对这个C++有了解了。
    如果你感觉这篇博客对你有帮助,不要忘了一键三连哦

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

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

相关文章

python读取指定文件夹下的图片(glob获取)

python读取指定文件夹下的图片&#xff08;glob获取&#xff09; 定义traverse_images函数&#xff0c;仅需要改变下根路径即可 glob是python中用来查找符合特定规则的文件路径名的函数 import os from glob import globdef traverse_images (folder_path):image_formats …

Google账号输入用户名和密码后提醒要到手机通知点是,还要点击数字,但是我手机收不到

有一些朋友换了一个新的电脑后手机登录谷歌账号时&#xff0c;用户名和密码都正确输入以后&#xff0c;第三步弹出一个提示&#xff0c;要在手机上的通知栏点击是&#xff0c;并且点击手机上相应的数字才能继续登录。 但是自己的手机上下拉通知栏却没有来自谷歌的通知&#xf…

mkv怎么改成mp4格式?把mkv改成MP4的几种方法介绍

mkv怎么改成mp4格式&#xff1f;将mkv格式的视频文件转换为MP4格式是许多用户常常需要解决的问题&#xff0c;尤其是在不同设备之间传输和播放视频时。mkv是一种灵活且功能强大的多媒体容器格式&#xff0c;能够包含多种视频、音频和字幕轨道。然而&#xff0c;尽管其优势显著&…

前端web在线PPT编辑器-PPTLIST

哈喽&#xff0c;大家好&#xff0c;今天给大家介绍一款的在线的PPT编辑器开源框架-PPTLIST&#xff1b;他是一个基于 Vue3.x TypeScript 的在线演示文稿&#xff08;幻灯片&#xff09;应用&#xff0c;还原了大部分 Office PowerPoint 常用功能&#xff0c;支持 文字、图片、…

MSP学习

一、迁移资源调研 完成导入&#xff0c;类似完成选型分析 离线工具调研 账单 二、迁移计划 1、

【教程】新的Selenium!整合了隐藏浏览器指纹等功能

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 目录 前景提要 driver Driver() 常用driver 接口 最后的话 前景提要 新的selenium&#xff0c;整合了隐藏浏览器指纹&#xff0c;非常好用&#x…

Nginx七层(应用层)反向代理:HTTP反向代理proxy_pass篇

Nginx七层&#xff08;应用层&#xff09;反向代理 HTTP反向代理proxy_pass篇 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of thi…

极品AI大模型,抓紧收藏!整合包!

近期&#xff0c;科技巨头谷歌终于发布了1个月前在I/O开发者大会上预告过的Gemma 2大模型。据谷歌介绍&#xff0c;与第1代Gemma模型相比&#xff0c;新模型拥有更优的性能&#xff0c;推理效率也更高。我当然是&#xff0c;“无所谓&#xff0c;我会出手.jpg”&#xff0c;给大…

微深节能 料场堆取料机大机定位防碰撞系统 格雷母线

在现代工业领域&#xff0c;尤其是大型料场、港口、码头等复杂作业环境中&#xff0c;堆取料机的精准定位与防碰撞系统显得尤为重要。这些大型设备的高效、安全运行直接关系到生产效率和作业安全。武汉市微深节能科技有限公司推出的格雷母线高精度位移测量系统&#xff0c;为料…

AI中药处方模型构建与案例

在中医领域,人工智能(AI)可以生成各种指令来辅助诊断、治疗和研究。 1. 诊断辅助指令: 根据患者的症状和体征,自动分析并生成可能的中医证候诊断建议。利用中医望闻问切四诊信息,智能识别关键症状,提供对应的中医辨证思路。2. 治疗建议指令: 根据辨证结果,自动推荐相应…

什么牌子麦克风好,无线麦克风什么品牌好,领夹麦克风性价比推荐

在自媒体内容创作的繁荣时代&#xff0c;领夹麦克风作为提升音频质量的关键工具&#xff0c;其市场需求正以前所未有的速度扩张。面对市场上琳琅满目的品牌和型号&#xff0c;如何在众多选项中做出既贴合个人需求又具备专业水准的选择&#xff0c;成为创作者们共同面临的课题。…

TB作品】51单片机 Proteus仿真 51单片机SPI显示OLED字符驱动

// GND 电源地 // VCC 接5V或3.3v电源 // D0 P1^4&#xff08;SCL&#xff09; // D1 P1^3&#xff08;SDA&#xff09; // RES 接P12 // DC 接P11 // CS 接P10 OLED显示接口与控制实验报告 背景 OLED&#xff08;有机发光二极管&#xff09;显示器由于其高对比度、低功耗和…

【DFS(深度优先搜索)详解】看这一篇就够啦

【DFS详解】看这一篇就够啦 &#x1f343;1. 算法思想&#x1f343;2. 三种枚举方式&#x1f343;2.1 指数型枚举&#x1f343;2.2 排列型枚举&#x1f343;2.3 组合型枚举 &#x1f343;3. 剪枝优化&#x1f343;4. 图的搜索&#x1f343;5. 来几道题试试手&#x1f343;5.1 选…

通过端口转发实现docker容器运行时端口更改

通过端口转发实现docker容器运行时端口更改 前言启动容器查看容器ip地址端口转发 前言 关于修改docker正在运行中容器端口&#xff0c;网上大部分分为3类: 1. 删除原有容器重新创建;2. 改配置文件;3. 在现有容器上新提交镜像&#xff0c;用新镜像起新的容器。 1和3属于同一种流…

【Linux】进程补充知识

文章目录 前言磁盘与物理内存 数据交互局部性原理页表 前言 磁盘是计算机唯一的一个机械设备&#xff0c;在磁盘文件系统中&#xff0c;我们了解到&#xff0c;磁盘的数据读取写入相比物理内存&#xff0c;CPU等效率低了很多。但是其作为数据的载体&#xff0c;物理内存与其交…

CentOS7下安装Doris

Doris简介 Apache Doris 是一款基于 MPP 架构的高性能、实时的分析型数据库&#xff0c;以高效、简单、统一的特点被人们所熟知&#xff0c;仅需亚秒级响应时间即可返回海量数据下的查询结果&#xff0c;不仅可以支持高并发的点查询场景&#xff0c;也能支持高吞吐的复杂分析场…

新时代【机器学习】与【Pycharm】:【随机数据生成】与智能【股票市场分析】

目录 第一步&#xff1a;准备工作 1.1 安装必要的库 小李的理解&#xff1a; 1.2 导入库 小李的理解&#xff1a; 第二步&#xff1a;生成和准备数据 2.1 生成随机股票数据 小李的理解&#xff1a; 2.2 数据探索与可视化 小李的理解&#xff1a; 2.3 数据处理 小李…

谷粒商城学习笔记-18-快速开发-配置测试微服务基本CRUD功能

文章目录 一&#xff0c;product模块整合mybatis-plus1&#xff0c;引入依赖2&#xff0c;product启动类指定mapper所在包3&#xff0c;在配置文件配置数据库连接信息4&#xff0c;在配置文件中配置mapper.xml映射文件信息 二&#xff0c;单元测试1&#xff0c;编写测试代码&am…

MySQL学习记录 —— 십칠 CentOS7.9环境下的MySQL8.4 安装和配置

文章目录 1、安装和配置2、MySQL 包位置3、主要程序介绍 本篇开始在之前mysql博客的基础上继续延伸&#xff0c;适合有一定基础的mysql使用者阅读 环境 &#xff1a;CentOS 7.9 root 用户&#xff0c;MySQL 8.4 1、安装和配置 看一下当前系统版本 cat /etc/redhat-release应当…

项目收获总结--MyBatis的知识收获

一、概述 最近几天公司项目开发上线完成&#xff0c;做个收获总结吧~ 今天记录MyBatis的收获和提升。 二、获取自动生成的(主)键值 insert 方法总是返回一个 int 值 &#xff0c;这个值代表的是插入的行数。若表的主键id采用自增长策略&#xff0c;自动生成的键值在 insert…