SystemVerilog学习笔记(十):进程/细粒度进程控制

news2025/1/4 19:54:31

进程

进程或线程是作为独立实体执行的任何代码片段。fork-join块创建并行运行的不同线程。在下面的图-1中,可以看到进程的类型和进程控制。

序号进程描述
1.fork-join只有所有子线程执行完毕时,父线程才会执行。
2.fork-join_any只有任何一个子线程执行完毕时,父线程才会执行。
3.fork-join_none父线程与子线程并行执行。
4.wait fork使父线程等待所有子线程执行完毕。
5.disable fork当执行disable fork时,会终止所有子线程的执行。
6.细粒度进程控制这些用于控制进程,并提供进程/线程的状态。

 进程或线程

有3种类型的线程/进程

  1. fork-join
  2. fork-join_any
  3. fork-join_none 

fork-join

SystemVerilog通过fork-join结构支持并行线程。在fork-join进程中,只有当所有子线程完成执行时,父线程才会执行。

语法:-

fork  
   线程1  
   线程2  
   线程3
join

代码片段:-

$display("[%0t] Thread_T1: a的值为%0d,b的值为%0d,c的值为%0d,d的值为%0d",$time,a,b,c,d);

fork:FORK_F1  

   begin:BEGIN_B2  
      #1 a <= b;  
      b <= 7;  
      $monitor("[%0t] Thread-T2: a的值为%0d,b的值为%0d,c的值为%0d,d的值为%0d",$time,a,b,c,d);  
      #1 ->e1;  
      c = b;  
   end:BEGIN_B2  

   begin:BEGIN_B3  
      wait(e1.triggered);  
      $display("[%0t] 事件已触发",$time);  

      begin:BEGIN_B4  
        #1 d = c;  
      end:BEGIN_B4  

   end:BEGIN_B3  

join:FORK_F1 

$display("[%0t] Thread_T3: a的值为%0d,b的值为%0d,c的值为%0d,d的值为%0d",$time,a,b,c,d); 

输出
在图-2中,我们可以看到Thread_T1首先在#0模拟时间执行,但是Thread_T3将在所有子线程执行完毕后才执行,子线程将根据时间延迟执行。

fork_join_output

在图-3中,可以清楚地了解关于fork-join代码的整个工作方式,以及与时间表区域相关的调度原理。

  • 变量的取样将在提前的区域中完成。
  • 所有阻塞赋值将在活动区域执行,所有非阻塞赋值将在活动区域中评估。
  • 事件将在活动区域执行。
  • $display语句将在活动区域执行。
  • 所有#0延迟语句将在非活动区域中执行。
  • 评估的非阻塞赋值将在NBA区域中执行。
  • $monitor语句将在推迟的区域中执行。

fork_join (1)

fork-join_any

当任何一个子线程完成执行时,父线程将执行。这意味着如果fork-join_any块中有2个或更多线程,并且每个线程需要不同的时间完成。在这种情况下,无论哪个线程先完成,fork-join_any都将退出该块,并开始执行模拟中的下一个父线程/语句。这并不意味着剩余的子线程将被模拟自动丢弃。这些线程将在后台运行。

语法:-

fork  
   Thread 1  
   Thread 2  
   Thread 3  
join_any  

代码片段:-

$display("[%0t] Thread_T1: Starting of fork_join_any",$time);

a = "Kapu";
c = "Malpe";

fork:FORK_F1  

   begin:BEGIN_B2  
      #0 $display("[%0t] Thread_T2: Values of a =%0s,b =%0s,c =%0s,d =%0s",$time,a,b,c,d);  

      begin:BEGIN_B3  
         b <= a;  
         #1 $display("[%0t] Thread_T3: Values of a =%0s,b =%0s,c =%0s,d =%0s",$time,a,b,c,d);  
      end:BEGIN_B3  

   end:BEGIN_B2  

   fork:FORK_F2  

      begin:BEGIN_B4  
         #3 -> e1;  
         $display("[%0t] Thread_T4: Values of a =%0s,b =%0s,c =%0s,d =%0s",$time,a,b,c,d);  
      end:BEGIN_B4  

   join:FORK_F2  
      
join_any:FORK_F1

#1 $display("[%0t] Thread_T5: Values of a =%0s,b =%0s,c =%0s,d =%0s",$time,a,b,c,d);
    
begin:BEGIN_B5
   wait(e1.triggered);
   d = "Kodi";
   $monitor("[%0t] Thread_T6: Values of a =%0s,b =%0s,c =%0s,d =%0s",$time,a,b,c,d);
end:BEGIN_B5

输出:-
在下图中,我们可以看到父线程Thread_T1在#0处执行,子线程Thread_T3在#1处执行,然后只有父线程Thread_T5将在#2处执行。

Untitled Diagram drawio (23)

fork join_any

fork-join_none

父线程与子线程并行执行。这意味着在fork-join_none外部的线程不会等待fork-join_none内部的任何线程完成,它们只是并行执行。这并不意味着模拟会自动丢弃其余的子线程。这些线程将在后台运行。

语法:-

fork 
   Thread 1  
   Thread 2  
   Thread 3  
join_none 

代码片段:-

$display("[%0t] Thread_T1: Starting of fork_join_none",$time);

a = "Kapu";
c = "Malpe";

fork:FORK_F1  

   begin:BEGIN_B2  
      #1 $display("[%0t] Thread_T2: Values of a =%0s,b =%0s,c =%0s,d =%0s",$time,a,b,c,d);      
      b <= a;  
      #1 $display("[%0t] Thread_T3: Values of a =%0s,b =%0s,c =%0s,d =%0s",$time,a,b,c,d);  
   end:BEGIN_B2  

   fork:FORK_F2  
      #1 -> e1;  
      $display("[%0t] Thread_T4: Values of a =%0s,b =%0s,c =%0s,d =%0s",$time,a,b,c,d);  
   join:FORK_F2  

join_none:FORK_F1

#1 $display("[%0t] Thread_T5: Values of a =%0s,b =%0s,c =%0s,d =%0s",$time,a,b,c,d);

wait(e1.triggered);
d = "Kodi";

$monitor("[%0t] Thread_T6: Values of a =%0s,b =%0s,c =%0s,d =%0s",$time,a,b,c,d);

输出:在下图中,在#0处执行父线程Thread_T1和子线程Thread_T4,然后在#1处同时执行父线程Thread_T5和子线程Thread_T2,以此类推。

Untitled Diagram drawio (28)

fork_join_none


进程控制

System Verilog提供了允许一个进程终止或等待其他进程完成的构造。

  1. wait fork
  2. disable fork
  3. 细粒度进程控制

wait fork

wait fork语句用于确保所有子进程(由调用进程创建的进程)都已完成执行。它将等待直到所有fork进程完成执行。

代码片段:-

#1 $display("[%0t] Thread_T1: values of a = %0s,b = %0s,c = %0s",$time,a,b,c);

fork:FORK_F1  

   #2 b <= "Delta";  
   #0 $display("[%0t] Thread_T2: values of a = %0s,b = %0s,c = %0s",$time,a,b,c);  

   begin:BEGIN_B2  
      #1 -> e1;  
      c = "Hoode";  
      #1 $display("[%0t] Thread_T3: values of a = %0s,b = %0s,c = %0s",$time,a,b,c);  
   end:BEGIN_B2  

   fork:FORK_F2  
      wait(e1.triggered);  
      #2 $display("[%0t] Thread_T4: values of a = %0s,b = %0s,c = %0s",$time,a,b,c);  
   join:FORK_F2  

   #1 $display("[%0t] Thread_T5: values of a = %0s,b = %0s,c = %0s",$time,a,b,c);  

join_none:FORK_F1  

wait fork;  
#0 $monitor("[%0t] Thread_T6: values of a = %0s,b = %0s,c = %0s",$time,a,b,c);  

输出:-

在下图中,我们看到在#1处,父线程Thread_T1将被执行,并且有一个#0语句将在非活动区域中工作,语句将在相应区域中执行。尽管我们使用了fork-join_none,但$monitor语句将等待所有子线程被执行。

wait_fork

disable fork

执行disable fork时,所有活动的进程都将被终止。

代码片段:-

#0 $display("[%0t] Thread_T1: Values of a = %0s,b = %0s,c = %0s",$time,a,b,c);

fork:FORK_F1  

   #3 b <= "Delta";  

   #4 $display("[%0t] Thread_T2: Values of a = %0s,b = %0s,c = %0s",$time,a,b,c);  
             
   begin:BEGIN_B2  
      #1 -> e1;  
      c = "Hoode";  
      #1 $display("[%0t] Thread_T3: Values of a = %0s,b = %0s,c = %0s",$time,a,b,c);  
   end:BEGIN_B2  
      
   fork:FORK_F2  
      @(e1.triggered);  
      #1 $display("[%0t] Thread_T4: Values of a = %0s,b = %0s,c = %0s",$time,a,b,c);  
   join:FORK_F2  
      
   #1 $display("[%0t] Thread_T5: Values of a = %0s,b = %0s,c = %0s",$time,a,b,c);  

join_any:FORK_F1  

disable fork;  
#1 $display("[%0t] Thread_T6: ending of fork-join",$time);   

输出:-

在下图中,在#0处,我们正在等待事件被触发,#0语句将在活动区域中执行,因为它是$display语句。 在#1处,它正在触发事件e1,并且一个子线程Thread_T5将被执行,然后由于使用了fork-join_any,它将转到父线程并触发disable fork语句,然后所有剩余的子线程将被终止。

细粒度进程控制 

SystemVerilog有一个内置的名为Process的类,允许一个进程(例如,像fork_join)访问和控制进程/线程。当我们分叉出任何线程时,会在那时创建Process类的新对象。该对象包含有关该线程的状态信息。

Untitled Diagram drawio (5)

序号任务描述
1.self()用于创建进程的ID/对象。
2.status()用于返回当前线程的模式。
3.kill()用于终止线程。
4.await()用于等待当前线程完成其他线程。
5.suspend()用于暂停线程一段时间。
6.resume()用于从暂停状态恢复线程。

self()

它为Process类创建对象/ID。该对象用于访问Process类的所有预定义方法。对象包含所有线程的状态信息。

语法:-

process p_handle1,p_handle2;  
initial begin 
   p_handle1 = process :: self();  
   p_handle2 = process :: self(); 
end  

代码片段:-

fork:FORK_F1  

   $display("[%0t] Entered into fork-join and started first check for the process",$time);  
   #1 ->e1;  

   begin:BEGIN_B2  
      wait(e1.triggered);  
      if(p1 == null)  
         $display("[%0t] Not created",$time);  
      else  
         $display("[%0t] Created",$time);  
      ->e3;  
      #1 ->e2;  
   end:BEGIN_B2  

   #2 p1 = process :: self();  

   begin:BEGIN_B3  
      wait(e2.triggered);
      $display("[%0t] Started second check for the process",$time);  
      if(p1 == null)
         $display("[%0t] Not created",$time);
      else
         $display("[%0t] Created",$time);
      ->e4;
   end:BEGIN_B3
      
   fork:FORK_F2

      begin:BEGIN_B4
         wait(e3.triggered);
         $display("[%0t] first check for the process done",$time);
      end:BEGIN_B4

      begin:BEGIN_B5
         wait(e4.triggered);
         $display("[%0t] Second check for the process done",$time);
      end:BEGIN_B5
      
   join:FORK_F2

join:FORK_F1

在上面的代码片段中,您可以看到在#0模拟时间时声明了进程类的句柄。在下面的图中,

  • 在#1模拟时间时,我们正在检查是否创建了对象p1,然后它显示“未创建”。
  • 在#2模拟时间时,我们为进程p1创建一个对象。
  • 在#3模拟时间时,我们检查对象p1,显示“已创建”。

fine_self_output

fork join_any _self _kill-Page-2 drawio (3)

Status()

它将显示进程ID的状态/模式。有不同的模式,如已完成(Finished)、运行中(Running)、等待中(Waiting)、已挂起(Suspended)、已终止(Killed)。

语法:-

process p_handle;
initial begin
   begin  
      p_handle = process :: self();  
      $display("status : %s",p_handle.status());  
   end
end 

代码片段:-

$display("[%0t] Seeking status:",$time);  

fork:FORK_F1  

   begin:BEGIN_B2  
      p1 = process :: self();  
      #1 $display("[%0t] I am in process p1",$time);  
      $display("[%0t] Initial status of p1: %s",$time,p1.status());  
      #1 $display("[%0t] Still working in p1",$time);  
      ->e1;  
      ->e2;  
   end:BEGIN_B2  
 
   begin:BEGIN_B3  
      p2 = process :: self();  
      wait(e2.triggered);  
      #1 $display("[%0t] I am in process p2",$time);  
      $display("[%0t] Initial status of p2: %s",$time,p2.status());  
      $display("[%0t] Still working in p2",$time);  
      ->e3;  
   end:BEGIN_B3  

   begin:BEGIN_B4  
      wait(e1.triggered);  
      $display("[%0t] Final status of p1: %s",$time,p1.status());  
   end:BEGIN_B4  

   begin:BEGIN_B5  
      wait(e3.triggered);  
      $display("[%0t] Final status of p2: %s",$time,p2.status());  
   end:BEGIN_B5  

   fork:FORK_F2  
      p3 = process :: self();  
      #1 $display("[%0t] I am in process p3",$time);  
      #1 $display("[%0t] status of p3: %s",$time,p3.status());  
      #1 ->e4;  
   join:FORK_F2  

join_any:FORK_F1  

wait(e4.triggered);  
#1 $display("[%0t] Final status of p3: %s",$time,p3.status());  

在下图中,

  • 您可以看到一些字符串是大写的,这些是进程p1和p2的状态。
  • 在不同的模拟时间,进程/线程的状态将根据它们的执行而改变。

    fine_status_output

status drawio (1)

kill()

kill()函数终止进程及其所有子进程。如果进程没有被阻塞(由于等待语句、延迟或等待事件触发),则它将在当前时间戳被终止。

语法:-

Process p_handle1; 
initial begin 
   fork 
      p_handle1 = process :: self();  
      p_handle1.kill(); 
   join_any  
end 

代码片段:-

$display("[%0t] Seeking status:",$time);

fork:FORK_F1  

   begin:BEGIN_B2  
      p1 = process :: self();  
      #1 $display("[%0t] I am in process p1",$time);  
      $display("[%0t] Initial status check of p1: %s",$time,p1.status);  
      ->e1;  

      if(p1.status() != process :: FINISHED)  
         p1.kill();  
         $display("hi i am working");  
         $display("what about you?");  
   end:BEGIN_B2  

   begin:BEGIN_B3  
      wait(e1.triggered);  
      #1 $display("[%0t] Status of p1 before killing: %s",$time,p1.status());  
   end:BEGIN_B3  

join:FORK_F1  

在上述代码片段中,您可以看到在#0模拟时间时创建了进程p1的进程类对象。 在下图中,

  • 在#1模拟时间时,进程p1的状态为RUNNING
  • 在使用kill()方法后的#2模拟时间时,进程p1的状态为KILLED

fine_kill_output

fork join_any _self _kill-Page-3 drawio

await()

这种方法用于允许一个进程等待另一个进程/线程完成。

语法:-

Process p_handle1,p_handle2;  
initial begin  
   fork 
      begin
         p_handle1 = process :: self(); 
         p_handle2.await(); 
      end 
      begin 
         p_handle2 = process :: self();
      end
   join 
end

代码片段:-

在上述代码片段中,我们试图使进程p1等待直到进程p2完成。 在下面的图8中,您可以看到:

  • 在#1模拟时间之前使用await()方法之前,p1的状态为RUNNING
  • 在使用await()方法后的#2模拟时间时,p1的状态为WAITING
  • 一旦p2的状态为FINISHED,则p1的状态也为FINISHED

fine_await_output

await drawio

suspend()

这个方法用于暂停进程/线程的执行。它可以暂停自己或其他进程的执行。执行将暂停,直到遇到resume()方法。 如果进程没有被阻塞(由于等待语句、延迟或等待事件触发),则它将在当前时间戳被暂停。

语法:-

Process p_handle1;  
initial begin  
   fork 
      begin
         p_handle1 = process :: self();
         p_handle1.suspend();  
      end
   join_none 
end 

代码片段:-

在上述代码片段中,我们试图使进程p1永久暂停。 在下面的图10中,您可以看到:

  • 在#1模拟时间之前,暂停p1的状态为RUNNING
  • 在#3模拟时间之后,暂停p1的状态为SUSPENDED

fine_suspend_output

Untitled Diagram drawio (5)

resume()

这个方法用于重新启动被暂停的进程。如果暂停的进程在被阻塞时(由于等待语句、延迟或等待事件触发),则恢复该进程将重新初始化到事件表达式或等待条件为真,或等待延迟到期。

语法:-

Process p_handle1,p_handle2;
initial begin 
   fork  
      begin  
         p_handle1 = process :: self();  
         p_handle1.suspend();  
      end  
      begin 
         p_handle2 = process :: self();
         p_handle1.resume();  
      end  
   join_none  
end

代码片段:-

$display("[%0t] Seeking status:",$time);  

   fork:FORK_F1  

      begin:BEGIN_B2  
         p1 = process :: self();  
         #1 $display("[%0t] I am in process p1",$time);  
         $display("[%0t] Initial status of p1: %s",$time,p1.status());  
         ->e1;  

         if(p1.status() != process :: FINISHED)  
        
         begin:BEGIN_B3  
           #1 $display("[%0t] Status of p1 before suspending: %s",$time,p1.status());  
           p1.suspend();  
           $display("[%0t] Status of p2 in p1 block: %s",$time,p2.status());  
         end:BEGIN_B3  

      end:BEGIN_B2  

      begin:BEGIN_B4  
         wait(e2.triggered);  
         $display("[%0t] Status of p1 before resuming: %s",$time,p1.status());  
         p1.resume();  
         #1 $display("[%0t] Status of p1 after resuming: %s",$time,p1.status());  
         ->e3;  
      end:BEGIN_B4  

      begin:BEGIN_B6  
         p2 = process :: self();  
         #1 $display("[%0t] I am in process p2",$time);  
         $display("[%0t] Initial status of p2: %s",$time,p2.status());  

         if(p1.status() == process :: SUSPENDED)  
            #1 ->e2;  
      end:BEGIN_B6  

      begin:BEGIN_B7  
         wait(e3.triggered);  
         #1 $display("[%0t] Final status of p1: %s",$time,p1.status());  
         $display("[%0t] Final status of p2: %s",$time,p2.status());  
      end:BEGIN_B7  

join:FORK_F1

在上述代码片段中,我们试图在进程p2中恢复进程p1。 在下面的图12中,您可以看到:

  • 在#1模拟时间时,p1的状态为RUNNING
  • 在使用resume()方法之前的#2模拟时间时,p1的状态为SUSPENDED
  • 在使用resume()方法后的#3模拟时间时,p1的状态为FINISHED

fine_resume_output

resume drawio

进程常见问题 

  • fork_join、fork_join_any 和 fork_join_none 之间的区别
fork_joinfork_join_anyfok_join_none
在 fork_join 中,主(父)线程在 fork_join 中的所有线程(子线程)执行完毕后才会执行在 fork_join_any 中,如果任何一个子线程执行,则主(父)线程执行在 fork_join_none 中,子线程和主(父)线程同时执行
  • 我们可以在 fork_join 中使用 wait_fork 吗?

我们知道,在 fork_join 中,仅当 fork_join 中的所有线程执行完毕时,主线程才会执行,因此不需要使用 wait_fork。 我们可以在 fork_join_any 或 fork_join_none 语句后使用 wait fork,以等待 fork-join_any 或 fork_join_none 中的所有线程完成。 因此,在 fork_join 中不需要 wait_fork。

  • 阻塞和非阻塞赋值的区别
阻塞非阻塞
在阻塞赋值中,一条语句执行完毕后,下一条语句将执行,即右侧表达式的第一个表达式被评估并立即分配给左侧变量在非阻塞赋值中,对当前时间单位的所有右侧表达式进行评估,并在时间单位结束时分配给左侧变量
由 " = " 表示由 " <= " 表示
它按顺序执行它并行执行
阻塞用于组合逻辑非阻塞用于时序逻辑
  • wait event 和 @ event 之间的区别

如果我们在相同的延迟下触发 wait 和 @,那么 wait 语句会被执行,因为 wait 捕获速度比 @ 快。

  • 我们可以使用不同延迟执行 wait 和 @ 吗?
module tb;    
    event e;  
    initial begin  
    #20 ->e;  
   $display($time,"thread1");  
   end  
  initial   
    begin  
     #25 @e;  
     $display($time,"thread2");  
    end  
  initial   
   begin  
   #15 wait(e.triggered);  
   $display($time,"thread3");  
   end 
endmodule  

在上面的例子中,我们可以看到事件、wait 和 @ 的延迟是不同的。我们还可以看到这里 @ 的延迟大于事件的延迟,而 wait 的延迟小于事件的延迟,所以这里只有 wait 语句与事件的延迟一起执行。因此,在下面的图中,我们可以看到线程 1 和线程 3 使用相同的延迟(#20)执行。

Untitled Diagram drawio (7)

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

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

相关文章

MySQL技巧之跨服务器数据查询:高级篇-先调用A数据库的MySql存储过程再复制到B数据库的表中

MySQL技巧之跨服务器数据查询&#xff1a;高级篇-先调用A数据库的MySql存储过程再复制到B数据库的表中 基础篇已经描述&#xff1a;借用微软的SQL Server ODBC 即可实现MySQL跨服务器间的数据查询。 而且还介绍了如何获得一个在MS SQL Server 可以连接指定实例的MySQL数据库的…

【数据结构】10.线索二叉树

一、线索二叉树的产生 采用先序、中序、后序三种方法遍历二叉树后都可以得到一个线性序列&#xff0c;序列上的每一个结点&#xff08;除了第一个和最后一个&#xff09;都有一个前驱和一个后继&#xff0c;但是&#xff0c;这个线性序列只是逻辑的概念&#xff0c;不是物理结…

springboot食物营养分析平台-计算机毕业设计源码75335

摘要 随着我国经济的发展,人民生活水平的提高&#xff0c;人们的饮食己由温饱型转向营养型。因此&#xff0c;营养问题日益受到重视。食物营养分析平台采用Java技术&#xff0c;Mysql数据库存储数据&#xff0c;基于Springboot框架开发。系统采用了模块化设计方法&#xff0c;根…

使用elementUI实现表格行拖拽改变顺序,无需引入外部库

前言&#xff1a; 使用vue2element UI&#xff0c;且完全使用原生的拖拽事件,无需引入外部库。 如果表格数据量较大&#xff0c;或需要更多复杂功能&#xff0c;可以考虑使用 vuedraggable库&#xff0c;提供更多配置选项和拖拽功能。 思路&#xff1a; 1. 通过el-table的ro…

开源共建 | 长安链开发常见问题及规避

长安链开源社区鼓励社区成员参与社区共建&#xff0c;参与形式包括不限于代码贡献、文章撰写、社区答疑等。腾讯云区块链王燕飞在参与长安链测试工作过程中&#xff0c;深入细致地总结了长安链实际开发应用中的常见问题及其有效的规避方法&#xff0c;相关内容多次解答社区成员…

Python - 初识Python;Python解释器下载安装;Python IDE(一)

一、初识Python Python 是一种高级编程语言&#xff0c;Python是一种面向对象的解释型计算机程序设计语言&#xff0c;Python由荷兰国家数学与计算机科学研究中心的吉多范罗苏姆&#xff08;&#xff09;Guido van Rossum吉多范罗苏姆&#xff08;&#xff09;于1989 年底发明…

Linux入门攻坚——37、Linux防火墙-iptables-3

私网地址访问公网地址的问题&#xff0c;请求时&#xff0c;目标地址是公网地址&#xff0c;可以在公网路由器中进行路由&#xff0c;但是响应报文的目的地址是私网地址&#xff0c;此时在公网路由器上就会出现问题。公网地址访问私网地址的问题&#xff0c;需要先访问一个公网…

C语言的内存函数(文章后附gitee链接,模拟实现函数)

之前我们已经讲解过了字符型数据的一类字符串函数&#xff0c; 现在我们来讨论字符型以外的数据处理。 1&#xff1a;memcpy 的使用和模拟实现 void * memcpy ( void * destination, const void * source, size_t num )&#xff1b; 注意&#xff1a; 1&#xff1a;函数memcp…

Leetcode 整数转罗马数字

这段代码的算法思想是基于罗马数字的减法规则&#xff0c;将整数转换为罗马数字的字符串表示。下面是详细的解释&#xff1a; 算法步骤&#xff1a; 定义数值和符号对应关系&#xff1a;代码中定义了两个数组&#xff1a;values 和 symbols。values 数组包含了罗马数字的数值&…

【赵渝强老师】MySQL InnoDB的段、区和页

MySQL的InnoDB存储引擎的逻辑存储结构和Oracle大致相同&#xff0c;所有数据都被逻辑地存放在一个空间中&#xff0c;我们称之为表空间&#xff08;tablespace&#xff09;。表空间又由段&#xff08;segment&#xff09;、区&#xff08;extent&#xff09;、页&#xff08;pa…

element-ui-plus给头像avatar增加头像框

template部分&#xff1a; <el-avatar shape"square" :size"50" :fit"fit":src"avatarImg"class"avatar-with-border-image"/>style部分&#xff1a; .avatar-with-border-image {position: relative;margin-top: 5px…

MySQL 忘记 root 密码,使用跳过密码验证进行登录

操作系统版本&#xff1a;CentOS 7 MySQL 忘记 root 密码&#xff0c;使用跳过密码验证进行登录 修改 /etc/my.cnf 配置文件&#xff0c;在 [mysqld] 后面任意一行添加 skip-grant-tables vim /etc/my.cnf 重启 MySQL systemctl restart mysqld 登录 MySQL&#xff08;无 -…

飞书 富文本(Markdown)

飞书机器人webhook支持Markdown格式&#xff0c;包括表格 表格 |Syntax | Description |\n|-------- | -------- |\n|Header | Title |\n|Paragraph | Text |参考 富文本&#xff08;Markdown&#xff09;

jmeter常用配置元件介绍总结之用linux服务器压测

系列文章目录 安装jmeter jmeter常用配置元件介绍总结之用linux服务器压测 1.编写测试脚本2.执行测试脚本 1.编写测试脚本 在linux服务器上进行压测&#xff0c;由于是没有界面的&#xff0c;因此我们可以先在界面上把压测脚本写好&#xff1a; 如图&#xff1a;我这里简单的写…

记录日志中logback和log4j2不能共存的问题

本文章记录设置两个日志时候&#xff0c;控制台直接报错 标黄处就是错误原因&#xff1a;1. SLF4J(W)&#xff1a;类路径包含多个SLF4J提供程序。 SLF4J(W)&#xff1a;找到提供程序[org.apache.logging.slf4j. net]。 SLF4J(W)&#xff1a;找到提供程序[ch.qos.log .classi…

丹摩征文活动 |通过Pycharm复现命名实体识别模型--MECT模型

文章目录 &#x1f34b;1 引言&#x1f34b;2 平台优势&#x1f34b;3 丹摩平台服务器配置教程&#x1f34b;4 实操案例&#xff08; MECT4CNER-main&#xff09;&#x1f34b;4.1 MECT4CNER-main模型&#x1f34b;4.2 环境配置&#x1f34b;4.3 训练模型&#x1f34b;4.4 数据…

电脑浏览器打不开网页怎么办 浏览器无法访问网页解决方法

我们在使用电脑的时候&#xff0c;使用浏览器是经常的&#xff0c;很多用户在点开浏览器时&#xff0c;却遇到浏览器无法访问网页的情况。那么电脑浏览器打不开网页是什么原因呢&#xff1f;今天小编就给大家分享几个常见的原因和具体的解决方法&#xff0c;希望能对大家有所帮…

YOLOv11实战宠物狗分类

本文采用YOLOv11作为核心算法框架&#xff0c;结合PyQt5构建用户界面&#xff0c;使用Python3进行开发。YOLOv11以其高效的特征提取能力&#xff0c;在多个图像分类任务中展现出卓越性能。本研究针对5种宠物狗数据集进行训练和优化&#xff0c;该数据集包含丰富的宠物狗图像样本…

Struts源码阅读——三个常用的辅助类DispatchAction

Struts源码阅读——三个常用的辅助类 紧接前文&#xff0c;我们来阅读org.apache.struts.actions包中三个常用类的源码。 DispatchAction、LookupDispatchAction 和 MappingDispatchAction 是 Struts 1 框架中的三个常用的辅助类&#xff0c;用来简化 Action 类中的请求分发。…

Linux设置Nginx开机启动

操作系统环境&#xff1a;CentOS 7 【需要 root 权限&#xff0c;使用 root 用户进行操作】 原理&#xff1a;利用 systemctl 管理服务 设置 Nginx 开机启动 需要 root 权限&#xff0c;普通用户使用 sudo 进行命令操作 原理&#xff1a;利用 systemctl 管理服务 1、新建…