Linux—进程学习-02

目录

  • Linux—进程学习—2
    • 1.通过系统调用创建进程—fork
      • 1.1fork创建子进程
      • 1.2fork函数的返回值
      • 1.3利用fork实现多进程
    • 2.有关cpu的常识了解
    • 3.进程状态
      • 3.1从操作系统层面了解进程状态
        • 3.1.1就绪和新建状态的理解
        • 3.1.2运行和阻塞状态的理解
        • 3.1.3挂起状态的理解
          • 挂起和阻塞的区别
        • 3.1.4总结
      • 3.2Linux中对进程状态的描述
      • 3.3查看进程状态
        • 3.3.1 R状态和S状态
        • 3.3.2 T状态
        • 3.3.3前台进程与后台进程
        • 3.3.4 D状态
        • 3.3.5 t状态
        • 3.3.6 X状态
        • 3.3.7 Z状态
          • 3.3.7.1为什么会有Z状态?(感性认识)
          • 3.3.7.2查看Z状态进程
            • 僵尸进程的危害
      • 3.4进程状态总结
      • 3.5孤儿进程
          • 关于孤儿进程需要知道的:

Linux—进程学习—2

1.通过系统调用创建进程—fork

1.1fork创建子进程

  • fork是一个用c语言写的函数,代码本身这个进程对于fork创建出来的进程就是父进程,而fork创建的进程对于代码本身被加载到内存的这个父进程就是子进程。

下图是一个使用fork创建子进程的例子:

image-20241106192546469

image-20241106192623737

可以看到fork创建的进程pid是20077,而父进程pid是20076,而父进程20076的父进程肯定是bash了。

1.2fork函数的返回值

下图是对于fork函数返回值的官方回答。

image-20241106194118690

  • 如果fork创建子进程成功,那么对于父进程会返回子进程的pid,对于子进会返回0.

  • 如果fork创建子进程失败,那么对于父进程返回一个-1、

下面是一个证明返回值的例子:

代码如下:

image-20241106194600049

运行结果如下:

image-20241106194531464

确实是和官方说的一样,对于不同的进程一个fork函数实现了不同的返回值。

可是这里有个问题,id这个变量是没有被改变过的,那是怎么实现返回不同的值的?

目前我的能力还不能解决,还等到学习进程地址空间的知识之后,才能够明白

1.3利用fork实现多进程

代码如下:

image-20241109123007037

执行结果如下:

image-20241106201015152

执行结果告诉我们,走进了两个分支,执行了两个死循环,这在之前打的代码中是没有出现的。这是因为fork创建了一个进程。

fork函数之后的代码是被父进程和子进程共享的,也就是一起执行的

这种编程方式也叫并发式编程

2.有关cpu的常识了解

cpu只能被动的接受别人的指令和数据来执行和计算。

这就要求cpu必须能够认识别人的指令,在编写代码的时候,如果想要执行代码,那么代码就必须要被编译成二进制可执行文件,其实就是编译成了cpu能够读懂的指令集,为什么cpu能够读懂呢?因为cpu有内置指令集

这个编译的过程也和此时cpu是64位环境还是32位环境有关系。如果此时cpu是64位环境,那么就要安装x64的环境去编译程序。这样cpu才能够读懂编译出来的指令,能够接受并运算。

image-20241109101824052

这也可以回答为什么程序要被加载到内存中,因为硬件规定了所有设备都只能和内存进行交互、如果程序不加载到内存中,cpu读不到

3.进程状态

为了更好的管理进程,操作系统(OS)会将进程分为多种状态

进程的状态有很多种:运行、就绪、新建、停止、死亡、挂起、阻塞、挂机、等待

3.1从操作系统层面了解进程状态

3.1.1就绪和新建状态的理解

关于新建和就绪状态的区别,不同的操作系统有不同的说法。

这里可以理解就绪和新建是同一种状态,指的都是可执行二进制文件被加载到内存中时,操作系统新建的进程。此时该进程的PCB内对该进程的状态的描述就是就绪和新建

3.1.2运行和阻塞状态的理解

要想理解运行和阻塞状态、需要先了解一下运行队列

在大多数的情况下,cpu只有一个,进程却有很多,为了让每个进程都会被运行,因此cpu需要一个运行队列。【就像需要人吃饭需要排队,进程要被执行也需要排队,因为cpu只有一个】

image-20241109200500983

由于cpu执行进程的速度很快,因此被cpu执行中的进程和运行队列中的进程,进程的状态都是运行状态®【注意了,不是只有在cpu中被执行的进程才叫做运行状态,进程在运行队列中准备好被cpu调用也叫运行状态】

除了运行状态R,还有很多其他状态。

进程的状态是属于进程的一种属性,在PCB中可能会以整数来区分,很可能运行状态就是1,死亡状态就是2,停止状态就是3等等【可能就会以宏定义实现】

要注意:

进程或多或少都会访问硬件资源、

不要认为进程只会占用cpu资源【在运行队列等代被cpu调用】,进程很有可能也会占有其他硬件资源,因为其他硬件资源往往也只有一个【比如网卡,显示器,磁盘】

因此,不只是cpu会有运行队列的存在,其他硬件资源也存在类似运行队列的等待队列的存在。比如有多个进程都需要访问网卡,那么就按照等待队列一个一个来。

image-20241109210724555

**但是这样也有个问题:**外设处理进程的速度相比cpu处理进程的速度慢很多,访问外设的进程,往往是一个程序中有访问外设的需求,当cpu执行该进程到需要访问外设的时候,难道cpu要等待该进程访问外设完毕吗?那样的效率会很低。

image-20241109212613245

因此操作系统会将需要访问外设的进程给链接到对应外设的等待队列去【此时进程的状态会从运行状态®,转变为阻塞状态】,等正在占用硬件资源的进程结束了,也就是硬件可以接受下一个进程的访问了,才会回到cpu的运行队列继续执行【此时进程状态从阻塞状态转变为运行状态】

这样cpu无需等待进程在对应硬件的等待队列的等待时间,可以一直的执行处于运行状态的进程。

总结:

  1. 一个cpu会有一个运行队列、
  2. 进程入队列的本质:将该进程的pcb对象放到运行队列里面
  3. pcb在运行队列中以及被运行时的状态都是运行状态®
  4. 进程状态是进程的一种属性,在PCB中很可能以整数(int)区分
  5. 进程不止会占用cpu资源,也会很可能占用外设资源
  6. 进程的不同状态,本质是进程在不同的队列中,等待某种资源。
3.1.3挂起状态的理解

挂起状态和阻塞状态是两种不同的状态,要区分清楚。

阻塞状态是cpu执行的进程需要访问某个硬件资源,但是这个硬件资源此时正在被别的进程占用,因此操作系统就会将该进程的pcb添加到对应硬件资源的等待队列中,此时该进程的状态就有运行状态变成阻塞状态

此时就会有一种情况:如果在内存中存在着非常多的进程,这些进程全部都要访问某个硬件资源、因此这些进程都被放进了对应硬件的等待队列,都是阻塞状态。但是一旦某个进程变成了阻塞状态,就意味着该进程短时间内无法被cpu调度。当阻塞状态的进程非常多时,内存的空间会不足!【因为有很多阻塞状态的进程,短时间内不会被调度,但是又在内存中占据着空间】

image-20241110125017386

因此,如果内存空间不足了,操作系统会将部分阻塞状态的进程的代码和数据移动到磁盘中【此时的状态由阻塞状态变成了挂起状态】,这样就可以将内存的空间腾出,继续执行其他进程了。

要注意:是将阻塞状态的进程的代码和数据移动到磁盘挂起,该进程的pcb仍然存在于内存中【因为pcb不大,不占多少内存空间】

image-20241110123833654

当该进程所等待的硬件资源此时准备好了之后,该进程的代码和数据就会被重新转移到内存当中去【不用担心此时内存没有空间,因为操作系统既然会将该进程挂起,自然也会为了该进程,将其他进程挂起】、并且将该进程的状态由挂起状态转变为运行状态。

而这个进程数据在内存和磁盘之间的转移,被叫做——内存数据的换入和换出

挂起和阻塞的区别
  • 挂起一定阻塞、阻塞不一定挂起

如果内存空间足够大,可以阻塞不需要挂起,但是如果内存空间不够了,部分阻塞状态的进程就需要转变为挂起状态,来为内存腾出更多空间

有一些操作系统会将挂起和其他状态组成一些新状态,比如阻塞挂起状态、比如新建挂起状态、意思就是正在阻塞的进程被挂起,以及刚新建的进程就被挂起了。

3.1.4总结

上面主要讲述了运行、阻塞、挂起状态的理解

其实不同的操作系统对于不同的状态是有不同的说法的,并且在实现上也有区别

挂起状态,在讲解操作系统的书里会叫做挂起,但是具体到操作系统中,可能不会将挂起这个状态暴露给我们知道。比如Linux

因此只要在操作系统的层面上大致理解,运行、阻塞、挂起状态的过程即可

3.2Linux中对进程状态的描述

上面所说的情况状态是一个大致的概括和总结,如果想要了解进程的具体状态,就必须挑选一个具体的操作系统来讲。

上面对进程的状态有了初步的理解,那么在Linux操作系统中,所谓各种状态是如何描述的?怎么实现的?

一个进程可以有几个状态(在Linux内核里,进程有时候也叫做任务)。

下面的状态在kernel源代码里定义:

/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};
  • R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。

  • S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠

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

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

  • X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态

这么多状态的存在,都是为了更好的应对不同的场景。

3.3查看进程状态

3.3.1 R状态和S状态

R(运行)、S(睡眠)

写一个死循环代码先,里面一直在执行重复的计算

image-20241111202703520

此时如果抓取进程信息,会发现进程状态是R+,也就是运行状态。至于R+的+后面会学习什么情况

image-20241111203313378

但是如果我们每次都将a打印出来,那么此时进程状态是什么呢?

image-20241111203409850

此时就会变成S+,睡眠状态

image-20241111203446517

这是为什么?明明一直在执行死循环。

其实是因为这里多了一个向显示器输出的代码,这意味着该进程需要访问显示屏这个硬件。但是cpu的计算是非常快的,而与IO的过程相比与cpu的计算是非常慢的,这就导致了这个进程的大部分时间都在等待显示器的就绪,显示器就绪后再输出。因此这个进程有99%的时间都在等待显示器,因此该进程的绝大多数时间的状态是S状态。【但是查到R状态的概率不为0】

要注意:

在Linux当中阻塞状态的一种就是上面所说的S状态,阻塞状态不是只有S,还有其他状态

3.3.2 T状态

其实在教材中是没有暂停状态(T)的,一般都归类到挂起或者阻塞里去。但是在Linux中,具体一点就有暂停状态

先看看暂停状态的情况:

下面是代码:

image-20241112111137230

该代码执行的结果就是进程一直处于R状态,此时只需要将其19号信号kill掉即可处于暂停状态。如下图所示

image-20241112111302930

这其实也可以理解成一种阻塞状态,既然该进程处于阻塞状态,代表它也有可能是挂起的状态,但是不知道到底是不是挂起的状态,这完全取决于操作系统如何处理的。Linux系统认为是我们并不需要知道该进程到底是挂起还是阻塞

既然可以通过kill来让其暂停,自然也可以通过kill让其继续执行,如下图所示:

image-20241112111822665

但是此时的R少了个+,这代表其变成了后台进程

3.3.3前台进程与后台进程

其实就是R+和R的区别

  • R+代表当前进程处于运行状态并且是前台进程

  • R代表当前进程处于运行状态并且是后台进程

前台进程——当运行进程之后,shell命令行无法在获取命令行来解析了,但是可以使用ctrl + c终止

后台进程——当运行进程后,shell命令行仍然可以获取命令行并解析,并且无法使用ctrl + c终止。

这有什么区别呢,其实一个可以被ctrl + c终止,一个不可以

下面是实验:

image-20241112112811126

image-20241112112635620

image-20241112113229036

image-20241112112712788

3.3.4 D状态

深度睡眠状态(D),这个状态也是比较少见的状态。

深度睡眠状态(D)和睡眠状态(S)状态的区别:

  • D状态是无法被ctrl + c终止的,能被ctrl + c终止的状态是S状态
  • D状态无法被OS杀死,只能通过断电,或者进程自己醒来,来解决

但是D状态的实验不好做,搞不好Linux系统就死机了。

这里可以讲述一个场景,也就是会出现D状态的高IO场景

image-20241112120933621

内存当中的进程数量太多,导致操作系统的内存实在是没有空间来放下更多的进程了,但是IO的速度又特别慢,有一个进程A此时正在占用磁盘,但是后面还有几千个进程在等待磁盘,这几千个进程部分处于等待队列,部分被操作系统挂起到磁盘中来腾出更多的内存空间,但是进程A给磁盘的任务是保存100000个转账记录,需要一定的时间,但是此时内存空间要爆了,能挂起的都挂起了,但是内存还是要爆了,此时操作系统就会说你这个进程A,占用时间这么久,直接把你杀了,来腾出空间给其他进程使用。那么进程A就被杀死了,此时磁盘不幸的存储数据失败,正想和进程A汇报,存储失败的时候,发现进程A找不到了,并且来了下一个进程B带着任务来了,磁盘此时又要上班了,那么之前这个存储失败的数据怎么办呢?磁盘说不管了,丢掉了,继续上班。这就意味着数据丢失了

这个时候数据的丢失对于用户来说就很懵逼啊,不是哥们,我让你帮我存个数据,你告诉我数据没了,找不到了。

但是这个时候能怪谁呢?你怪操作系统,操作系统也很懵逼啊,你给我的任务就是管理好软硬件资源,我没死机不错了。你怪磁盘,磁盘也很懵逼啊,我虽然写入数据的成功率很高,但是我也有失败的时候啊,我反馈的时候,还反馈不了呢?你怪进程A吗,进程A也很无语啊,我就是老老实实干着自己的活,让磁盘去干活,磁盘干的慢我等,我直接被杀死了,这也能怪我吗?

这个时候用户就给操作系统制定了一个新规则:就是当遇到这个情况的时候,将进程A标记为深度睡眠状态,不要杀死进程A了,这样就不会丢失数据了、并且也能腾出内存空间给其他进程使用

因此D状态无法被OS杀死,只能通过断电,或者进程自己醒来,来解决

3.3.5 t状态

小t状态在Linux内核中其实也是T状态,即暂停状态。**t状态也是一种暂停状态,表示被追踪,**这里我们通过实验来查看t状态

先写一个程序和Makefile,方便实验。

  • Makefile

image-20241114122806543

这里面的**$@代表目标文件,%^代表依赖路径文件,-g是希望编译出来的可执行文件是debug模式**,可以使用gdb调试器调试

  • 程序

image-20241114122921625

然后make一下,然后去调试一下。

image-20241114124306807

此时抓取进程状态,会发现变成了t状态**,t状态也是一种暂停状态,表示该进程正在被追踪!**

image-20241114124332833

此时进程在等待gdb调试器的下一步,然后才能继续运行。也就是在等待硬件—键盘的输入

3.3.6 X状态

X(dead)是死亡状态

X状态是不好做实验的,因为一旦进程变成了X(死亡)状态,那么操作系统就会将该进程回收、这个回收过程对我们来说是很快的,操作系统一下就回收完了,因此我们很难通过查看进程状态来直接查看一个进程是(X)死亡的状态

不过X状态也不难理解,就是一个进程死亡了,然后会被操作系统回收。

3.3.7 Z状态

Z(zombie)状态可以叫做僵死状态,也可以称作僵尸状态

  • 僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用,后面讲)没有读取到子进程退出的返回代码时就会产生僵死(尸)进程

  • 僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。

  • 所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态

这里所提到的读取进程中的读取过程还没有学习,等到后面学习进程控制会知道。今天只是见到为什么会有Z状态的进程,以及Z状态进程什么情况会出现即可。

僵尸进程是一个问题——进程退出了,但是没有被回收

这个问题后面会解决,今天只是知道有这个东西即可

3.3.7.1为什么会有Z状态?(感性认识)

一个进程,往往是带着任务去运行的,因此进程也被称作任务。而既然进程需要执行任务,那么作为操作系统肯定得知道当前进程是否完成任务,完成的怎么样了。

因此当一个进程退出的时候,不能直接将其标记为(X)死亡状态,然后释放资源并回收该进程。而是要让父进程或者OS去读取该进程的执行结果,读取该进程是什么原因退出的【是成功完成之后退出的,还是遇到了什么错误退出的】。

而该进程退出时,被保留资源并被父进程或者OS读取的这个状态就是僵死状态。

当父进程或者OS读取完之后,该进程就由Z状态变成X状态,然后被OS释放资源并回收该进程

结论:因为OS需要得知一个进程退出时是因为什么原因退出的【是成功完成之后退出的,还是遇到了什么错误退出的】,所以会需要僵尸状态,僵尸状态的进程就会被父进程或者OS读取。

3.3.7.2查看Z状态进程

**做个可以查看到Z状态进程的实验:**让父进程去创建一个子进程,然后让子进程正常退出,但是父进程不允许去做相关回收子进程的动作,此时子进程就是Z状态。因为父进程没有来读取子进程。

写一个实验的程序:

image-20241114154740667

然后为了方便查看到子进程转变到Z状态,这里写一个简单的监控脚本

while :; do ps axj | head -1 && ps axj | grep "process" | grep -v grep; sleep 1; done

这个句指令的执行效果就是,每隔一秒不断循环抓取process进程的状态信息。

  • 实验结果:

代码执行结果:

image-20241114155513274

抓取进程的信息结果:

image-20241114155717346

根据我们的代码,我们知道,子进程在被创建出来5秒后就退出了。而抓取进程的结果也是如此,从第5秒开始,子进程的状态就变成了Z+。并且这里出现了一个单词<defunct>,这个单词的意思就是失效的。也说明了这个子进程其实已经死掉了,但是还没有被回收。

解释:为什么子进程在第5秒的时候变成了Z+,并且后面一直都是Z+呢?

一开始两个进程的状态都是S+,这个前面也有说,这里不详细讲,就是父进程和子进程都在等待硬件资源,并且都是前台程序。

为什么子进程在第5秒的时候变成了Z+,并且后面一直都是Z+呢?

  1. 这是因为代码中,子进程在第五秒的时候执行了exit(1),这个代码,导致子进程退出了,返回的是1。此时子进程等待被读取,自然变成了Z+状态【+是因为仍然是前台进程】
  2. 正常来说父进程这个时候要去读取子进程,知道子进程为什么退出,然后子进程才能变成X状态,从而被OS回收。
  3. 但是代码中,此时父进程陷入了一个死循环,一直在执行和读取子进程无关的操作,这就导致了子进程一直没有被读取,既然没有被读取,自然就一直在等待被读取
  4. 因此子进程在第五秒之后,一直处于Z+状态。

因此这个子进程也被叫做僵尸进程【一直处于僵尸状态】,这是有问题的!如何解决呢?需要学习进程控制的知识才能解决。

这里先了解一下僵尸进程的危害

僵尸进程的危害
  • 进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样了。

可父进程如果一直不读取,那子进程就一直处于Z状态!

  • 维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中。

换句话说,Z状态一直不退出,PCB一直都要维护!PCB一直都需要存在!

  • **那一个父进程创建了很多子进程,就是不回收,就会造成内存资源的浪费!**因为数据结构对象本身就要占用内存,想想C中定义一个结构体变量(对象),是要在内存的某个位置进行开辟空间

也就是说,僵尸进程会导致内存泄漏!

3.4进程状态总结

  1. 经过上述学习,已经初步理解了全体操作系统层面下进程状态中的运行,阻塞和挂起。
  2. 往往理论和实践是不太一样的,每个操作系统对于进程状态的理解和实现都是不太一样的、
  3. 学习了Linux操作系统中,对于进程状态的理解。并实验了大部分能查看的进程状态。【R S T D t X Z】
  4. 在Linux中前台进程和后台进程的区别

3.5孤儿进程

前面有讲到僵尸进程——即子进程退出时没有被父进程回收,子进程一直处于僵尸状态

现在再来看看孤儿进程

  • 父进程如果提前退出,那么子进程后退出,进入Z之后,是如何处理的呢?

  • 父进程先退出,子进程就称之为“孤儿进程”

  • 孤儿进程被1号init进程领养,当然要由init进程回收。

**下面是实验:**让将一个进程创建一个子进程,并将该进程杀掉,此时子进程就变成了孤儿进程。【父进程被操作系统回收了】

image-20241114211227434

此时子进程就会被进程1接管,1号进程成为了子进程的新的父进程。【1号进程就是操作系统】,这个过程可以说是1号进程领养了这个孤儿进程

并且子进程的状态变成了S(睡眠),从前台进程变成了后台进程。

image-20241114212357110

关于孤儿进程需要知道的:
  • 孤儿进程这个情况是一定会存在的。【谁也不能保证父进程一定会比子进程完被杀死】

  • 为什么孤儿进程要被操作系统领养?

因为孤儿进程如果不被操作系统领养,那么等到其正常执行或者遇到某种错误,进程退出处于僵尸状态的时候,就没有父进程来读取孤儿进程,那么就会一直处于僵尸状态。变成一个僵尸进程,从而造成内存泄漏。

  • 孤儿进程被领养之后会从前台进程变成后台进程

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

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

相关文章

基于yolov8、yolov5的鱼类检测识别系统(含UI界面、训练好的模型、Python代码、数据集)

项目介绍 项目中所用到的算法模型和数据集等信息如下&#xff1a; 算法模型&#xff1a;     yolov8、yolov8 SE注意力机制 或 yolov5、yolov5 SE注意力机制 &#xff0c; 直接提供最少两个训练好的模型。模型十分重要&#xff0c;因为有些同学的电脑没有 GPU&#xff0…

【数据价值化】国有企业数据资产入表及估值实践指南:挖掘数字资产新价值

在当今数字化转型的浪潮中&#xff0c;国有企业作为国民经济的支柱&#xff0c;正积极探索如何更好地管理和利用自身的数据资产。数据&#xff0c;这一新时代的“石油”&#xff0c;正逐渐成为驱动国有企业创新发展的关键要素。然而&#xff0c;如何准确地将数据资产纳入企业财…

AndroidStudio-常用布局

一、线性布局LinearLayout 线性布局内部的各视图有两种排列方式: 1.orientation属性值为horizontal时&#xff0c;内部视图在水平方向从左往右排列。 2.orientation属性值为vertical时&#xff0c;内部视图在垂直方向从上往下排列。 如果不指定orientation属性&#xff0c;…

力扣-Mysql-3308- 寻找表现最佳的司机(中等)

一、题目来源 3308. 寻找表现最佳的司机 - 力扣&#xff08;LeetCode&#xff09; 二、数据表结构 表&#xff1a;Drivers ----------------------- | Column Name | Type | ----------------------- | driver_id | int | | name | varchar | | age …

【汇编语言】包含多个段的程序(二)—— 将数据、代码、栈放入不同的段

文章目录 前言1. 存在的两个问题2. 解决办法3. 示例代码3.1 程序说明3.1.1 定义多个段的方法3.1.2 对段地址的引用3.1.3 各种段完全是我们的安排 4. 总结结语 前言 &#x1f4cc; 汇编语言是很多相关课程&#xff08;如数据结构、操作系统、微机原理&#xff09;的重要基础。但…

Iotop使用

文章目录 Iotop依赖及编译1:内核配置2: 环境配置3.依赖库ncurses3.1 Ncurses的编译配置 4. Iotop的编译及修改5.测试效果如下&#xff1a; Iotop依赖及编译 源码路径&#xff1a;https://github.com/Tomas-M/iotop#how-to-build-from-source (GitHub - Tomas-M/iotop: A top u…

LaTeX之四:如何兼容中文(上手中文简历和中文论文)、在win/mac上安装新字体。

改成中文版 如果你已经修改了.cls文件和主文档&#xff0c;但编译后的PDF仍然显示英文版本&#xff0c;可能有以下几个原因&#xff1a; 编译器问题&#xff1a;确保你使用的是XeLaTeX或LuaLaTeX进行编译&#xff0c;因为它们对Unicode和中文支持更好。你可以在你的LaTeX编辑器…

java的JJWT 0.91在jdk21中报错的解决方法

参考了很多其他人的办法&#xff0c;只有这种方式可以解决问题 JSON Web Token&#xff08;缩写 JWT&#xff09; 目前最流行、最常见的跨域认证解决方案&#xff0c;前端后端都需要会使用的东西 如果根据黑马的视频&#xff0c;导入了阿里云OSS的相关依赖&#xff0c;自然不会…

卷积、频域乘积和矩阵向量乘积三种形式之间的等价关系与转换

线性移不变系统 线性移不变系统&#xff08;Linear Time-Invariant System, LTI系统&#xff09;同时满足线性和时不变性两个条件。 线性&#xff1a;如果输入信号的加权和通过系统后&#xff0c;输出是这些输入信号单独通过系统后的输出的相同加权和&#xff0c;那么该系统就…

一文窥见神经网络

一文窥见神经网络 1.初识神经元1.1 生物神经元1.2 人工神经元1.3 权重的作用1.4 偏置的作用1.5 激活函数的作用1.5.1 线性激活函数1.5.2 非线性激活函数 2. 神经元模型2.1 多输入单神经元模型2.2 一层神经元模型2.3 神经网络&#xff08;多层神经元&#xff09;模型 3. 神经网络…

DBeaver 连接 OceanBase Oracle 租户

DBeaver 是一款通用的数据库工具软件&#xff0c;支持任何具有JDBC驱动程序的数据库。DBeaver 需要 Java 运行环境的支持。截稿时 DBeaver 24.0.0 版本默认提供的 OceanBase 驱动是连接 MySQL 的&#xff0c;想连接 Oracle 租户需要新建一个驱动器使用。 下载数据库驱动包 1、…

web实操5——http数据详解,request对象功能

http请求数据 现在我们浏览器f12的那些是浏览器给http格式数据整理之后便于我们阅读的。 原始的http格式信息&#xff1a; 就是按照一定格式和符号的字符串&#xff1a; 请求行&#xff1a;格式如下图 请求头&#xff1a;一个个key&#xff0c;value数据&#xff0c;用,分割…

u盘加密软件有哪些?2025年必备的u盘加密神器分享(共6款!提前布局!)

2024年《数据泄露成本报告》最新出炉&#xff01;再破纪录&#xff01; 报告显示&#xff0c;全球数据泄露事件的平均成本达488万美元&#xff0c;同比增加10%。 其中&#xff0c;u盘最为数据存储和传输的常用媒介&#xff0c;对其进行加密早已箭在弦上&#xff01; 在2025年…

实验5:网络设备发现、管理和维护

实验5&#xff1a;网络设备发现、管理和维护 实验目的及要求&#xff1a; 通过实验&#xff0c;掌握Cisco 路由器和交换机的IOS配置管理。自动从NTP服务器获取时间信息。能够利用TFTP服务器实现路由器和交换机配置文件的备份和恢复。同时验证CDP协议和LLDP协议的网络参数。完…

基于java的航空机票预定管理系统

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue、Element-ui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 数据…

排序算法 -快速排序

文章目录 1. 快速排序&#xff08;Quick Sort&#xff09;1.1、 简介1.2、 快速排序的步骤 2. Hoare 版本2.1、 基本思路1. 分区&#xff08;Partition&#xff09;2. 基准选择&#xff08;Pivot Selection&#xff09;3. 递归排序&#xff08;Recursive Sorting&#xff09; 2…

UAC2.0 speaker——同时支持 16bit,24bit 和 32bit

文章目录 同时支持 16bit,24bit 和 32bit配置描述符集合描述符结构位数切换16bit 选择24bit 选择32bit 选择枚举效果同时支持 16bit,24bit 和 32bit 在一个 USB speaker 设备中同时支持 16bit, 24bit 和 32bit。 配置描述符集合 09 02 E9 00 02 01 00 80 32 08 0B 00 02

conda创建 、查看、 激活、删除 python 虚拟环境

1、创建 python 虚拟环境 ,假设该环境命名为 “name”。 conda create -n name python3.11 2、查看 python 虚拟环境。 conda info -e 3、激活使用 python 虚拟环境。 conda activate name 4、删除 python 虚拟环境 conda remove -n name --all ​​ 助力快速掌握数据集…

三周精通FastAPI:37 包含 WSGI - Flask,Django,Pyramid 以及其它

官方文档&#xff1a;https://fastapi.tiangolo.com/zh/advanced/wsgi/ 包含 WSGI - Flask&#xff0c;Django&#xff0c;其它 您可以挂载多个 WSGI 应用&#xff0c;正如您在 Sub Applications - Mounts, Behind a Proxy 中所看到的那样。 为此, 您可以使用 WSGIMiddlewar…

微服务即时通讯系统的实现(客户端)----(1)

目录 1. 项目整体介绍1.1 项目概况1.2 界面预览和功能介绍1.3 技术重点和服务器架构 2. 项目环境搭建2.1 安装Qt62.3 安装vcpkg2.3 安装protobuf2.4 构建项目2.5 配置CMake属性 3. 项目核心数据结构的实现3.1 创建data.h存放核心的类3.2 工具函数的实现3.3 创建编译开关 4. 界面…