【并发程序设计】13.信号机制

13.信号机制

概念

信号机制是Unix、类Unix以及其他POSIX兼容的操作系统中的一种进程间通讯方式,它允许进程在发生特定事件时接收通知

信号机制是操作系统中的一个重要概念,它提供了一种异步的通知机制,用于在进程之间传递消息。信号可以被看作是一种软中断,它们可以在任何时间被发送给一个进程,以通知该进程发生了某个特定的事件。信号的本质是在软件层次上模拟硬件中断的行为,但它完全由软件控制,因此被称为“软中断”。

信号的处理过程通常涉及以下几个步骤:

  1. 信号的产生:当某个事件发生时,如用户按下Ctrl+C,或者程序访问了非法内存地址,操作系统会产生一个信号。
  2. 信号的传递:产生的信号会被操作系统传递给目标进程。这个过程是异步的,意味着信号可以在任何时间点到达。
  3. 信号的接收:进程通过注册信号处理函数来接收和处理信号。当信号到达时,如果进程已经为该信号注册了处理函数,操作系统会调用该函数。
  4. 信号的处理:在信号处理函数中,进程可以决定如何处理信号。常见的处理方式包括忽略信号、采取默认行为(如终止进程)或执行自定义的操作。
  5. 信号的屏蔽:进程可以选择暂时屏蔽某些信号,这样即使在信号产生时也不会被立即处理。这通常用于避免在某些关键操作中被信号中断。

在Linux系统中,信号机制是通过内核实现的。内核负责管理信号的发送和接收,并通过软中断的方式通知进程。进程可以通过系统调用来设置信号处理函数,从而定义对不同信号的响应方式。

常用信号

信号名代号含义默认操作
SIGHUP1该信号在用户终端关闭时产生,通常是发给和该 终端关联的会话内的所有进程终止
SIGINT2该信号在用户键入INTR字符(Ctrl-C)时产生,内核发送此信号送到当前终端的所有前台进程终止
SIGQUIT3该信号和SIGINT类似,但由QUIT字符(通常是 Ctrl-)来产生终止
SIGILL4该信号在一个进程企图执行一条非法指令时产生终止
SIGSEV5该信号在非法访问内存时产生,如野指针、缓 冲区溢出终止
SIGPIPE13当进程往一个没有读端的管道中写入时产生,代 表“管道断裂”终止
SIGKILL9该信号用来结束进程,并且不能被捕捉和忽略终止
SIGSTOP19该信号用于暂停进程,并且不能被捕捉和忽略暂停进程
SIGTSTP20该信号用于暂停进程,用户可键入SUSP字符( 通常是Ctrl-Z)发出这个信号暂停进程
SIGCONT18该信号让进程进入运行态继续运行
SIGALRM14该信号用于通知进程定时器时间已到终止
SIGUSR1/210/12该信号保留给用户程序使用终止
SIGCHLD17是子进程状态改变发给父进程的。忽略

kill -l 命令查看所有信号

在这里插入图片描述

用到的命令

Kill 命令

  1. 格式kill [参数] [进程号]
  2. 功能:Linux中的kill命令的功能是向指定进程发送信号以终止该进程的运行
  3. 参数
    • -[信号名或代号],例 kill -9 pid 结束进程pid
    • -l(小写L):列出所有可用的信号名称。如果不加信号编号,使用此参数会显示全部信号。
    • -s:指定要发送的信号的名称或编号。这允许用户选择发送不同的信号到进程。
    • -a:当处理当前进程时,不限制命令名和进程号的对应关系。这在批量脚本中尤其有用。
    • -p:指定kill命令只打印相关进程的进程号,而不发送任何信号。
    • -u:指定用户。这个参数用来限定只向特定用户的进程发送信号

killall 命令

  1. 格式killall [参数] [进程名]
  2. 功能结束所有与给定名称匹配的运行中的进程。这可以简化操作,因为用户不需要先查找进程ID(PID),再使用kill命令来终止进程。
  3. 参数
    • -e | --exact:要求进程名与指定名称完全匹配。
    • -I | --ignore-case:在匹配进程名时忽略大小写。
    • -g | --process-group:结束整个进程组而不仅仅是单个进程。
    • -i | --interactive:在结束进程前询问用户确认,实现交互式操作。
    • -l | --list:列出所有已知的信号名称。
    • -q | --quiet:在进程没有结束时不输出任何信息。
    • -s | --signal:发送指定的信号到进程,默认为SIGTERM。
    • -v | --verbose:报告信号是否成功发送到每个匹配的进程。
    • -w | --wait:等待每个被发送信号的进程终止

发送信号的函数

kill 函数

  1. 原型

    #include <signal.h>
    int kill(pid_t pid, int sig)
    
  2. 功能:指定的进程或进程组发送信号

  3. 参数

    • pid:指定要接收信号的进程或进程组
      • pid > 0:信号将被发送到进程ID为pid的进程。
      • pid = 0:信号将被发送到与调用kill()的进程属于同一个进程组的所有进程。
      • pid = -1:信号将被广播发送到系统中所有调用进程有权发送信号的进程,除了进程1(init)。
      • pid < -1:信号将被发送到以-pid为进程组标识的所有进程。
    • int sig:指定要发送的信号的编号。不同的信号编号代表不同的信号,例如SIGTERM代表终止信号,SIGKILL代表强制终止信号。
  4. 返回值

    • 成功,返回0
    • 失败,返回非零数

alarm 函数

  1. 原型

    #include <unistd.h>
    unsigned int alarm(unsigned int seconds);
    
  2. 功能:设置一个定时器,在定时器到期时向调用进程发送SIGALRM信号

  3. 参数seconds:指定定时器的数。如果seconds为0,则取消之前设置的定时器,并返回剩余的时间片。如果seconds非零,则设置一个新的定时器,定时器到期时,将向调用alarm函数的进程发送SIGALRM信号。

  4. 返回值

    • 上一个定时器的剩余时间(以秒为单位)
    • 如果没有设置过定时器,则返回值为0
  5. 注意:如果在定时器到期前再次调用alarm函数设置了新的定时器,那么原来的定时器会被取消,新的定时器将从当前时间开始计时。

pause 函数

  1. 原型

    #include <stdlib.h>
    int pause(void);
    
  2. 功能暂停程序执行,直到接收到一个信号

  3. 参数:无

  4. 返回值

    • 如果成功,则返回-1
    • 如果发生错误,则返回-1并设置errno为相应的错误代码

ualarm 函数

  1. 原型

    #include <unistd.h>
    int ualarm(unsigned int seconds, int interval);
    
  2. 功能:设置一个定时器,在定时器到期时向进程发送SIGALRM信号

  3. 参数

    • seconds:指定定时器的秒数。如果seconds为0,则取消之前设置的定时器。
    • interval:指定间隔时间(以jiffies为单位)。如果interval为0或负数,则表示只执行一次定时器。
  4. 返回值

    • 成功,返回0
    • 失败,返回-1
  5. 注意ualarm函数已经被标记为已废弃(deprecated),因为它的行为在不同的系统和平台上可能不一致。在新的代码中,建议使用setitimer函数来代替ualarm函数,以实现更可靠和可移植的定时器功能。

setitimer函数

  1. 原型

    #include <sys/time.h>
    int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value);
    
  2. 功能:设置一个定时器,该定时器在到期时会向调用进程发送一个SIGALRM信号

  3. 参数

    • which:指定定时器类型,可以是以下三种之一:
      • ITIMER_REAL:基于真实的时间间隔(Real timer),即按照日历时间来计算。
      • ITIMER_VIRTUAL:基于虚拟的时间间隔(Virtual timer),即按照进程在用户态消耗的CPU时间来计算。
      • ITIMER_PROF:基于进程时间(Profiling timer),即按照进程在用户态和内核态消耗的CPU时间来计算。
    • new_value:指向struct itimerval结构的指针,该结构定义了定时器的间隔时间和总时间。如果这个指针为NULL,则定时器被取消。
    • old_value:指向struct itimerval结构的指针,用于存储之前的定时器设置。如果这个指针为NULL,则不保存之前的定时器设置。
  4. 结构体

    • struct itimerval {
          struct timeval it_interval; /* 定时器触发的时间间隔 */
          struct timeval it_value;    /* 第一次触发定时器的时间 */
      };
      
    • struct timeval {
          time_t tv_sec; // 秒数
          suseconds_t tv_usec; // 微秒数
      };
      
  5. 返回值

    • 成功,返回0
    • 失败,返回-1
  6. :可以通过调用gettimeofday(&t_start, NULL)来获取当前时间,并将其存储在timeval结构体变量t_start中。

捕获信号

捕获流程

在这里插入图片描述

signal函数

  1. 原型

    #include <signal.h>
    typedef void (*sighandler_t)(int);` 
    sighandler_t signal(int signum, sighandler_t handler);
    
  2. 功能:设置指定信号的处理函数

  3. 参数

    • signum:指定要处理的信号的编号。
    • handler:指向信号处理函数的指针。如果设置为SIG_IGN,则忽略该信号;如果设置为SIG_DFL,则采用系统默认处理方式。
  4. 返回值:返回先前为指定信号设置的处理函数指针,或者如果之前没有设置处理函数,则返回SIG_DFL

  5. 注:typedef void (*sighandler_t)(int);

    • (*sighandler_t) 表示定义了一个名为 sighandler_t 的函数指针类型。这个函数指针类型指向的函数返回值为 void,即没有返回值,同时接受一个整型参数 int,通常用于传递信号编号
  6. 示例

    捕捉SIGINT信号,打印"I cath the SIGINT \n"

    程序执行后按ctrl +c 打印“I cath the SIGINT \n”后信号功能复原,再按一次ctrl +c,程序退出

    #include <signal.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <string.h>
    #include <linux/posix_types.h>
    
    typedef void (*sighandler_t)(int);
    
    sighandler_t oldact;
    
    void handle(int sig){
        printf("I cath the SIGINT \n");
        signal(SIGINT,oldact);//回复信号原来的功能
    }
    
    int main(){
    
        oldact = signal(SIGINT,handle);//设定信号执行的函数,并将原来的处理信号的函数指针赋值给oldact
        while(1){
            sleep(1);
        }
    
    

sigaction函数

  1. 原型

    #include <signal.h>
    int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
    
  2. 功能

    • sigaction 函数用于设置指定信号 signum 的信号处理函数、信号集和标志。
    • 它允许更细致的控制信号的行为,比 signal 函数提供了更多的选项。
  3. 参数

    • signum:要处理的信号编号。
    • act:指向 sigaction 结构体的指针,该结构体定义了新的信号处理行为。
    • oldact:指向 sigaction 结构体的指针,用于存储原来的信号处理行为。如果不需要保存旧的行为,可以设置为 NULL
  4. 返回值

    • 成功时返回 0
    • 失败时返回 -1
  5. sigaction 结构体

    struct sigaction {
        void (*sa_handler)(int);      // 信号处理函数
        void (*sa_sigaction)(int, siginfo_t *, void *); // 带有额外信息的信号处理函数(POSIX标准)
        sigset_t sa_mask;             // 信号集,指定在处理信号时阻塞哪些信号
        int sa_flags;                 // 影响信号处理行为的标志
    };
    
    • sa_flags 标志
      • SA_NOCLDSTOP:如果子进程被终止,父进程不会成为停止状态。
      • SA_ONSTACK:使用用户栈中的额外空间执行信号处理函数。
      • SA_RESTART:在信号处理完成后,重启被中断的系统调用。
      • SA_RESETHAND:在信号处理结束后,将信号处理函数重置为默认行为。
      • SA_SIGINFO:使用 sa_sigaction 成员而不是 sa_handler 作为信号处理函数,以提供额外的信号信息。
  6. 注意

    • 不同的操作系统可能对信号的支持不同,因此在使用前应检查操作系统的文档。
    • 在多线程环境中,信号处理可能会被任何线程接收,因此信号处理函数应设计为异步安全的。
    • 当一个信号被捕获时,它的默认行为会被禁止,除非在 sa_handlersa_sigaction 中明确指定。

sigemptyset函数

  1. 原型

    #include <signal.h>
    int sigemptyset(sigset_t *set);
    
  2. 功能:初始化或清空信号集

  3. 参数

    • set:指向要清空的信号集的指针。
  4. 返回值

    • 成功时返回0
    • 失败时返回-1

示例

使用信号回收子进程

  • 信号 17)SIGCHLD 是子进程状态改变发给父进程的。

  • SIGCHLD的产生条件

    1. 子进程终止时

    2. 子进程接收到SIGSTOP信号停止时

    3. 子进程处在停止态,接受到SIGCONT后唤醒时

#include <stdio.h>
#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>

// 信号处理函数
void handle(int sig){
    wait(NULL); // 等待子进程结束
    printf("Get sig =%d\n",sig); // 输出接收到的信号编号
}

int main()
{
    pid_t pid; // 用于存储fork()函数的返回值
    struct sigaction myact; // 用于存储信号处理结构体
    myact.sa_handler = handle; // 设置信号处理函数为handle
    myact.sa_flags = 0; // 设置信号处理标志为0

    sigemptyset(&myact.sa_mask); // 清空信号集

    pid = fork(); // 创建子进程

    // 父进程部分
    if(pid>0)
    {
        //wait(NULL);
        sigaction(SIGCHLD,&myact,NULL); // 设置SIGCHLD信号的处理函数为handle
        while(1)
        {
            printf("this is father process\n"); // 输出信息
            sleep(1); // 休眠1秒
        }
    }

    // 子进程部分
    else if(pid==0)
    {
        sleep(5); // 休眠5秒
        exit(0); // 退出子进程
    }
}

信号阻塞和信号集

有时候不希望在接到信号时就立即停止当前执行,去处理信号,同时也不希望忽略该信号,而是延时一段时间去调用信号处理函数。这种情况可以通过阻塞信号实现。

概念:信号的”阻塞“是一个开关动作,指的是阻止信号被处理,但不是阻止信号产生。

信号的状态:

  • 信号递达(Delivery ):实际信号执行的处理过程(3种状态:忽略,执行默认动作,捕获)
  • 信号未决(Pending):从产生到递达之间的状态

信号集

信号集是一组用于表示信号的集合,它包含了一组信号的状态,通常用来表示这些信号是否已经发生或被处理

信号集操作函数

  1. sigset_t set; 自定义信号集。 是一个32bit 64bit 128bit的数组。
  2. sigemptyset(sigset_t *set); 清空信号集
  3. sigfillset(sigset_t *set); 全部置1
  4. sigaddset(sigset_t *set, int signum); 将第signum个信号添加到集合中
  5. sigdelset(sigset_t *set, int signum); 将第signum个信号从集合中移除
  6. sigismember(const sigset_t *set,int signum); 判断一个信号是否在集合中。

信号屏蔽函数

sigprocmask函数
  1. 原型

    #include <signal.h>
    int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
    
  2. 功能:设定对信号集内的信号的处理方式(阻塞或不阻塞)

  3. 参数

    • how:指定函数的行为,可以是以下值之一:

      • SIG_BLOCK:将参数set中的信号加入到进程的信号屏蔽字中。

      • SIG_UNBLOCK:从进程的信号屏蔽字中移除参数set中的信号。

      • SIG_SETMASK:将参数set设置为进程的信号屏蔽字。

      • SIG_MASK:清空信号集,然后加入原来的信号屏蔽字。

      • SIG_BLOCKSET:类似于SIG_BLOCK,但不会改变原来的信号屏蔽字。

      • SIG_UNBLOCKSET:类似于SIG_UNBLOCK,但不会改变原来的信号屏蔽字。

    • set:指向sigset_t类型的指针,包含了要添加到信号屏蔽字中的信号集合。

    • oldset:指向sigset_t类型的指针,用于存放调用前的信号屏蔽字。

  4. 返回值

    • 成功时返回0,
    • 失败时返回-1,并设置errno为错误码。

示例

SIGINT信号的处理和屏蔽

在刚开始运行时的5秒内按下ctrl+c终端没有反应,五秒结束后信号屏蔽解除,终端打印"I get sig=%d\n"

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

void handle(int sig)  // 定义一个信号处理函数,参数为接收到的信号值
{
    printf("I get sig=%d\n", sig);  // 打印接收到的信号值
}

int main()  // 主函数
{
    struct sigaction act;  // 定义一个sigaction结构体变量act
    act.sa_handler = handle;  // 设置信号处理函数为handle
    sigemptyset(&act.sa_mask);  // 初始化清空信号集
    act.sa_flags = 0;  // 设置标志位为0
    sigaction(SIGINT, &act, NULL);  // 将SIGINT信号的处理方式设置为act

    sigset_t set;  // 定义一个信号集变量set
    sigemptyset(&set);  // 初始化清空信号集
    sigaddset(&set, SIGINT);  // 将SIGINT信号添加到信号集中

    sigprocmask(SIG_BLOCK, &set, NULL);  // 阻塞信号集set中的信号(即禁止接收SIGINT信号)
    sleep(5);  // 暂停执行5秒
    sigprocmask(SIG_UNBLOCK, &set, NULL);  // 解除对信号集中的信号的阻塞(即允许接收SIGINT信号)

    while (1) 
    {
        sleep(1);  
    }
}

信号阻塞函数

pause函数
  1. 原型

    #include <unistd.h>
    int pause(void);
    
  2. 功能pause函数使当前进程进入睡眠状态,直到收到一个信号为止。在睡眠期间,进程不会占用CPU资源。

  3. 返回值

    • 如果成功,则返回-1,并将errno设置为EINTR(表示被中断)。
    • 如果失败,则返回-1,并将errno设置为错误码。
sigsuspend函数
  1. 原型

    #include <signal.h>
    int sigsuspend(const sigset_t *mask);
    
  2. 功能

    • sigsuspend函数使当前进程进入睡眠状态,直到收到一个信号为止。在睡眠期间,进程不会占用CPU资源。
    • pause函数不同,sigsuspend函数可以指定要阻塞的信号集,即在等待信号时,哪些信号应该被阻塞。
  3. 参数

    • mask:指向sigset_t类型的指针,表示要阻塞的信号集。如果为NULL,则不阻塞任何信号
  4. 返回值

    • 如果成功,则返回-1,并将errno设置为EINTR(表示被中断)
    • 如果失败,则返回-1,并将errno设置为错误码

示例

展示两个方法阻塞信号

  • 法一:通过sigprocmask和pause实现
  • 法二:通过sigsuspend实现
#include <signal.h>  // 引入信号处理相关的头文件
#include <stdio.h>   // 引入标准输入输出相关的头文件
#include <stdlib.h>  // 引入标准库函数相关的头文件
#include <unistd.h>  // 引入Unix系统调用相关的头文件

void handle(int sig)  // 信号处理函数
{
    printf("I get sig=%d\n", sig);  // 打印接收到的信号值
}

void mytask()  // 任务函数
{
    printf("My task start\n");  // 打印任务开始信息
    sleep(3);  // 暂停3秒
    printf("My task end\n");  // 打印任务结束信息
}

int main()  // 主函数
{
    struct sigaction act;  // 定义一个sigaction结构体变量act
    act.sa_handler = handle;  // 设置信号处理函数为handle
    act.sa_flags = 0;  // 设置标志位为0
    sigemptyset(&act.sa_mask);  // 初始化清空信号集
    sigaction(SIGINT, &act, NULL);  // 将SIGINT信号的处理方式设置为act
    sigaction(SIGHUP, &act, NULL);  // 将SIGHUP信号的处理方式设置为act

    sigset_t set, set2;  // 定义两个信号集变量set和set2
    sigemptyset(&set2);  // 初始化清空set2信号集
    sigaddset(&set, SIGHUP);  // 将SIGHUP信号添加到信号集set中
    sigaddset(&set, SIGINT);  // 将SIGINT信号添加到信号集set中

    pause();  // 暂停执行,等待信号的到来

    while (1)  // 无限循环
    {
        sigprocmask(SIG_BLOCK, &set, NULL);  // 阻塞信号集中的信号(即禁止接收SIGHUP和SIGINT信号)
        mytask();  // 执行自定义的任务函数
        /*法一*/
        //sigprocmask(SIG_UNBLOCK,&set,NULL);  // 解除对信号集中的信号的阻塞(即允许接收SIGHUP和SIGINT信号)
        //pause();//暂停执行,等待信号的到来
        /*法二*/
        sigsuspend(&set2);  // 挂起进程,直到收到信号为止
    }

    printf("After pause\n");  // 打印"After pause"信息

    while (1)  // 无限循环
    {
        sleep(1);  // 每次循环暂停执行1秒
    }
}

具体分析:

  • sigprocmask:这个函数用于修改进程的信号屏蔽字,即它可以阻止某些信号的传递。当设置了信号屏蔽字后,指定的信号将不会传递给进程,直到取消屏蔽。这种方法的缺点是,如果在取消屏蔽和调用pause之间有信号发生,那么这个信号可能会丢失。
  • pause:这个函数会使进程进入睡眠状态,直到收到一个信号。如果在使用sigprocmask解除信号屏蔽之后调用pause,在这两个调用之间的时间窗口内发生的信号可能会导致pause永远挂起,因为pause只有在接收到信号后才会返回。
  • sigsuspend:这个函数结合了sigprocmaskpause的功能,它在解除信号屏蔽的同时使进程进入睡眠状态。这是一个原子操作,意味着它保证了在信号解除屏蔽和等待信号之间不会有时间窗口,从而避免了信号丢失的问题。因此,如果需要等待某个信号,建议使用sigsuspend而不是单独使用sigprocmaskpause

总的来说,sigprocmask主要用于改变信号屏蔽字,pause用于等待任何信号的到来,而sigsuspend则是在等待特定信号时使用的更为安全的方法,因为它可以保证在等待期间不会错过任何信号

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

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

相关文章

每日一题——Python实现PAT甲级1042 Shuffling Machine(举一反三+思想解读+逐步优化)

一个认为一切根源都是“自己不够强”的INTJ 个人主页&#xff1a;用哲学编程-CSDN博客专栏&#xff1a;每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 我的写法 功能分析 时间复杂度 空间复杂度 总结 代码点评 我要更强 优化方向 …

数据库开发-Mysql03

目录 1. 多表查询 1.1 概述 1.1.1 数据准备 1.1.2 介绍 1.1.3 分类 1.2 内连接 1.3 外连接 1.4 子查询 1.4.1 介绍 1.4.2 标量子查询 1.4.3 列子查询 1.4.4 行子查询 1.4.5 表子查询 1.5 案例 2. 事务 2.1 介绍 2.2 操作 2.3 四大特性 3. 索引 3.1 介绍 3…

光伏企业供应链采购数字化转型升级路径

随着中国光伏行业引领全球&#xff0c;光伏行业竞争激烈。在供应链方面的处理能力也需要有更好的提升。本身光伏企业采购体系依赖传统采购方式&#xff0c;除了需要采购人员耗费大量的时间做供应商的背景调查之外&#xff0c;大量环节却依靠人工线下的方式完成&#xff0c;比如…

微服务 feign-gateway

早期微服务跨集群调用 使用的是Eureka 和RestTemplate&#xff0c;这种写法虽然可以解决服务之间的调用问题 ,但是随着服务的增多&#xff0c;实例变动&#xff0c;早期的写法相当于把请求方式&#xff0c;请求地址&#xff0c;参数写死了&#xff0c;耦合度太高&#xff0c;参…

OpenAI助手API接入-问答对自动生成

支持GPT-3.5-Turbo, GPT-4o, GPT-4-Turbo import json import openai from pathlib import Path import os client openai.OpenAI(base_urlbase_url, api_keyapi_key) file client.files.create( fileopen("H3.pdf", "rb"), purposeassistants ) …

Matplotlib | 绘制柱状图

简介 安装 Matplotlib 开始绘制 简单柱状图 改变颜色 改变纹理 改变边框样式 改变透明度 改变柱子宽度 改变图表标题 ​编辑 并列柱状图 横向柱状图 堆叠柱状图 更多函数 简介 柱状图&#xff08;Bar chart&#xff09;&#xff0c;是一种以长方形的长度为变量的…

重庆人文科技学院建立“软件安全产学研基地”,推动西南地区软件安全发展

5月29日&#xff0c;重庆人文科技学院与开源网安签订了《产学研校企合作协议》&#xff0c;并举行了“重庆人文科技学院产学研基地”授牌仪式&#xff0c;此次合作不仅深化了双方在软件安全领域的产学研紧密联结&#xff0c;更是对川渝乃至西南地区软件供应链安全发展起到重要的…

缓冲区溢出攻击

缓冲区溢出攻击 缓冲区溢出概述基础概念缓冲区溢出根源缓冲区溢出危害性&普遍性 缓冲区溢出攻击原理内存分配模式缓冲区溢出攻击缓冲区溢出攻击原理缓冲区溢出攻击分类堆栈溢出堆栈相关知识攻击原理 堆溢出攻击堆简介堆溢出DWORD SHOOT BSS段溢出 缓冲区溢出攻击防御措施防…

npm install pubsub-js报错的解决汇总

我在练习谷粒商城P83时&#xff0c;选择分类时触发向后端请求选择分类catId绑定的品牌数据&#xff0c;发现前端控制台报错&#xff1a; "PubSub is not definded",找不到pubsub。 因为缺少pubsub包&#xff0c;所以开始安装此包。 于是在网上一顿搜索猛如虎&…

使用Python库Matplotlib绘制常用图表类型

使用Python库Matplotlib绘图 一、Matplotlib绘图参数设置1.1 设置分辨率和画布大小1.2 保存图片并设置边缘留白为紧凑型1.3 设置坐标轴标签1.4 画直线设置线宽和颜色1.5 画子图1.5.1 通过figure的add_subplot()画子图1.5.2 通过plt的subplots画子图 二、使用Matplotlib中scatte…

Geek Uninstaller丨轻盈免费无需安装,Win超强卸载工具

以前卸载软件用习惯了uninstall tool&#xff0c;今天试了一下geek&#xff0c;对比一下还是geek卸载软件更轻盈一点&#xff0c;没有太多冗杂的步骤。 Geek Uninstaller 是一款轻量级的软件卸载工具&#xff0c;它可以帮助用户彻底删除电脑上的软件&#xff0c;包括那些顽固的…

【因果推断python】8_线性回归模型2

目录 回归理论 非随机数据的回归 回归理论 我不打算深入研究线性回归是如何构建和估计的。然而&#xff0c;一点点理论将有助于解释它在因果推断中的力量。首先&#xff0c;回归解决了理论上的最佳线性预测问题。令 是一个参数向量&#xff1a; 线性回归找到最小化均方误差 (…

JavaScript倍速播放视频

F12打开开发者工具&#xff0c;打开控制台&#xff0c;输入这行代码&#xff0c;视频即可加速播放&#xff0c; 可以调整倍速&#xff08;2&#xff0c;4&#xff0c;8&#xff0c;16&#xff09; document. getElementsByTagName("video")[0]. playbackRate16

单片机建立自己的库文件(1)

文章目录 前言一、代码模块化是什么&#xff1f;二、使用步骤1.以LCD1602作为例子2.将LCD1602 相关的代码抽取到另外一个文件中 三、调用LCD1602.h1.新建一个工程项目&#xff0c;将LCD1602.h添加到工程中2.在主函数上加入 #include <LCD1602.h> 总结 前言 提示&#xf…

MACOS安装 vue 抱错解决方法npm ERR! code EACCESnpm ERR! syscall mkdirnpm ERR!

问题 在使用脚手架 vue-cli 创建 vue 工程的时候存在权限不足的情况下&#xff0c;报错&#xff1b; npm error code EACCES npm error syscall open npm error path /Users/ npm ERR! code EACCESnpm ERR! syscall mkdirnpm ERR! 解决方案&#xff1a; sudo npm cache cl…

Go跨平台编译

1.编译windows平台运行程序 # windows env GOOSwindows GOARCHamd64 go build main.go2.编译linux平台运行程序 # linux env GOOSlinux GOARCHamd64 go build main.go 3.编译macos平台运行程序 # macos env GOOSdarwin GOARCHamd64 go build main.go 编译结果:

VQAScore开启文本到视觉生成评估新篇章

随着生成式人工智能技术的飞速发展&#xff0c;如何全面评估生成内容的质量和与输入提示的一致性成为了一个挑战。在图像-文本对齐领域&#xff0c;传统的评估方法如CLIPScore存在局限性&#xff0c;尤其是在处理涉及多个对象、属性和关系的复杂提示时。它们通常基于简单的词袋…

Linux域名解析不了/网络不可达/虚拟机连接不了的问题

记录域名解析不了/网络不可达/虚拟机连接不了的问题问题 目录 文章目录 记录域名解析不了/网络不可达/虚拟机连接不了的问题问题1.首先确定已经连接上路由器(我的就是在这嗝屁了....)1.1 查看路由表1.2查看当前的网络连接状态&#xff0c;包括网关1.3查看网络接口的状态&…

机器学习笔记 - PyTorch 分布式训练概览

一、简述 对于大规模的数据集,只能进行分布式训练,分布式训练会尽可能的利用我们的算力,使模型训练更加高效。PyTorch提供了Data Parallel包,它可以实现单机、多GPU并行。 PyTorch 数据并行模块的内部工作原理 上面的图像说明了PyTorch 如何在单个系统中利用多个 G…

jmeter多用户登录并退出教程

有时候为了模拟更真实的场景&#xff0c;在项目中需要多用户登录并退出操作&#xff0c;大致参考如下 多用户登录前面已经实现&#xff1a;参考博文 多用户登录并退出jmx文件&#xff1a;百度网盘 提取码&#xff1a;0000 一、多用户退出操作 添加一个setUp线程组&#xff0…