『 Linux 』信号概念与信号的产生

文章目录

    • 信号概念
    • 前台进程与后台进程
    • 信号的本质
    • 硬件理解
    • 信号的产生


信号概念

请添加图片描述

"信号"一词指用来传达信息或只是的各种形式的提示或标志;

在生活中常见的信号例如红绿灯,交通标志,短信通知等

在操作系统中,"信号"是一种用于异步通知进程发生特定事件的机制;

信号允许操作系统或其他进程向目标进程发送通知以便他们能够相应某些时间或条件;

  • 异步

    异步指在处理任务或操作时发起操作与处理结果的时间节点不一致;

    意味着操作的启动和完成不是在同一时间点发生,这种机制一般用于提高程序和效率的响应性;

    • 任务启动与完成的独立性

      在异步操作中任务的发起和完成是独立的;

      发起操作后程序可以继续执行其他任务而不需要等待操作完成;

      使得程序能够在等待期间进行其他有用的工作而提高效率;

    • 回调机制

      异步操作通常使用回调函数来处理操作完成后的结果;

      回调函数会在操作完成时被调用,处理结果或执行后续操作;

      这种机制允许程序继续运行其他任务直到操作完成时才处理结果;

在默认情况下,操作系统将为每个进程预设对所有信号的接收及处理方式;

默认的信号处理行为是由操作系统定义的,确保在没有消失设置信号处理程序的情况下能够合理响应各种信号;

使得即便目前未产生信号时进程也能知道在信号产生之后该作何处理;

  • 信号的异步处理特性

    当一个信号产生时并不会立即中断进程正在执行的关键代码,而是在适当的时候处理;

    表明在信号的产生到处理的过程中必须存在一个"时间窗口"用于进程保存已经识别到的信号,并在适合时间段对信号进行处理;

    这个机制通常通过信号的阻塞(屏蔽)和信号队列来实现;

一个信号由产生到被处理一般要经过三个步骤:

  • 信号的产生
  • 信号的保存
  • 信号的处理


前台进程与后台进程

请添加图片描述

  • 前台进程

    前台进程是直接与用户进行交互的进程;

    用户可以通过中断或者命令行界面与前台进程进行实时交互;

    • 交互性

      前台进程直接接收用户的输入,并将输出显示给用户;

      如在终端运行文本编辑器,浏览器等;

    • 控制终端

      前台进程与控制终端相关联,当用户在终端输入命令时这些命令会发送给前台进程;

    • 信号响应

      前台进程通常响应特点的信号,如按下Ctrl + c发送的SIGINT信号将终止前台进程;

  • 后台进程

    后台进程是在后台执行的进程,不直接与用户交互;

    这些进程通常执行长时间运行的任务,不需要用户的实时干预;

    • 非交互性

      后台进程不直接接受用户输入也不会将输出显示给用户;

      它们通常将输出重定向到文件或是日志;

    • 脱离终端

      后台进程不与控制终端直接关联,因此不会阻塞终端,允许用户继续在终端中执行其他操作;

    • 启动方式

      后台进程通常可以通过在运行命令后加上&符号启动,如:

      ./myprocess &
      
  • 前后台进程的转换

    将前台进程转换到后台:

    $ ./myprocess 
    I am a crazy Process , PID : 15708
    I am a crazy Process , PID : 15708
    ^Z
    [1]+  Stopped                 ./myprocess
    $ bg
    [1]+ ./myprocess &
    I am a crazy Process , PID : 15708
    $ I am a crazy Process , PID : 15708
    I am a crazy Process , PID : 15708
    • 暂停前台进程

      使用Ctrl + z将前台进程挂起;

    • 将挂起的进程放到后台

      bg命令;

    将后台进程转换到前台:

    $ ./myprocess &
    [1] 15720
    $ I am a crazy Process , PID : 15720
    I am a crazy Process , PID : 15720
    fI am a crazy Process , PID : 15720
    g I am a crazy Process , PID : 15720
    %I am a crazy Process , PID : 15720
    1
    ./myprocess
    I am a crazy Process , PID : 15720
    I am a crazy Process , PID : 15720
    ^C
    
    • 使用fg命令

      $ fg %1
      

      这个命令将后台进程编号为1(非进程PID)的进程调回前台;

Linux中,一次登录中一个终端一般会配上一个bash;

每一个登录只允许一个进程是前台进程,可以允许存在多个后台进程;

当未启动其他前台进程时bash将作为一个前台进程,负责与用户交互;

当用户从键盘中输入数据时将被前台进程获取;


信号的本质

请添加图片描述

使用命令kill -l可以查看当前操作系统中可用的信号;

$ kill -l1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP6) SIGABRT	 7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
11) SIGSEGV	12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
16) SIGSTKFLT	17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
21) SIGTTIN	22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
26) SIGVTALRM	27) SIGPROF	28) SIGWINCH	29) SIGIO	30) SIGPWR
31) SIGSYS	34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
63) SIGRTMAX-1	64) SIGRTMAX	

其中1 - 31号信号被称为 普通信号 ,34 - 64号信号被称为 实时信号 (不考虑实时信号);

信号列表中32号和33号信号不存在,原因为其并非标准的POSIX信号;

信号本质在内核中通过宏定义,通常可在<signal.h>,<asm/signal.h><linux/signal.h>等头文件中找到;

#define SIGHUP    1  /* Hangup (POSIX).  */
#define SIGINT    2  /* Interrupt (ANSI).  */
#define SIGQUIT   3  /* Quit (POSIX).  */
#define SIGILL    4  /* Illegal instruction (ANSI).  */
#define SIGABRT   6  /* Abort (ANSI).  */
#define SIGFPE    8  /* Floating-point exception (ANSI).  */
#define SIGKILL   9  /* Kill, unblockable (POSIX).  */
#define SIGSEGV   11 /* Segmentation violation (ANSI).  */
#define SIGPIPE   13 /* Broken pipe (POSIX).  */
#define SIGALRM   14 /* Alarm clock (POSIX).  */
#define SIGTERM   15 /* Termination (ANSI).  */
// ...

信号的处理方式一般分为三种:

  • 默认动作

    进程收到信号后将执行默认的动作,默认动作属于进程内置功能的一部分;

  • 忽略

    可调用系统调用接口signal()传递SIG_IGN参数来忽略信号(9号信号SIGKILL19号信号SIGSTOP无法被忽略);

    在进行忽略时不需要捕获信号,会直接进行忽略,这意味着捕获和忽略是完全不同的处理方式;

  • 自定义动作

    可调用系统调用接口signal()自定义对应的动作并设置信号的捕捉,使得进程在收到信号时作对应动作(9号信号SIGKILL19号信号SIGSTOP无法被捕捉);

处理方式只能三选一, 不能既…又… ;

本质上在使用Ctrl + C终止一个前台进程是向该前台进程发送了2号信号即SIGINT信号,可通过系统调用接口signal()使用自定义动作进行验证;

  • signal()

    NAMEsignal - ANSI C signal handlingSYNOPSIS#include <signal.h>typedef void (*sighandler_t)(int);sighandler_t signal(int signum, sighandler_t handler);RETURN VALUEsignal()  returns  the  previous  value  of  the signal handler, or SIG_ERR onerror.  In the event of an error, errno is set to indicate the cause.
    

    当接口调用成功时将返回先前信号处理程序的指针,指针的情况为如下:

    • 自定义处理程序

      将返回一个有效的函数指针指向先前设置的处理程序;

    • SIG_IGN

      表示信号先前被忽略;

    • SIG_DFL

      表示信号先前有默认处理程序;

    当调用失败时返回SIG_ERR表示一个错误并且errno被设置以指示错误原因;

    调用参数如下:

    • int signum

      传入一个参数代表需要操作的信号编号;

    • sighandler_t handler

      选项操作,传入一个函数指针,这个函数指针可以是用户自定义的函数指针(自定义操作),也可以是SIG_IGNSIG_DFL;

      当用户选择自定义操作时需要自行构造一个函数用于自定义动作,自定义动作所用函数必须传入一个参数来接收所捕获的信号编号;

在原有的myprocess.cc文件中进行修改,调用signal()系统调用接口设置信号捕获与自定义动作;

#include <signal.h>
#include <sys/types.h>
#include <unistd.h>#include <iostream>
using namespace std;// 自定义动作
void signal_handler(int signum) { cout << "get a signal : " << signum << endl; }int main() {signal(SIGINT, signal_handler);while (1) {cout << "I am a crazy Process , PID : " << getpid() << endl;sleep(1);}return 0;
}

该操作为两步:

  • 设置信号处理程序

    调用signal(SIGINT, signal_handler)设置信号处理,该操作是一个同步操作;

  • 异步信号处理

    当运行程序时用户按下Ctrl + C发送SIGINT信号将立即中断当前的执行并调用signal_handler函数然后恢复执行循环;

这意味着同一个信号的一种操作的捕获只需要设置一次,如本次操作需要设置捕获到信号2的行为为执行自定义动作;

对应结果为:

 ./myprocess 
I am a crazy Process , PID : 15850
I am a crazy Process , PID : 15850
^Cget a signal : 2
I am a crazy Process , PID : 15850
I am a crazy Process , PID : 15850
^Cget a signal : 2
I am a crazy Process , PID : 15850
I am a crazy Process , PID : 15850
^Cget a signal : 2
I am a crazy Process , PID : 15850
I am a crazy Process , PID : 15850
I am a crazy Process , PID : 15850
...

使用Ctrl + C将为前台进程发送信号2SIGINT,进程捕获到信号执行自定义动作打印对应信号编号;

  • 不可被忽略与捕获的信号

    在所有普通信号中9号信号和19号信号不可被捕获与忽略,其中9号信号SIGKILL19号信号SIGSTOP分别作用为:

    • SIGKILL

      强制终止进程,主要作用是立即停止进程的执行并将其从系统重移除;

    • SIGSTOP

      暂停进程;

      SIGSTOP信号会让进程进入停滞状态,直到接收到继续执行的信号,如SIGCONT;

    本质原因为防止不可杀死进程与无法暂停进程的恶意行为,可循环调用系统调用接口signal()进行验证;

    #include <signal.h>
    #include <sys/types.h>
    #include <unistd.h>#include <iostream>
    using namespace std;void signal_handler(int signum) { cout << "get a signal : " << signum << endl; }int main() {for (int i = 1; i <= 31; ++i) {signal(i, signal_handler);}while (1) {cout << "I am a crazy Process , PID : " << getpid() << endl;sleep(1);}return 0;
    }
    

    循环调用将131号信号都捕获并执行自定义动作;

    同时使用shell脚本:

    while :; do for i in $(seq 1 31); do  echo "Sending signal $i to process $TARGET_PID";kill -$i (pid);sleep 1;done; sleep 50;
    done
    

    来观察对应结果;

    其结果为:

    • bash命令行

      $ while :; do for i in $(seq 1 31); do echo "Sending signal $i to process $17342" ;kill -$i 17342; sleep 1; done; sleep 50; done
      Sending signal 1 to process 17342
      Sending signal 2 to process 17342
      Sending signal 3 to process 17342
      Sending signal 4 to process 17342
      Sending signal 5 to process 17342
      Sending signal 6 to process 17342
      Sending signal 7 to process 17342
      Sending signal 8 to process 17342
      Sending signal 9 to process 17342
      Sending signal 10 to process 17342
      -bash: kill: (17342) - No such process
      ^C
      $ while :; do for i in $(seq 10 31); do echo "Sending signal $i to process $17355" ;kill -$i 17355; sleep 1; done; sleep 50; done
      Sending signal 10 to process 17355
      Sending signal 11 to process 17355
      Sending signal 12 to process 17355
      Sending signal 13 to process 17355
      Sending signal 14 to process 17355
      Sending signal 15 to process 17355
      Sending signal 16 to process 17355
      Sending signal 17 to process 17355
      Sending signal 18 to process 17355
      Sending signal 19 to process 17355
      ^C
      $ kill -9 17355
      $ while :; do for i in $(seq 20 31); do echo "Sending signal $i to process $17367" ;kill -$i 17367; sleep 1; done; sleep 50; done
      Sending signal 20 to process 17367
      Sending signal 21 to process 17367
      Sending signal 22 to process 17367
      Sending signal 23 to process 17367
      Sending signal 24 to process 17367
      Sending signal 25 to process 17367
      Sending signal 26 to process 17367
      Sending signal 27 to process 17367
      Sending signal 28 to process 17367
      Sending signal 29 to process 17367
      Sending signal 30 to process 17367
      Sending signal 31 to process 17367
      ^C
      
    • myprocess所在窗口

      $ ./myprocess
      get a signal : 1
      I am a crazy Process , PID : 17342
      get a signal : 2
      I am a crazy Process , PID : 17342
      get a signal : 3
      I am a crazy Process , PID : 17342
      get a signal : 4
      I am a crazy Process , PID : 17342
      get a signal : 5
      I am a crazy Process , PID : 17342
      get a signal : 6
      I am a crazy Process , PID : 17342
      get a signal : 7
      I am a crazy Process , PID : 17342
      get a signal : 8
      I am a crazy Process , PID : 17342
      Killed  # 被9号信号杀死$ ./myprocess 
      I am a crazy Process , PID : 17355
      get a signal : 10
      I am a crazy Process , PID : 17355
      get a signal : 11
      I am a crazy Process , PID : 17355
      get a signal : 12
      I am a crazy Process , PID : 17355
      get a signal : 13
      I am a crazy Process , PID : 17355
      get a signal : 14
      I am a crazy Process , PID : 17355
      get a signal : 15
      I am a crazy Process , PID : 17355
      get a signal : 16
      I am a crazy Process , PID : 17355
      get a signal : 17
      I am a crazy Process , PID : 17355
      get a signal : 18
      I am a crazy Process , PID : 17355[1]+  Stopped                 ./myprocess # 被19号信号暂停$ ./myprocess
      I am a crazy Process , PID : 17367
      get a signal : 20
      I am a crazy Process , PID : 17367
      get a signal : 21
      I am a crazy Process , PID : 17367
      get a signal : 22
      I am a crazy Process , PID : 17367
      get a signal : 23
      I am a crazy Process , PID : 17367
      get a signal : 24
      I am a crazy Process , PID : 17367
      get a signal : 25
      I am a crazy Process , PID : 17367
      get a signal : 26
      I am a crazy Process , PID : 17367
      get a signal : 27
      I am a crazy Process , PID : 17367
      get a signal : 28
      I am a crazy Process , PID : 17367
      get a signal : 29
      I am a crazy Process , PID : 17367
      get a signal : 30
      I am a crazy Process , PID : 17367
      get a signal : 31
      

硬件理解

请添加图片描述

当用户按下键盘Ctrl + C时将默认转化为信号2,即SIGINT信号;

通常涉及到以下步骤:

  • 键盘输入

    键盘中每个按键都将有一个唯一的键码;

    当用户按下Ctrl + C组合键时,键盘硬件将会生成一个键码,键盘控制器将负责将按键的物理动作转化为键码;

  • 键盘硬件中断

    键盘控制器将检测到按键事件并向CPU发送一个硬件中断请求;

    在发送中断请求的同时,键盘控制器还会将键码放置在其缓冲区中;

    • 普通按键

      当用户按下普通按键(字母,数字等)时,操作系统将会将扫描码转化为ASCII码或其他字符编码并放入键盘缓冲区;

      如果按下普通按键时没有按下任何控制键,操作系统将会视其为普通按键进行输入;

    • 控制按键组合

      如果用户按下了一个普通按键同时按下了一个或多个控制按键(Ctrl,Alt,Shift等),操作系统会检查当前的控制按键状态标志并将按键组合视为特殊的控制输入;

      如按下Ctrl + C会被识别为一个特定的控制字符而不是单独的CtrlC;

  • CPU中断处理

    收到键盘中断请求后CPU将会暂停当前执行的任务并通过中断向量表查找对应的中断服务例程;

    中断向量表是一个包含中断服务例程地址的表,通常存储在内存的特定位置;

  • 中断服务例程

    键盘的中断服务例程是由操作系统提供的处理函数,负责从键盘控制器中读取键码并将其转化为ASCII码或其他合适的格式;

    这些键码通常会被放入一个键盘缓冲区一遍操作系统读取和处理;

  • 操作系统处理键盘输入并生成SIGINT信号

    操作系统内核将定期检查键盘缓冲区并处理其中的键码;

    当检测到Ctrl + C组合键时将是识别出这是一个产生SIGINT信号的控制字符并将该信号发送给当前的前台进程组;

  • 信号接收和处理信号

    进程接收到SIGINT信号将根据预先定义的信号处理机制处理信号;


信号的产生

请添加图片描述

信号的产生可以源于多种情况:

  • 用户输入

    • SIGINT

      用户通过键盘按键组合Ctrl + C产生,作用为中断当前前台进程;

    • SIGQUIT

      用户通过键盘按键组合Ctrl + \产生,作用为强制终止进程并生成核心转储文件;

    • SIGTSTP

      用户通过键盘按键组合Ctrl + Z产生,作用为暂停(停止)当前前台进程,将其放入后台;

  • kill -signo pid

    通过kill命令带信号编号及进程PID产生信号;

  • 系统调用接口

    • kill()

      可通过kill()函数调用产生信号;

      NAMEkill - send signal to a processSYNOPSIS#include <sys/types.h>#include <signal.h>int kill(pid_t pid, int sig);Feature Test Macro Requirements for glibc (see feature_test_macros(7)):kill(): _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCERETURN VALUEOn  success (at least one signal was sent), zero is returned.  On error, -1 isreturned, and errno is set appropriately.

      当函数成功调用(至少发送一个信号)返回0,失败则返回-1并设置errno;

      其中参数pid_t pidint sig分别为进程的PID和信号的信号编号;

      可用该接口模拟实现一个kill命令;

      #include <signal.h>
      #include <sys/types.h>
      #include <unistd.h>#include <iostream>
      #include <string>
      using namespace std;// 运行用法为
      /*./mykill signum pid0       1      2一共3个 argc = 3
      */void Usage(string proc) {// 使用手册cout << "usage:\n\t" << proc << " signum pid" << endl << endl;
      }int main(int argc, char* argv[]) {if (argc != 3) {Usage(argv[0]);exit(3);}int signum = stoi(argv[1]);int pid = stoi(argv[2]);kill(pid, signum);return 0;
      }
      
    • raise()

      通过调用raise()接口向调用者发送一个信号;

      NAMEraise - send a signal to the callerSYNOPSIS#include <signal.h>int raise(int sig);DESCRIPTIONThe  raise()  function  sends a signal to the calling process or thread.  In asingle-threaded program it is equivalent tokill(getpid(), sig);RETURN VALUEraise() returns 0 on success, and nonzero for failure.

      函数调用成功时返回0,调用失败时返回!0;

      参数int sig表示需要发送的信号编号;

      验证:

      #include <signal.h>
      #include <sys/types.h>
      #include <unistd.h>#include <iostream>
      using namespace std;void signal_handler(int signum) { cout << "get a signal : " << signum << endl; }int main() {signal(SIGINT, signal_handler);int n = 4;while (n--) {cout << "I am a crazy Process , PID : " << getpid() << endl;sleep(1);}raise(2);return 0;
      }
      

      当进程执行4s后运行raise(2)向自己发送一个信号,并调用signal()设置捕获;

      $ ./myprocess 
      I am a crazy Process , PID : 18003
      I am a crazy Process , PID : 18003
      I am a crazy Process , PID : 18003
      I am a crazy Process , PID : 18003
      get a signal : 2
      

      结果为发送了信号2并被捕获;

      本质上raise()函数是kill(getpid(), sig)的封装;

    • abort()

      NAMEabort - cause abnormal process terminationSYNOPSIS#include <stdlib.h>void abort(void);DESCRIPTIONThe abort() first unblocks the SIGABRT signal, and then raises that signal forthe calling process.  This results in the abnormal termination of the  processunless  the  SIGABRT  signal  is caught and the signal handler does not return(see longjmp(3)).If the abort() function causes  process  termination,  all  open  streams  areclosed and flushed.If  the  SIGABRT  signal  is ignored, or caught by a handler that returns, theabort() function will still terminate the process.  It does this by  restoringthe  default  disposition for SIGABRT and then raising the signal for a secondtime.RETURN VALUEThe abort() function never returns.
      

      通过调用abort()函数向进程发送一个6号信号SIGABRT信号,并强行终止进程;

      #include <signal.h>
      #include <sys/types.h>
      #include <unistd.h>
      #include <cstdlib>
      #include <iostream>
      using namespace std;void signal_handler(int signum) { cout << "get a signal : " << signum << endl; }int main() {signal(SIGABRT, signal_handler);// 6号信号可被捕获与忽略int n = 0;while (++n) {cout << "I am a crazy Process , PID : " << getpid() << endl;sleep(1);if (n % 5 == 0) {abort();}}return 0;
      }
      

      自定义动作中并未涉及进程退出;

      5s过后将调用abort()向进程发送一个SIGABRT信号,并使得signal()捕获到该信号并执行自定义动作;

      $ ./myprocess 
      I am a crazy Process , PID : 18218
      I am a crazy Process , PID : 18218
      I am a crazy Process , PID : 18218
      I am a crazy Process , PID : 18218
      I am a crazy Process , PID : 18218
      get a signal : 6
      Aborted
      $ 
      

      运行结果表示信号被捕获但进程仍被终止;

      实际上abort()的封装过程中封装了_exit();

      /* 可能的abort()实现 (简化版本) */
      void abort(void) {// 发送 SIGABRT 信号raise(SIGABRT);// 如果 SIGABRT 信号被捕获,并且处理函数返回,则直接退出_exit(1); // 使用 _exit 直接退出,避免调用清理函数
      }
      

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

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

相关文章

WebGIS的Web服务概述

WebGIS是互联网技术应用于GIS开发的产物&#xff0c;是现代GIS技术的重要组成部分&#xff0c;其中的Web服务是现代WebGIS的核心技术和重要标志&#xff0c;它集GIS、程序组件和互联网的优点于一身&#xff0c;深刻改变了GIS开发和应用的方式&#xff0c;绕过了本地数据转换和本…

Yum包下载

1. 起因 内网有一台服务器需要升级php版本,维护的同学又不想二进制安装.服务器只有一个光盘的yum仓库 2. 解决方法 解决思路如下: 外网找一台机器配置php8.3.8的仓库外网服务器下载软件集并打包内网服务器上传并解压实现升级 2.1 下载php8.3.8仓库 配置php仓库 rootcent…

Postman导出excel文件

0 写在前面 在我们后端写接口的时候&#xff0c;前端页面还没有出来&#xff0c;我们就得先接口测试&#xff0c;在此记录下如何使用postman测试导出excel接口。 如果不会使用接口传参可以看我这篇博客如何使用Postman 1 方法一 2 方法二 3 写在末尾 虽然在代码中写入文件名…

7月21日,贪心练习

大家好呀&#xff0c;今天带来一些贪心算法的应用解题、 一&#xff0c;柠檬水找零 . - 力扣&#xff08;LeetCode&#xff09; 解析&#xff1a; 本题的贪心体现在对于20美元的处理上&#xff0c;我们总是优先把功能较少的10元作为找零&#xff0c;这样可以让5元用处更大 …

OpenAI发布迷你AI模型GPT-4o mini

本心、输入输出、结果 文章目录 OpenAI发布迷你AI模型GPT-4o mini前言OpenAI发布迷你AI模型GPT-4o mini英伟达联合发布 Mistral-NeMo AI 模型:120 亿参数、上下文窗口 12.8 万个 tokenOpenAI发布迷你AI模型GPT-4o mini 编辑 | 简简单单 Online zuozuo 地址 | https://blog.csd…

vulnhub——Ai-Web1靶机渗透

Ai-Web1靶机渗透 靶机下载&#xff1a; 官网地址&#xff1a;https://www.vulnhub.com/entry/ai-web-1,353/ 攻击机&#xff1a;kali2024 一、信息收集 发下目标主机的IP为&#xff1a;192.168.201.141 用nmap工具扫描一下对方主机和服务 发现他打开了80端口 发现搜不到于是…

提升无线网络安全:用Python脚本发现并修复WiFi安全问题

文章目录 概要环境准备技术细节3.1 实现原理3.2 创建python文件3.3 插入内容3.4 运行python脚本 加固建议4.1 选择强密码4.2 定期更换密码4.3 启用网络加密4.4 关闭WPS4.5 隐藏SSID4.6 限制连接设备 小结 概要 在本文中&#xff0c;我们将介绍并展示如何使用Python脚本来测试本…

Linux系统学习日记——vim操作手册

Vim编辑器是linux下的一个命令行编辑器&#xff0c;类似于我们windows下的记事本。 目录 打开文件 编辑 保存退出 打开文件 打开 hello.c不存在也可以打开&#xff0c;保存时vim会自动创建。 效果 Vim打开时&#xff0c;处于命令模式&#xff0c;即执行命令的模式&#x…

Web 3.0革新:社交金融与边玩边赚开启用户数据主权时代

目录 Web 3.0与社交商业模式 传统社交平台的问题 去中心化社交创新 Mirror&#xff1a;去中心化内容发布平台 Lens Protocol&#xff1a;去中心化社交图谱 Maskbook&#xff1a;隐私保护的社交方式 Web 3.0与与边玩边赚模式 经济模型解析 新商业模式的探索 Axie Infi…

【MySQL-17】存储过程-[变量篇]详解-(系统变量&用户定义变量&局部变量)

前言 大家好吖&#xff0c;欢迎来到 YY 滴MySQL系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的《Lin…

《0基础》学习Python——第二十二讲__网络爬虫/<5>爬取豆瓣电影封面图

一、爬取豆瓣电影的图片封面 1、经过上节课我们所爬取的豆瓣电影的电影名、年份、国家、导演、主演、剧情&#xff0c;那么接下来我们将学习如何去爬取这些电影的图片&#xff0c;并将这些图片存放在文件夹中。 2、过程实现&#xff1a; 2.1、获取网页源码 首先还是和爬取电影名…

FreeU: Free Lunch in Diffusion U-Net

FreeU&#xff1a;扩散 U-Net 模型的免费午餐 论文链接&#xff1a;https://arxiv.org/abs/2309.11497 代码链接&#xff1a;https://github.com/ChenyangSi/FreeU 项目链接&#xff1a;https://chenyangsi.top/FreeU/&#xff08;CVPR2024) Abstract 在本文中&#xff0c;…

python3.10.4——windows环境安装

python下载官网&#xff1a;https://www.python.org/downloads/ 如果安装在C盘&#xff0c;需要右键→选择“以管理员身份运行” 勾选2个按钮&#xff0c;选择自定义安装 全部选择&#xff0c;点击Next 更改安装路径 命令行检查python是否安装成功&#xff1a; 出现版本号说明…

web前端学习笔记Day02

web学习Day02 一、页面布局 盒子模型 盒子将页面的所有标签都包含在了一个矩形区域content(内容区域)->padding(内边距区域)->border(边框区域)->margin(外边距区域) div标签: 一行只能显示一个&#xff08;独占一行&#xff09;width默认为父元素宽度&#xff0c…

21k star 开源项目,让模糊图像秒变高清!

不知道大家有没有遇到这样的需求&#xff1a;电脑里有一些很久之前保存的好看的图片&#xff0c;但是因为分辨率不高&#xff0c;当做壁纸使用会变得模糊。或者是从网上下载的需要使用的图片&#xff0c;找不到更高清的版本导致使用效果不好。之前分享过基于 Real-ESRGAN 算法修…

安全与便捷并行,打造高效易用的用户支付体验

在当今数字时代&#xff0c;快捷、安全的支付方式已经成为用户日常生活中不可或缺的一部分。不论是在线购物、订阅服务&#xff0c;还是线下消费&#xff0c;用户都期望享受流畅且安全的支付体验。作为开发者&#xff0c;选择适合的支付服务不仅关乎用户体验&#xff0c;更直接…

开源模型应用落地-FastAPI-助力模型交互-进阶篇-中间件(四)

一、前言 FastAPI 的高级用法可以为开发人员带来许多好处。它能帮助实现更复杂的路由逻辑和参数处理&#xff0c;使应用程序能够处理各种不同的请求场景&#xff0c;提高应用程序的灵活性和可扩展性。 在数据验证和转换方面&#xff0c;高级用法提供了更精细和准确的控制&#…

【优秀设计案例】基于K-Means聚类算法的球员数据聚类分析设计与实现

背景及意义 随着NBA比赛的日益竞争激烈&#xff0c;球队需要更加深入地了解球员的能力和特征&#xff0c;以制定更有效的战术和球队管理策略。而NBA球员的统计数据包含了大量有价值的信息&#xff0c;通过对这些数据进行聚类分析&#xff0c;可以揭示出球员之间的相似性和差异…

套接字编程一(简单的UDP网络程序)

文章目录 一、 理解源IP地址和目的IP地址二、 认识端口号1. 理解 "端口号" 和 "进程ID"2. 理解源端口号和目的端口号 三、 认识协议1. 认识TCP协议2. 认识UDP协议 四、 网络字节序五、 socket编程接口1. socket 常见API2. sockaddr结构&#xff08;1&#…

Leetcode1688. 比赛中的配对次数

问题描述&#xff1a; 给你一个整数 n &#xff0c;表示比赛中的队伍数。比赛遵循一种独特的赛制&#xff1a; 如果当前队伍数是 偶数 &#xff0c;那么每支队伍都会与另一支队伍配对。总共进行 n / 2 场比赛&#xff0c;且产生 n / 2 支队伍进入下一轮。如果当前队伍数为 奇…