【IPC通信--信号】

信号处理函数

信号发送函数
kill(), sigqueue(), raise(), alarm(), setitimer(), pause() abort()
信号安装函数
signal(), sigaction()
信号集操作函数
sigemptyset(), sigfillset(), sigaddset(), sigdelset(), sigismember()

 

信号发送函数—kill()

#include <sys/types.h> 
#include <signal.h> 
int kill(pid_t pid,int signo) 
功能
向进程或进程组发送一个信号 ( 成功返回 0 ; 否则,返回 -1
参数说明
pid :接收信号的进程(组)的进程号
pid>0 :发送给进程号为 pid 的进程
pid=0 :发送给当前进程所属进程组里的所有进程
pid=-1 :发送给除 1 号进程和自身以外的所有进程
pid<-1 :发送给属于进程组 -pid 的所有进程
signo :发送的信号
Signo = 0 :不发送信号 , 可用于检查目标进程是否存在,以及当前进程是否具有向目标 进程 发送信号的权限( root 权限的进程可以向任何进程发送信号,非 root 权限的进程只能向属于同一个 session 或者同一个用户的进程发送信号)。

 

#include <sys/wait.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
int main( void ) {
    pid_t childpid;
    int status;
    int retval;
    childpid = fork();
    if ( -1 == childpid ){
       perror( "fork()" );
       exit( EXIT_FAILURE );
    }
    else if ( 0 == childpid ){
       puts( "In child process" );
       sleep( 100 );//让子进程睡眠,看看父进程的行为
       exit(EXIT_SUCCESS);
    }
    else{
         if ( 0 == (waitpid( childpid, &status, WNOHANG ))){
             retval = kill( childpid,SIGKILL ); 
             if ( retval ){
                 puts( "kill failed." );
                 perror( "kill" );
                 waitpid( childpid, &status, 0 );
             }
             else{
                 printf( "%d killed\n", childpid );
             }
         }
     }
     exit(EXIT_SUCCESS);
 }

 信号发送函数—sigqueue()

#include <sys/types.h> 
#include <signal.h> 
int sigqueue(pid_t
pid , int signo , const union sigval sigval_t )
调用成功返回 0 ;否则,返回 -1
功能
主要针对 实时信号 ,支持带有参数信号,与函数 sigaction() 配合使用
参数说明
pid :接收信号的进程 ID
signo :待发送信号
sigval_t :信号传递的参数( 4 字节)
说明
调用 sigqueue() 时, sigval_t 被拷贝到信号处理函数
sigqueue() 发送 非实时信号
sigval_t 包含的信息仍然能够传递给信号处理函数

仍然不支持排队,所有相同信号都被合并为一个信号

sigqueue()向信号传递附加消息的流程

sigqueue() 的第三个参数是 sigval 联合数据结构
调用 sigqueue() 时,该数据结构中的数据将被拷贝到信号处理函数 sigaction() 的第二个参数
这样,就可在发送信号的同时让信号传递一些附加信息

 

Kill()sigqueue()区别

sigqueue() kill() 传递更多的附加信息
sigqueue() 只能向一个进程 发送信号

信号发送函数—raise()

#include <signal.h> 
int raise(int signo) 
功能
向自身发送信号 
参数说明
signo :发送的信号
signo=0 :不发送信号
返回值
成功时,返回 0
错误时,返回 -1
说明
raise() 可以通过 kill( ) 实现, raise(signo) 等价于
kill(getpid( ), signo);

 

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

int main(void)
{
        printf("kill myself!\n");
        raise(SIGKILL);
        printf("can you see this?\n");
        return 0;
}

信号发送函数—alarm()

#include <unistd.h> 
unsigned int   alarm(unsigned int seconds) 
功能
设置定时器,当计时时间到达时,向进程发出 SIGALRM 信号
参数说明
seconds :等待秒数
seconds 0 时,取消先前设置的闹钟,返回闹钟剩余时间
若之前未设闹钟,则返回 0
说明
alarm() 只发送一次信号
若需重复设定定时器,则要多次调用 alarm() 函数
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <signal.h>
void handler() {
	printf("hellon\n");
}
main()
{
	int i;
	signal(SIGALRM,handler);
	alarm(5);
	for(i=1;i<7;i++){
		printf("sleep %d \n",i);
		sleep(1);
	}
}

信号发送函数—setitimer()

函数原型
int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue);
参数说明
which :逻辑定时器类型
ITIMER_REAL :按 实际时间 计时,计时到达时向进程发送 SIGALRM 信号。
ITIMER_VIRTUAL :计算进程在用户态执行的时间,计时到达将发送 SIGVTALRM 信号给进程。
ITIMER_PROF :计算进程在用户态和核心态的总时间。计时到达将发送 SIGPROF 信号给进程。
ITIMER_VIRTUAL 是一对,该定时器经常用来统计进程在用户态和核心态花费的时间
value :指明定时器的时间
ovalue :如果不为空,则保存上次调用设定的值
功能
指定一段时间后,执行某个 function;

每间格一段时间就执行某个function

返回值
成功时,返回 0
错误时,返回 -1
struct itimerval 结构 定义

struct itimerval {

    struct   timeval   it_interval;     /*定时器周期*/

    struct   timeval   it_value;    /*定时器剩的时间,为0时发信号*/

};

struct timeval 结构定义

struct timeval {

    long  tv_sec;   /*秒*/

    long  tv_usec; /*微秒,1=1000000微秒*/

};

it_value0是不会触发信号的,所以要能触发信号,it_value得大于0;如果it_interval为零,只会延时,不会定时(也就是说只会触发一次信号)

#include <stdio.h>
#include <signal.h>
#include <sys/time.h>

void signalHandler(int signo)
{
    switch (signo){
        case SIGALRM:
            printf("Caught the SIGALRM signal!\n");
            break;
   }
}

int main(int argc, char *argv[])
{
    signal(SIGALRM, signalHandler);
    struct itimerval new_value, old_value;
    new_value.it_value.tv_sec = 1;
    new_value.it_value.tv_usec = 0;
    new_value.it_interval.tv_sec = 2;
    new_value.it_interval.tv_usec = 0;
    setitimer(ITIMER_REAL, &new_value, &old_value); 
    for(;;); 
    return 0;
}

信号发送函数—pause()

功能
使当前进程暂停,进入睡眠状态,直到被信号所中断,即将进程挂起等待信号到来。
函数原型
int pause(void);  
返回值
-1
举例
使用 alarm( ) pause( ) 实现 sleep( ) 功能

信号的安装(设置信号关联动作)

如果进程要处理某一信号,那么就要在进程中安装该信号。安装信号主要用来确定信号值及进程针对该信号值的动作之间的映射关系,即进程将要 处理哪个信号 ;该信号被传递给进程时,将 执行何种操作
linux 主要有两个函数实现信号的安装: signal() sigaction() 。其中 signal() 在非可靠信号系统调用的基础上实现 , 是库函数。它只有 两个参数 ,不支持信号传递信息,主要是用于前 32 种非实时信号的安装;而 sigaction() 是较新的函数(由两个系统调用实现: sys_signal 以及 sys_rt_sigaction ), 有三个参数 ,支持信号传递信息,主要用来与 sigqueue() 系统调用配合使用,当然, sigaction() 同样支持非实时信号的安装。 sigaction() 优于 signal() 主要体现在 支持信号带有参数。

信号安装函数—signal()

原型定义
void (*signal(int signum, void (*handler)(int))) (int);
参数说明
signum :需要安装的信号
handler :与安装信号相关的处理函数,可以是 SIG_IGN SIG_DFL
SIG_IGN :忽略该信号
SIG_DFL :执行默认操作函数
返回值
成功时,返回新安装信号处理函数 handler 的值
失败时,返回 SIG_ERR
底层系统调用
sys_signal(int sig,  __sighandler_t handler)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void sig_usr(int sig);
int main(int argc, char* argv[])
{
        int i=0;
        if(signal(SIGUSR1, sig_usr) == SIG_ERR)
	printf("Can't catch SIGUSR1\n");
       if(signal(SIGUSR2, sig_usr) == SIG_ERR)
                printf(“Can‘t catch SIGUSR2\n”);   
        while(1) {
                printf("%2d\n", i);
                pause();
                i++;
        }
        return 0;
}
void sig_usr(int sig)
{
        if(sig == SIGUSR1)
                printf("Received SIGUSR1\n");
        else if(sig == SIGUSR2)
                printf("Received SIGUSR2\n");
        else
                printf("Undeclared signal %d \n",sig);
}

执行:

Gcc signal.c –o signal
./signal&( 以后台程序运行,并显示 pid )
Kill  –SIGUSR1 pid

信号安装函数—sigaction()

原型定义

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

sigaction函数用于设定进程接收到特定信号后的行为。

第一个参数为信号的值 ,可以为除 SIGKILL SIGSTOP 外的任何一个特定有效的信号(为这两个信号定义自己的处理函数,将导致信号安装错误)。
第二个 参数是指向结构 sigaction 的一个实例的指针,在结构 sigaction 的实例中, 指定了对特定信号的处理 ,如果为空,进程会以缺省方式对信号处理;
第三个参数 oldact 指向的对象 用来保存原来对相应信号的处理 ,可指定 oldact NULL 。如果把第二、第三个参数都设为 NULL ,那么该函数可用于检查信号的有效性。
第二个参数最为重要,其中包含了 对指定信号的处理 信号所传递的信息 信号处理函数执行过程中应屏蔽掉哪些函数 等等。
底层系统调用
sys_sigaction ( int sig, const struct old_sigaction __user *act, struct old_sigaction __user * oact )

        •sigaction结构定义如下:

struct sigaction {
    union{
            __sighandler_t _sa_handler;
            void (*_sa_sigaction)(int, struct siginfo *, void *);
         }_u
         sigset_t sa_mask;
         unsigned long sa_flags;
         void (*sa_restorer)(void);
}
sa_restorer ,已过时, POSIX 不支持它,不应再被使用
联合 数据结构中的两个元素 _ sa_handler 以及 *_ sa_sigaction 指定信号 关联函数 即用户指定的信号处理函数 。除了可以是用户自定义的处理函数外,还可以为 SIG_DFL( 采用缺省的处理方式 ) ,也可以为 SIG_IGN (忽略信号)。
_ sa_handler 指定的处理函数只有一个参数,即信号值,所以信号不能传递除信号值之外的任何信息;
_ sa_sigaction 指定的信号处理函数带有三个参数,是为实时信号而设的(当然同样支持非实时信号),它指定一个 3 参数信号处理函数。 第一个参数为信号值 第三个参数没有使用 posix 没有规范使用该参数的标准), 第二个参数是指向 siginfo_t 结构的指针,结构中包含 信号携带的数据值 ,参数所指向的结构如下:

 siginfo_t {
                  int      si_signo;  /* 信号值,对所有信号有意义*/
                  int      si_errno;  /* errno值,对所有信号有意义*/
                  int      si_code;   /* 信号产生的原因,对所有信号有意义*/
                  pid_t    si_pid;    /* 发送信号的进程ID,对实时信号以及SIGCHLD有                意义 */
                  uid_t    si_uid;    /* 发送信号进程的真实用户ID,对kill(2),实时信号以及SIGCHLD有意义 */
                   int      si_status; /* 退出状态,对SIGCHLD有意义*/
                  clock_t  si_utime;  /* 用户消耗的时间,对SIGCHLD有意义 */
                  clock_t  si_stime;  /* 内核消耗的时间,对SIGCHLD有意义 */
                  sigval_t si_value;  /* 信号值,对所有实时有意义,是一个联合数据结构,
             /*可以为一个整数(由si_int标示,也可以为一个指针,由si_ptr标示)*/    
                 void *   si_addr;   /* 触发fault的内存地址,对SIGILL,SIGFPE,SIGSEGV,SIGBUS 信号有意义*/
                 int      si_band;   /* 对SIGPOLL信号有意义 */
                  int      si_fd;     /* 对SIGPOLL信号有意义 */
}

sa_mask : 信号的集合。 指定在信号处理程序执行过程中,哪些信号应当被阻塞。缺省情况下当前信号本身被阻塞,防止信号的嵌套发送。
sigaction ()安装信号的处理函数执行过程中由 sa_mask 指定的信号才被阻塞。
sa_flags 用于更改指定信号的行为 。比较重要的标志位是 SA_SIGINFO ,当设定了该标志位时,表示信号附带的参数可以被传递到信号处理函数中,因此,应该为 sigaction 结构中的 sa_sigaction 指定处理函数,而不应该为 sa_handler 指定信号处理函数,否则,设置该标志变得毫无意义。即使为 sa_sigaction 指定了信号处理函数,如果不设置 SA_SIGINFO ,信号处理函数同样不能得到信号传递过来的数据,在信号处理函数中对这些信息的访问都将导致段错误( Segmentation fault )。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void myFun(int sig);
int main(int argc, char* argv[])
{
        struct sigaction act, oldact;
        act.sa_handler = myFun;
        sigemptyset(&act.sa_mask);
        act.sa_flags = 0;
        sigaction(SIGUSR1, &act, &oldact);
        while(1){
                printf("Hello world!\n");
                pause();
        }
}
void myFun(int sig)
{
        printf("I got a signal:%d\n",sig);
}
Gcc sigacton1.c –o sigaction
./ sigaction &
Kill –SIGUSR1 pid
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>

void func(int signo, siginfo_t *info, void *p)
{
        printf("signo = %d\n", signo);
        printf("sender pid = %d\n", info->si_pid);
}
int main()
{
        struct sigaction   act,  oldact;
        sigemptyset(&act.sa_mask);
        act.sa_flags = SA_SIGINFO;
        act.sa_sigaction = func;
        sigaction(SIGUSR1, &act, &oldact);
        while(1)
        {
                printf("pid is %d hello!\n",getpid());
                pause();
        }
}

在另外一个终端发送信号给当前进程 

sigqueue()函数调用示例在不同进程间传递整型参数.信号接收程序

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
void myFun(int, siginfo_t*, void* myfun);
int main(int argc, char* argv[])
{
        struct sigaction act;
        int sig;
        pid_t pid;
        pid = getpid();
        printf("pid is%d\n",pid);

        sigemptyset(&act.sa_mask);
        act.sa_sigaction = myFun;
        act.sa_flags = SA_SIGINFO;
        if(sigaction(SIGUSR1, &act, NULL)<0)
        {
                printf("install sig error\n");
                return 0;
        }
        while(1)
        {
                sleep(2);
                printf("wait for the signal\n");
        }
}
void myFun(int signo, siginfo_t *info, void* myfun)
{
        printf("the int value is %d\n",info->si_int);
        printf("Recv signum is%d\n",signo);
        //raise(SIGKILL);
}

sigqueue()函数调用示例在不同进程间传递整型参数.信号发送程序

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/time.h>
main(int argc, char* argv[])
{
        pid_t pid;
        int signum;
        union sigval mysigval;
        pid = (pid_t)atoi(argv[1]);
        mysigval.sival_int = 8;
        if(sigqueue(pid, SIGUSR1, mysigval)==-1)
                printf("send error\n");
        sleep(2);
        return 0;
}

signal()sigaction()的区别

不同点
signal()
安装的信号不能向信号处理函数传递信息
sigaction ()
可设置进程的信号掩码,返回设置之前的 sigaction 结构
安装的信号可以向信号处理函数传递信息
相同点
都可以为指定的信号设置信号处理函数
共用同一个内核函数 do_sigaction ()

信号集操作函数

信号集定义
函数原型
int sigemptyset ( sigset_t *set);
初始化信号集合 set ,将 set 设置为空
int sigfillset ( sigset_t *set);
初始化信号集合,将信号集 set 设置为包含所有信号的集合
int sigaddset ( sigset_t *set, int signo );
将信号 signo 加入到信号集 set
int sigdelset ( sigset_t *set, int signo );
将信号 signo 从信号集 set 中删除
int sigismember ( sigset_t *set, int signo );

查询信号signo是否在信号集set

信号操作函数sigprocmask( )

功能
通过信号集 set 修改进程的信号阻塞集
函数原型
int sigprocmask (int how, const sigset_t *set, sigset_t * oset );
参数
how :函数操作方式
SIG_BLOCK :增加一个信号集到当前进程的阻塞集中
SIG_UNBLOCK :从当前阻塞集中删除一个信号集
SIG_SETMASK :将当前信号集设置为信号阻塞集合
set :当前进程的信号集
oset :保存当前进程的信号阻塞集
说明
在使用之前需先设置好信号集合 set

其他信号处理函数

sigpending ( sigset_t *set))
获取当前进程的未决信号集
set 保存返回结果
sigsuspend (const sigset_t *mask))
在接收到某个信号之前,临时用 mask 替换进程的信号掩码,并暂停进程执行,直到收到信号为止
sigsuspend 返回后将恢复调用之前的信号掩码
信号处理函数完成后,进程将继续执行
该系统调用始终返回 -1 ,并将 errno 设置为 EINTR

task_struct中与信号处理相关的成员

struct signal_struct *signal
信号 描述符结构 每种信号选择处理函数
struct sighand_struct * sighand
包含信号处理函数描述符的数组,信号作为数组序号
sigset_t blocked, real_blocked
被阻塞信号的掩码,每种信号类型对应一个元素
struct sigpending pending;
维护本进程中的未决信号
sigset_t saved_sigmask ;
保存信号掩码

定义TIF_RESTORE_SIGMASK时恢复信号掩码

task_struct信号处理相关数据结构关系图

 

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

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

相关文章

xgboost对密西西比数据集csv文件进行预测

代码&#xff1a; # 导入需要的库 from sklearn.preprocessing import LabelEncoder import matplotlib.pyplot as plt import pandas as pd import xgboost as xgb from sklearn.model_selection import train_test_split from sklearn.metrics import confusion_matrix, cla…

自定义事件总线

文章目录 什么是自定义事件总线具体实现思路分析定义结构实现 on实现 emit实现 off 源码 什么是自定义事件总线 自定义事件总线属于一种观察着模式&#xff0c;其中包括三个角色发布者&#xff08;Publisher&#xff09;&#xff1a;发出事件&#xff08;Event&#xff09;订阅…

[SwiftUI]工程最低适配iOS13

问题&#xff1a; 新建工程&#xff0c;选择最低支持iOS13报错&#xff1a; main() is only available in iOS 14.0 or newer Scene is only available in iOS 14.0 or newer WindowGroup is only available in iOS 14.0 or newer 解决&#xff1a; 注释掉上面代码&#x…

短剧分销系统搭建:其成为普通人创业的新选择?短剧的红利有多高?

去年&#xff0c;短剧进入到了爆发期&#xff0c;成为了年轻人闲暇时间的娱乐方式。短剧每集只有几分钟时间&#xff0c;非常适合当下大众的碎片化时间。根据当下短剧的发展趋势&#xff0c;短剧的市场规模将逐渐赶超电影票房。 目前短剧还进行了多元化发展&#xff0c;逐渐走…

两数之和 ? 三数之和? 四数之和? 统统搞定

&#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;推荐专栏1: &#x1f354;&#x1f35f;&#x1f32f;C语言初阶 &#x1f43b;推荐专栏2: &#x1f354;&#x1f35f;&#x1f32f;C语言进阶 &#x1f511;个人信条: &#x1f335;知行合一 前言 声明…

高性价比LDR6028Type-C转3.5mm音频和PD快充转接器

随着市面上的大部分手机逐渐取消了3.5mm音频耳机接口&#xff0c;仅保留一个Type-C接口&#xff0c;追求音质和零延迟的用户面临着一大痛点。对于这些用户&#xff0c;Type-C转3.5mm接口线的出现无疑是一大福音。这款线材在刚推出时就受到了手机配件市场的热烈欢迎&#xff0c;…

Python武器库开发-武器库篇之子域名扫描器开发(四十一)

Python武器库开发-武器库篇之子域名扫描器开发(四十一) 在我们做红队攻防或者渗透测试的过程中&#xff0c;信息收集往往都是第一步的&#xff0c;有人说&#xff1a;渗透的本质就是信息收集&#xff0c;前期好的信息收集很大程度上决定了渗透的质量和攻击面&#xff0c;本文将…

AI数字人国内人工智能产业发展趋势

随着科技的不断进步&#xff0c;人工智能&#xff08;Artificial Intelligence&#xff0c;简称AI&#xff09;已成为当今社会的热门话题。作为一种复杂而高级的技术&#xff0c;人工智能在国内发展势头迅猛。本文将探讨AI数字人国内人工智能产业的发展趋势。 首先&#xff0c…

科锐16位汇编学习笔记01汇编基础和debug使用

为什么学习16位汇编&#xff1f; 16位操作指令最多能够操作两个字节&#xff0c;且更能够体现出与硬件的交互。16位下的指令和32位汇编的指令差不多。16位汇编的指令在32位一样使用.要学好汇编必须要了解一点点硬件知识,16汇编是直接操作硬件,32位汇编指令跟硬件隔离了 硬件运…

simulink代码生成(六)——中断向量模块的配置

假如系统中存在多个中断&#xff0c;需要合理的配置中断的优先级与中断向量表&#xff1b;在代码生成中&#xff0c;要与中断向量表对应&#xff1b;中断相关的知识参照博客&#xff1a; DSP28335学习——中断向量表的初始化_中断向量表什么时候初始化-CSDN博客 F28335中断系…

目标检测-One Stage-YOLOv2

文章目录 前言一、YOLOv2的网络结构和流程二、YOLOv2的创新点预处理网络结构训练 总结 前言 根据前文目标检测-One Stage-YOLOv1可以看出YOLOv1的主要缺点是&#xff1a; 和Fast-CNN相比&#xff0c;速度快&#xff0c;但精度下降。&#xff08;边框回归不加限制&#xff09;…

24年初级会计资格考试报名信息采集流程共10大步骤,千万不要搞错

2024年初级会计资格考试报名信息采集流程共10大步骤&#xff0c;不要搞错哦&#xff1b; 第一步&#xff1a;输入证件号、点击登录 第二步&#xff1a;阅读采集须知 第三步&#xff1a;填写个人信息&#xff08;支付宝搜索"亿鸣证件照"或者微信搜索"随时照&q…

uniapp 日历组件

我们的需求是显示当前月和下个月的排班表 引入 uniapp 日历组件 uni-calendar 做法有两种&#xff0c;一种是直接去修改组件&#xff0c;还有就是文档中提供的 selected 方法 修改组件的就不写了 <uni-calendar :lunar"true" :selected"selected" :in…

2023 hnust 湖南科技大学 大四上 计算机图形图像技术 课程 期末考试 复习资料

计算机图形图像技术复习资料 前言 改编自&#xff1a;https://blog.csdn.net/Liu_Xin233/article/details/135232531★重点&#xff0c;※补充github 考试题型 简述题&#xff08;10分4题&#xff0c;共40分&#xff09; 第1章的基本内容三维观察流水线中的基本概念与理解三…

使用Python给图片加水印(通过OpenCV和Pillow实现,内含完整代码链接)

from PIL import Image, ImageFont, ImageDraw, ImageEnhance, ImageChops import cv2 import math import numpy as npdef crop_image(im):"""裁剪图片边缘空白"""bg Image.new(mode"RGBA", sizeim.size)bbox ImageChops.differenc…

ASPICE4.0标准参考模型

aspice4.0 已经发布了&#xff0c;最近正在规划公司开发流程向4.0升级&#xff0c;研究对比了下4.0和3.1的改变&#xff0c;整体来说4.0减少了很多3.1不实用的过程&#xff0c;增加了硬件过程&#xff0c;机器学习过程&#xff0c;过程细节叶更加贴近项目的实际需求&#xff0c…

【Python特征工程系列】教你利用逻辑回归模型分析特征重要性(源码)

这是Python特征工程系列原创文章&#xff0c;我的第191篇原创文章。 一、问题 应用背景介绍&#xff1a; 如果有一个包含数十个甚至数百个特征的数据集&#xff0c;每个特征都可能对你的机器学习模型的性能有所贡献。但是并不是所有的特征都是一样的。有些可能是冗余的…

【年终总结系列 2023】新起点,同时追寻更高的起点

什么是攀登者&#xff0c;用一个场景来概括就是&#xff1a;经常弯腰低头手脚并用向上攀爬&#xff0c;待到山的顶峰后终于可以舒展一下身体&#xff0c;但若舒展的时间过长便会觉得无聊&#xff0c;此时向远处眺望&#xff0c;发现了更高的山峰&#xff0c;便又充满了激情。对…

上门洗车小程序开发源码,预约上门或到店洗车

预约上门洗车小程序&#xff0c;可以预约上门服务&#xff0c;也可以预约到店洗车&#xff0c;可以在线开通会员&#xff0c;领优惠券&#xff0c;分销推广。门店商家端可以管理订单&#xff0c;查看收益。 该系统分为三个端&#xff1a;用户端、商家端、管理后台。 一 用户端…

数据结构 模拟实现Stack栈(数组模拟)

目录 一、栈的概念 二、栈的接口 三、栈的方法实现 &#xff08;1&#xff09;push方法 &#xff08;2&#xff09;pop方法 &#xff08;3&#xff09;peek方法 &#xff08;4&#xff09;size方法 ​编辑 &#xff08;5&#xff09;empty方法 四、最终代码 一、栈的…