【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");elseprintf("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 *);}_usigset_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信号处理相关数据结构关系图

 

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

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

相关文章

将yolov8的检测框从正框修改为旋转框需要做那些修改?

将yolov8项目修改为yolov8_obb项目需要修改模型结构(增加角度预测)、dataloader(使其支持dota格式数据)、修改TaskAlignedAssigner(使其支持带角度的bbox)、修改loss(新增对角度的训练)、修改metric(将hbb指标titile修改为obb)、修改绘图代码(使其能绘制旋转框)。 …

常用类型_日期..

1.Date java.util.Date是开发中常用的日期处理类(并非java.sql.Date类) 现在这么一个需求&#xff1a; 就是获取当前时区的时间 public class Main{public static void main(String[] args) {// d1和d2表示的时间都是一样的 所以推荐使用第一种写法 比较简洁Date d1 new Da…

MybatisPlus—快速入门

目录 1.使用MybatisPlus的基本步骤 1.1引入MybatisPlus的起步依赖 1.2 定义Mapper 2.MybatisPlus常用注解 2.1 TableName 2.2 TableId 2.3 TableField 2.4 小结 3. 常用配置 4. 总结 1.使用MybatisPlus的基本步骤 1.1引入MybatisPlus的起步依赖 MyBatisPlus官方提…

124基于matlab的禁忌搜索算法和蚁群优化算法优化TSP路径

基于matlab的禁忌搜索算法和蚁群优化算法优化TSP路径&#xff0c;动态输出路径规划过程及输出最小距离。数据可更换自己的&#xff0c;程序已调通&#xff0c;可直接运行。需要直接拍下&#xff0c;拍下后发邮箱。标价为程序价格&#xff0c;不包含售后。程序保证可直接运行。 …

【本科生通信原理】【实验报告】【北京航空航天大学】实验一:通信原理初步

一、实验目的&#xff1a; 熟悉 MATLAB开发环境、掌握 MATLAB基本运算操作&#xff1b;熟悉和了解 MATLAB图形绘制基本指令&#xff1b;熟悉使用 MATLAB分析信号频谱的过程&#xff1b;掌握加性白高斯噪声信道模型 二、实验内容&#xff1a; 三、实验程序&#xff1a; 1、 f…

爬取彼案壁纸

代码展现&#xff1a; 具体代码&#xff1a; import requests import re import os filename 壁纸\\ if not os.path.exists(filename): os.mkdir(filename) for i in range(2,11): url fhttp://www.netbian.com/index_{i}.htm headers {User-Agent: …

日常测试工作中哪些是必须知道的 SQL 语句?

SQL 简介 SQL(Structured Query Language&#xff0c;结构化查询语言)是一套用于管理关系数据库管理系统(RDBMS)&#xff0c;基于 ANSI&#xff08;American National Standards Institute 美国国家标准化组织&#xff09;标准的计算机语言&#xff0c;比较重要的版本是 SQL92…

在Ubuntu22.04上离线部署Tailchat(一)

一&#xff1a;Tailchat介绍 Tailchat 是一款插件化易拓展的开源 IM 应用。可拓展架构赋予 Tailchat 无限可能性。前端微内核架构 后端微服务架构 使得 Tailchat 能够驾驭任何定制化/私有化的场景&#xff0c;是面向企业与私域用户打造&#xff0c;高度自由的群组管理与定制化…

大一,如何成为一名fpga工程师?

​ 1、数电&#xff08;必须掌握的基础&#xff09;&#xff0c;然后进阶学模电&#xff08;选学&#xff09;&#xff0c; 2、掌握HDL&#xff08;HDLverilogVHDL&#xff09;可以选择verilog或者VHDL&#xff0c;建议verilog就行。 3、掌握FPGA设计流程/原理&#xff08;推…

KBDLT2.DLL文件丢失,软件或游戏无法启动,如何解决,试试这些方法,亲测有效

KBDLT2.DLL是Windows操作系统中的一个重要的动态链接库文件&#xff0c;它主要用于支持系统的键盘布局功能&#xff0c;尤其是与立陶宛语相关的键盘布局。 如果KBDLT2.DLL文件缺失或损坏&#xff0c;可能会导致一些问题。例如&#xff0c;当你试图使用立陶宛语键盘布局时&#…

Linux--vim操作

目录 前言 一、vim模式 二、底行模式的操作 三、命令模式的操作 四、替换模式 五、视图模式 六、vim的多文件编译 前言 本文主要讲解了vim的一些使用技巧。帮助我们轻松上手vim。 vim是一种多模式编辑器&#xff0c;通过vim打开文件并对文件进行编辑。 使用vim很简单…

MySQL四大引擎建库建表账号管理

目录 一. 数据库四大引擎 1.1 引擎查看 1.2 InnoDB引擎 1.3 MyISAM引擎 1.4 MEMORY引擎 1.5 Archive引擎 二. 数据库管理 2.1 元数据库 2.2 数据库的增删改查及使用 2.3 权限相关表 三. 数据表管理 3.1 三大范式 3.2 基本数据类型 优化原则 分类 四. 数据库账号…

Service Weaver:Google开源基于分布式应用程序开发的框架,重新定义微服务边界

大家好&#xff0c;我是萧楚河&#xff0c;公众号&#xff1a;golang面试经典讲解&#xff0c;感谢关注&#xff0c;一起学习一起成长。一、前言 今年6月&#xff0c;一群谷歌员工&#xff08;由谷歌软件工程师Michael Whittaker领导&#xff09;发表了一篇名为“Towards Mode…

wsl(ubuntu)创建用户

我们打卡ubuntu窗口&#xff0c;如果没有创建用户&#xff0c;那么默认是root用户 用户的增删改查 查 查询所有的用户列表 cat /etc/passwd | cut -d: -f1cat /etc/passwd: 这个命令用于显示 /etc/passwd 文件的内容。/etc/passwd 文件包含了系统上所有用户的基本信息。每一…

Odoo | Module | 统计系统周期使用人数/当前在线人数

文内材料 GITHUB地址 前言介绍 Odoo作为开源ERP系统的No.01,近年愈发的得到国内很多公司的关注。 虽然它的定位是中小型企业的ERP管理系统&#xff0c;但是在几年的Odoo开发实施过程中&#xff0c;有不足50人的小型企业&#xff0c;也有上万人的中大型企业。功能快速落地和…

ipyvizzu:一款可以绘制超级惊艳的可视化动图的 Python 工具包

今天我给大家介绍一款可视化模块&#xff0c;使用它可以绘制出十分惊艳的动图效果&#xff0c;那么当然第一步我们首先是要安装一下该模块&#xff0c;通过pip命令行来安装 pip install ipyvizzu牛刀小试 我们首先来简单地使用该模块来绘制一张动图&#xff0c;用Pandas导入数…

2024年阿里云服务器优惠活动大全,实时更新

阿里云服务器优惠活动大全包括&#xff1a;云服务器新人特惠、云小站、阿里云免费中心、学生主机优惠、云服务器精选特惠、阿里云领券中心等&#xff0c;活动上阿里云服务器ECS经济型e实例2核2G、3M固定带宽99元一年、轻量应用服务器2核2G3M带宽轻量服务器一年61元&#xff0c;…

【大数据进阶第三阶段之Hive学习笔记】Hive安装

目录 1、环境准备 2、下载安装 3、配置环境变量 4、配置文件 4.1、配置hive-env.sh ​编辑4.2、配置hive-site.xml 5、上传配置jar 6、启动 1、环境准备 安装hadoop 以及 zookeeper、mysql 【大数据进阶第二阶段之Hadoop学习笔记】Hadoop 运行环境搭建-CSDN博客 《z…

C++string类的介绍及常用函数用法总结

&#x1f389;个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名乐于分享在学习道路上收获的大二在校生&#x1f43b;‍❄个人主页&#x1f389;&#xff1a;GOTXX &#x1f43c;个人WeChat&#xff1a;ILXOXVJE&#x1f43c;本文由GOTXX原创&#xff0c;首发CSDN&a…

更改ERPNEXT源

更改ERPNEXT源 一&#xff0c; 更改源 针对已经安装了erpnext的&#xff0c;需要更改源的情况&#xff1a; 1, 更改为官方默认源, 进入frapp-bench的目录&#xff0c; 然后执行: bench remote-reset-url frappe //重设frappe的源为官方github地址。 bench remote-reset-url…