【信号】信号处理与进程通信:快速上手

目录

0. 信号概述

1. 产生信号的方式:

1.1 当用户按某些终端键时,将产生信号。

1.2 硬件异常将产生信号。

1.3 软件异常将产生信号。

1.4 调用kill函数将发送信号。

1.5 运行kill命令将发送信号。

2. 信号的默认(缺省)处理方式

2.1 终止进程:

2.2 缺省出来:

2.3 停止进程:

2.4 让停止的进程恢复运行:

3. 进程收到信号后的处理方式

3.1 执行系统默认动作

3.2 忽略此信号

3.3 执行自定义信号处理函数

4. 常见的信号: 

5. 信号的基本操作

5.1 kill函数

5.2 alarm函数

5.3 setitimer函数(定时器) 

 5.4 raise函数

5.5 abort函数

5.6 pause函数

5.7 signal函数

6. 信号集

6.1 信号集概述

6.2 信号集数据类型

6.3 定义路径:

 6.4 信号集相关的操作主要有以下几个函数:

7. 信号阻塞集(屏蔽集、掩码)

7.1 sigprocmask函数

7.2 sigpending函数

总结:


0. 信号概述

        信号是软件中断,它是在软件层次上对中断机制的一种模拟。

        信号可以导致一个正在运行的进程被另一个正在运行的异步进程中断,转而处理某一个突发事件。

        信号是一种异步通信方式。

        进程不必等待信号的到达,进程也不知道信号什么时候到达。

        信号可以直接进行用户空间进程和内核空间进程的交互,内核进程可以利用它来通知 用户空间进程发生了哪些系统事件。

        每个信号的名字都以字符 SIG 开头。

        每个信号和一个数字编码相对应,在头文件 signum.h 中,这些信号都被定义为正整数。

信号名定义路径: /usr/include/x86_64-linux-gnu/bits/signum.h (ubuntu12.04)

在 Linux 下,要想查看这些信号和编码的对应关系,可使用命令:kill -l

        信号是由当前系统已经定义好的一些标识,每一个标识都会在特定的场合使用。并且都会对进程有一定的影响,当信号产生时,会让当前信号做出相应的操作。这些信号都是已经定义好的,我们不能自己在去创造,直接使用这些就可以了。

1. 产生信号的方式:

1.1 当用户按某些终端键时,将产生信号。

例如:终端上按“Ctrl+c”组合键通常产生中断信号 SIGINT

           终端上按"Ctrl+\"键通常产 生中断信号 SIGQUIT

           终端上按"Ctrl+z"键通常产生中断信号 SIGSTOP。

1.2 硬件异常将产生信号。

        除数为 0,无效的内存访问等。这些情况通常由硬件检测到,并通知内核,然后内 核产生适当的信号发送给相应的进程。

1.3 软件异常将产生信号。

        当检测到某种软件条件已发生,并将其通知有关进程时,产生信号。

1.4 调用kill函数将发送信号。

        注意:接收信号进程和发送信号进程的所有者必须相同,或发送信号进程的 所有者必须是超级用户。

1.5 运行kill命令将发送信号。

        此程序实际上是使用 kill函数来发送信号。也常用此命令终止一个失控的后台进程。

2. 信号的默认(缺省)处理方式

当进程中产生了一个信号,就会让当前进程做出一定的反应。

默认处理进程的方式如下:

2.1 终止进程:

        当信号产生后,当前进程就会立即结束。

2.2 缺省出来:

        当信号产生后,当前进程不做任何处理。

2.3 停止进程:

        当信号产生后,使得当前进程停止。

2.4 让停止的进程恢复运行:

        当信号产生后,停止的进程会恢复执行(后台进程)。

注意:每一个信号只有一个默认的处理方式。

3. 进程收到信号后的处理方式

3.1 执行系统默认动作

        对大多数信号来说,系统默认动作是用来终止该进程。

3.2 忽略此信号

        接收到此信号后没有任何动作。

3.3 执行自定义信号处理函数

        用用户定义的信号处理函数处理该信号。

注意:SIGKILL和SIGSTOP这两个信号只能以默认的处理方式执行,不能忽略,也不能自定义。

4. 常见的信号: 

信号性质默认处理方式
SIGKILL9当产生这个信号后,当前进程会退出,不能被缺省和捕捉退出进程
SIGSTOP19当产生这个信号后,当前进程会停止,不能缺省和捕捉停止进程
SIGINT2键盘输入ctrl+c时产生信号退出进程
SIGQUIT3键盘输入ctrl+\时产生信号退出进程
SIGSTP20键盘输入ctrl+z时产生信号停止进程
SIGCONT18当产生当前信号后,当前停止的进程会恢复运行停止的进程恢复运行
SIGALRM14当调用alarm函数设置的时间到达时会产生当前信号退出进程
SIGPIPE13当管道破裂时,会产生当前信号退出进程
SIGABRT6当调用abort函数时会产生当前信号退出进程
SIGCHLD17当使用fork创建一个子进程时,如果子进程状态改变(退出),会产生当前信号缺省
SIGUSR110用户自定义信号,不会自动产生,只能使用kill函数或命令给指定的进程发送当前信号缺省
SIGUSR212用户自定义信号,不会自动产生,只能使用kill函数或命令给指定的进程发送当前信号缺省

5. 信号的基本操作

5.1 kill函数

#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int signum);
功能:
    给指定进程发送信号。
参数:
    pid:
        pid 的取值有 4 种情况: 
        pid>0: 将信号传送给进程 ID 为 pid 的进程。
        pid=0: 将信号传送给当前进程所在进程组中的所有进程。
        pid=-1: 将信号传送给系统内所有的进程。
        pid<-1: 将信号传给指定进程组的所有进程。这个进程组号等于 pid 的绝对值。
    signum:信号的编号
返回值:
    成功:返回 0
    失败:返回 -1

代码示例: 

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

int main(int argc, char* argv[])
{
	pid_t pid;
	pid = fork();
	if (pid < 0) {
		perror("fork is error:");
		exit(1);
	}
	else if (pid == 0)//子进程的代码区
	{
		int i = 0;
		for (i = 0; i < 5; i++)
		{
			printf("in son process\n");
			sleep(1);
		}
	}
	else//父进程的代码区
	{
		printf("in father process\n");
		sleep(2);
		printf("kill sub process now \n");
		kill(pid, SIGINT);
	}
	return 0;
}

注意:

        使用 kill 函数发送信号,接收信号进程和发送信号进程的所有者必须相同,或者 发送信号进程的所有者是超级用户。

5.2 alarm函数

#include <unistd.h>
unsigned int alarm(unsigned int seconds);
功能: 
    定时器,闹钟,当设定的时间到达时,会产生SIGALRM信号
参数:
    seconds:设定的秒数
返回值: 
    如果alarm函数之前没有alarm设置,则返回0
    如果有,则返回上一个alarm剩余的时间

代码示例: 

#include <stdio.h>
#include <unistd.h>
int main(int argc, char* argv[])
{
	int seconds = 0;
	seconds = alarm(5);
	printf("seconds = %d\n", seconds);
	sleep(2);
	seconds = alarm(5);
	printf("seconds = %d\n", seconds);
	while (1);
	return 0;
}

5.3 setitimer函数(定时器) 

#include <sys/time.h>
int setitimer(int which, const struct itimerval *new_value, struct itimerval
*old_value);
功能:
    设置定时器(闹钟)。 可代替alarm函数。精度微秒us,可以实现周期定时。
参数:
    which:指定定时方式
        a) 自然定时:ITIMER_REAL → 14)SIGALRM计算自然时间
        b) 虚拟空间计时(用户空间):ITIMER_VIRTUAL → 26)SIGVTALRM 只计算进程占用cpu的时间
        c) 运行时计时(用户 + 内核):ITIMER_PROF → 27)SIGPROF计算占用cpu及执行系统调用的时间
    new_value:struct itimerval, 负责设定timeout时间
    struct itimerval {
        struct timerval it_interval; // 闹钟触发周期
        struct timerval it_value; // 闹钟触发时间
    };
    struct timeval {
        long tv_sec; // 秒
        long tv_usec; // 微秒
    }
        itimerval.it_value: 设定第一次执行function所延迟的秒数
        itimerval.it_interval: 设定以后每几秒执行function
    old_value: 存放旧的timeout值,一般指定为NULL
返回值:
    成功:0
    失败:-1

代码示例: 

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

void myfunc(int sig)
{
	printf("hello\n");
}
int main(int argc, char* argv[])
{
	struct itimerval new_value;
	//定时周期
	new_value.it_interval.tv_sec = 1;
	new_value.it_interval.tv_usec = 0;
	//第一次触发的时间
	new_value.it_value.tv_sec = 2;
	new_value.it_value.tv_usec = 0;
	signal(SIGALRM, myfunc); //信号处理
	setitimer(ITIMER_REAL, &new_value, NULL); //定时器设置
	while (1);
	return 0;
}

 5.4 raise函数

#include <signal.h>
int raise(int signum);
功能:
    给调用进程本身送一个信号。
参数:
    signum:信号的编号。
返回值:
    成功:返回 0
    失败:返回 非0

raise(sig) <==> kill(getpid(),sig)

代码示例: 

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

int main(int argc, char const* grgv[]) 
{
	int num = 0;
	while (1) {
		printf("hello world\n");
		sleep(1);
		num++;

		//循环执行5秒后,进程退出
		if (num == 5) {
			raise(SIGINT);
			//kill(getpid(), SIGINT);
		}
	}

	return 0;
}

5.5 abort函数

#include <stdlib.h>
void abort(void);
功能:
    向进程发送一个 SIGABRT 信号,默认情况下进程会退出
参数:
    无
返回值:
    无

注意:

        即使 SIGABRT 信号被加入阻塞集,一旦进程调用了 abort 函数,进程也还是会被终止,且在终止前会刷新缓冲区,关文件描述符。

代码示例: 

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

int main(int argc, char const* grgv[]) 
{
	int num = 0;
	while (1) {
		printf("hello world\n");
		sleep(1);
		num++;

		//循环执行5秒后,进程退出
		if (num == 5) {
			abort();
		}
	}

	return 0;
}

5.6 pause函数

#include <unistd.h>
int pause(void);
功能:
    将调用进程挂起直至捕捉到信号为止。这个函数通常用于判断信号是否已到。
参数:
    无
返回值:
    直到捕获到信号,pause 函数才返回-1,且 errno 被设置成 EINTR。

代码示例: 

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

int main(int argc, char* argv[])
{
	pid_t pid;
	pid = fork();
	if (pid < 0) {
		perror("fail to fork");
		exit(1);
	}
	else if (pid > 0)//父进程的代码区
	{
		printf("in father process\n");
		pause();
	}
	else//子进程的代码区
	{
		printf("in son process\n");
		sleep(3);
		kill(getpid(), SIGINT);
	}
	return 0;
}

5.7 signal函数

#include <signal.h>
void (*signal(int sig,void(*func)(int)))(int)
    typedef void (*sighandler_t)(int);
    sighandler_t signal(int signum,sighandler_t handler);
功能: 
    当进程中产生某一个信号时,对当前信号进行处理
参数: 
    sig:指定要处理的信号
    handler:处理方式
        SIG_INT 当信号产生时,以缺省(忽略)方式处理
        SIG_DFL 当信号产生时,以当前信号默认的方式处理
        void handler(int sig):当信号产生时,通过信号处理函数自定义方式处理,
                                函数名可以随便写,参数表示当前的信号
返回值:
    成功:第一次返回 NULL,下一次返回此信号上一次注册的信号处理函数的地址。如果需要使用此返回
值,必须在前面先声明此函数指针的类型。
    失败:SIG_ERR

代码示例: 

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

void handler(int sig);

int main(int argc, char* argv[])
{
	//以默认的方式处理信号
#if 0
	if (signal(SIGINT, SIG_DFL) == SIG_ERR) {
		perror("fail to signal");
		exit(1);
	}
	if (signal(SIGQUIT, SIG_DFL) == SIG_ERR) {
		perror("fail to signal");
		exit(1);
	}
#endif

	//以忽略的方式处理信号
#if 0
	if (signal(SIGINT, SIG_IGN) == SIG_ERR) {
		perror("fail to siganl");
		exit(1);
	}
	if (signal(SIGQUIT, SIG_IGN) == SIG_ERR) {
		perror("fail to signal");
		exit(1);
	}
#endif

	//以用户自定义方式处理信号
#if 0
	if (signal(SIGINT, handler) == SIG_ERR) {
		perror("fail to signal");
		exit(1);
	}
	if (signal(SIGQUIT, handler) == SIG_ERR) {
		perror("fail to signal");
		exit(1);
	}
#endif 

	while (1) {
		printf("hello world\n");
		sleep(1);
	}
	void handler(int sig) {
		if (sig == SIGINT) {
			printf("SIGINT正在处理\n");
		}
		if (sig == SIGQUIT) {
			printf("SIGQUIT正在处理\n");
		}
	}
	return 0;
}

返回值:

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

void handler(int sig);
void* ret_handler;
void handler(int sig) {
	printf("******************************\n");
	printf("nihao beijing\n");
	printf("welcome to hangzhou\n");
	printf("******************************\n");

	if (signal(SIGINT, ret_handler) == SIG_ERR) {
		perror("fail to signal");
		exit(1);
	}
}
int main(int argc, char* argv[])
{
	if ((ret_handler = signal(SIGINT, handler)) == SIG_ERR){
		perror("fail to siganl");
		exit(1);
	}
	while (1) {
		printf("hello world\n");
		sleep(1);
	}

	return 0;
}

6. 信号集

6.1 信号集概述

        一个用户进程常常需要对多个信号做出处理。为了方便对多个信号进行处理,在Linux系统中引入了信号集。

        信号集是用来表示多个信号的数据类型。

6.2 信号集数据类型

        sigset_t

6.3 定义路径:

        /usr/include/x86_64-linux-gnu/bits/sigset.h   (ubuntu12.04)

 6.4 信号集相关的操作主要有以下几个函数:

  • sigemptyset
  • sigfillset
  • sigismember
  • sigaddset
  • sigdelset
1----sigemptyset()
#include <signal.h>
int sigemptyset(sigset_t *set);
功能: 
    初始化由 set 指向的信号集,清除其中所有的信号即初始化一个空信号集。
参数: 
    set:信号集标识的地址,以后操作此信号集,对 set 进行操作就可以了。
返回值: 
    成功:返回 0
    失败:返回 -1

2----sigfillset()
#include <signal.h>
int sigfillset(sigset_t *set);
功能: 
    初始化信号集合 set, 将信号集合设置为所有信号的集合。
参数: 
    信号集标识的地址,以后操作此信号集,对 set 进行操作就可以了。
返回值:
    成功:返回 0
    失败:返回 -1

3----sigismember()
#include <signal.h>
int sigismember(const sigset_t *set,int signum);
功能: 
    查询 signum 标识的信号是否在信号集合 set 之中。
参数: 
    set:信号集标识符号的地址。
    signum:信号的编号。
返回值: 
    在信号集中返回 1,不在信号集中返回 0
    错误:返回 -1

4----sigaddset()
#include <signal.h>
int sigaddset(sigset_t *set, int signum);
功能: 
    将信号 signum 加入到信号集合 set 之中。
参数: 
    set:信号集标识的地址。
    signum:信号的编号。
返回值: 
    成功:返回 0
    失败:返回 -1

5----sigdelset()
#include <signal.h>
int sigdelset(sigset_t *set, int signum);
功能: 
    将 signum 所标识的信号从信号集合 set 中删除。
参数: 
    set:信号集标识的地址。
    signum:信号的编号。
返回值: 
    成功:返回 0
    失败:返回 -1

代码案例: 

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

v
int main(int argc, char* argv[])
{
	//创建一个信号集
	sigset_t set;
	int ret = 0;
	//初始化一个空的信号集
	sigemptyset(&set);
	//判断SIGINT信号是否在信号集中
	ret = sigismember(&set, SIGINT);
	if (ret == 0) {
		printf("SIGINT is not a member of sigprocmask\n ret=%d\n", ret);
	}
	//将指定的信号添加到信号集中
	sigaddset(&set, SIGINT);
	sigaddset(&set, SIGQUIT);

	ret = sigismember(&set, SIGINT);
	ir(ret == 1) {
		printf("SIGINT is a member of sigprocmask\n ret=%d\n", ret);
	}
	return 0;
}

7. 信号阻塞集(屏蔽集、掩码)

        每个进程都有一个阻塞集,它用来描述哪些信号递送到该进程的时候被阻塞(在信 号发生时记住它,直到进程准备好时再将信号通知进程)。

         所谓阻塞并不是禁止传送信号, 而是暂缓信号的传送。若将被阻塞的信号从信号阻 塞集中删除,且对应的信号在被阻塞时发生了,进程将会收到相应的信号。

7.1 sigprocmask函数

#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
功能: 
    检查或修改信号阻塞集,根据 how 指定的方法对进程的阻塞集合进行修改,新的信号阻塞集由 set 指定,而原先的信号阻塞集合由 oldset 保存。
参数: 
    how:信号阻塞集合的修改方法。
        SIG_BLOCK:向信号阻塞集合中添加 set 信号集
        SIG_UNBLOCK:从信号阻塞集合中删除 set 集合
        SIG_SETMASK:将信号阻塞集合设为 set 集合
    set:要操作的信号集地址。
    oldset:保存原先信号集地址。
    注:若 set 为 NULL,则不改变信号阻塞集合,函数只把当前信号阻塞集合保存到oldset 中。
返回值: 
    成功:返回 0
    失败:返回 -1

代码示例: 

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

int main(int argc, char* argv[])
{
	int i = 0;
	//创建一个信号集
	sigset_t set;
	sigemptyset(&set);
	sigaddset(&set, SIGINT);
	while(1){
		//将set信号集添加到信号阻塞集中
		sigprocmask(SIG_BLOCK, &set, NULL);
		for (i = 0; i < 5; i++) {
			printf("SIGINT signal is blocked\n");
			sleep(1);
		}
		//将set信号集从信号阻塞集中删除
		sigprocmask(SIG_UNBLOCK, &set, NULL);
		for (i = 0; i < 5; i++) {
			printf("SIGINT signal unblocked\n");
			sleep(1);
		}
	}
	return 0;
}

7.2 sigpending函数

#include <signal.h>
int sigpending(sigset_t *set);
功能:
    读取当前进程的未决信号集
参数:
    set:未决信号集
返回值:
    成功:0
    失败:-1

代码示例: 

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

int main()
{
	// 自定义信号集
	sigset_t myset, old;
	sigemptyset(&myset);// 清空 -》 0
	// 添加要阻塞的信号
	sigaddset(&myset, SIGINT);
	sigaddset(&myset, SIGQUIT);
	sigaddset(&myset, SIGKILL);
	// 自定义信号集设置到内核中的阻塞信号集
	sigprocmask(SIG_BLOCK, &myset, &old);
	sigset_t pend;
	int i = 0;
	while (1)
	{
		// 读内核中的未决信号集的状态
		sigpending(&pend);
		for (int i = 1; i < 32; ++i)
		{
			if (sigismember(&pend, i))
			{
				printf("1");
			}
			else if (sigismember(&pend, i) == 0)
			{
				printf("0");
			}
		}
		printf("\n");
		sleep(1);
		i++;
		// 10s之后解除阻塞
		if (i > 10)
		{
			// sigprocmask(SIG_UNBLOCK, &myset, NULL);
			sigprocmask(SIG_SETMASK, &old, NULL);
		}
	}
	return 0;
}

总结:

        信号机制是操作系统中用于处理异步事件的一种强大工具,它提供了一种处理程序中非预期事件(如硬件错误、特定的用户交互等)的方法。理解和有效使用信号机制,可以帮助我们编写更健壮、更稳定的程序。总的来说,信号是进程通信的重要方式之一,它的理解和掌握对于系统编程人员至关重要。

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

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

相关文章

Visual C++类的继承及类中成员的访问特性——搞懂public、protected、private

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;今天来说说Visual C中类的继承及类中成员的访问特性&#xff0c;也就是来搞懂public、protected、private这三个东西。 很多人搞不清楚这三个东西&#xff0c;并且很容易弄错&#xff0c;其实不是学习的人的…

ModaHub魔搭社区:向量数据库MIlvus服务端配置(三)

目录 gpu 区域 logs 区域 metric_config 区域 gpu 区域 在该区域选择是否在 Milvus 里启用 GPU 用于搜索和索引创建。同时使用 CPU 和 GPU 可以达到资源的最优利用&#xff0c;在特别大的数据集里做搜索时性能更佳。 若要切换到 CPU-only 模式&#xff0c;只要将 enable 设…

【VMD-LSTM】变分模态分解-长短时记忆神经网络研究(Python代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

数据库大题

(计算题&#xff0c;20分) 设有两个关系R和S,求① R ∪ S R \cup S R∪S;② R − S R - S R−S;③ R S R \times S RS;④ ∏ C , A ( R ) \prod_{C,A}(R) ∏C,A​(R);⑤ σ B > ′ 4 ′ ( R ) \sigma_{B>4}(R) σB>′4′​(R) 关系R关系S (简答题&#xff0c;10…

基于深度学习FasterRCNN模型Restnet50 的生活垃圾智能分类(准确率达84%)-含python工程全源码

目录 前言总体设计系统整体结构图系统流程图 运行环境1. 硬件环境2. Python 环境 模块实现1. 数据预处理2. 数据加载3. 模型构建4. 模型训练及保存5. 模型加载与调用 系统测试1. 模型准确率2. 分类别准确率 工程源代码下载其它资料下载 前言 本项目基于Faster R-CNN模型&#…

jenkins流水线Pipeline的使用

pipeline流水线 1、jenkins安装pipeline插件 2、创建流水线项目 1、创建pipeline的流水线项目 2、编写流水线 pipeline {agent anystages {stage(拉去代码) {steps {git credentialsId: gitee, url: https://gitee.com/xwb1056481167/jenkins-demo.gitecho 拉去代码}}stage(m…

Vue中如何进行数据导入与Excel导入

Vue中如何进行数据导入与Excel导入 Vue是一款非常流行的JavaScript框架&#xff0c;它提供了一套用于构建用户界面的工具和库。在Vue中&#xff0c;我们可以使用多种方式来导入数据&#xff0c;包括从服务器获取数据、从本地存储获取数据、从文件中读取数据等等。其中&#xf…

NVIDIA Jetson TX1,TX2,TX2 NX,AGX Xavier 和 Nano开发板GPIO口配置及应用

NVIDIA Jetson TX1&#xff0c;TX2&#xff0c;TX2 NX&#xff0c;AGX Xavier 和 Nano开发板GPIO口配置及应用 简介 ​ Jetson TX1、TX2、TX2 NX、AGX Xavier和Nano开发板都配备了一个包含40个引脚的GPIO接头&#xff0c;这些引脚可以用于数字输入输出。如下图 ​ 类似于Rasp…

Solid Converter PDF v10 安装及使用教程

目录 一、软件介绍二、下载教程三、安装教程四、使用教程1.PDF转Word、Html等2.合并PDF文件 一、软件介绍 Solid Converter PDF是一套专门将PDF文件转换成Word的软件。 能够将PDF转换为Word、Excel、HTML、PowerPoint、纯文本文件从PDF文档中提取数据并以CSV等格式保存能够转…

【人工智能】— 深度神经网络、卷积神经网络(CNN)、多卷积核、全连接、池化

【人工智能】— 深度神经网络、卷积神经网络&#xff08;CNN&#xff09;、多卷积核、全连接、池化 深度神经网络训练训练深度神经网络参数共享 卷积神经网络&#xff08;CNN&#xff09;卷积多卷积核卷积全连接最大池化卷积池化拉平向量激活函数优化小结 深度神经网络训练 Pr…

Pytest+selenium+allure+Jenkins自动化测试框架搭建及使用

一、 环境搭建 1. Python下载及安装 Python可应用于多平台包括windows, Linux 和 Mac OS X, 本文主要介绍windows环境下。你可以通过终端窗口输入 "python" 命令来查看本地是否已经安装Python以及Python的安装版本。 如未安装python, 推荐下载python 3.8.3以…

Prompt的技巧持续总结

Prompt 有很多网站已经收录了&#xff0c;比如&#xff1a;aimappro 有些直接抄上述网站的作业即可&#xff0c;不过也来看看&#xff0c; 有一些日常提问大概的咒语该怎么写。 1 三种微调下的提示写法 chatgpt时代的创新&#xff1a;LLM的应用模式比较 实际案例说明AI时代大…

将win上的文件传输到Ubuntu虚拟机

首先获取Ubuntu系统的ip地址&#xff0c;在Ubuntu的Terminal中输入ifconfig&#xff0c;可以看到Ubuntu的ip地址 可以看到我电脑的ip地址是10.0.2.15。更改虚拟机的网络连接 这里以VirtualBox为例&#xff0c;打开VirtualBox设置&#xff0c;选择网络&#xff0c;将连接方式改…

通付盾入围《2023年度中国数字安全能力图谱(行业版)》

近日&#xff0c;数世咨询发布《2023年度中国数字安全能力图谱&#xff08;行业版&#xff09;》。通付盾作为以分布式数字身份和大数据决策智能技术为核心的数字化高端软件与服务提供商&#xff0c;凭借在数字安全领域的实力和影响力&#xff0c;入选政府、互联网两大行业细分…

ElasticSearch的安装和访问

ElasticSearch的安装 前言: 本次下载是在Windows系统进行操作,版本为7.6.1,因为下周最新版本的8.1.2有问题 ElasticSearch基于Java开发,JDK最低1.8版本 ElasticSearch的版本要和之后引入的Maven的Jar包版本对应 1 下载ElasticSearch 官网:https://www.elastic.co/cn/ 产品…

【yocto1】利用yocto工具构建嵌入式Linux系统

文章目录 1.获取Yocto软件源码2.初始化Yocto构建目录2.1 imx-setup-release.sh脚本运行2.2 imx-setup-release.sh脚本解析2.2.1 setup-environment脚本解析 3.构建嵌入式Linux系统3.1 BitBake构建系统3.2 BitBake构建系统过程简要解析3.2.1 解析Metadata基本配置Metadatarecipe…

Spring Boot面试题

什么是 Spring Boot&#xff1f; Spring Boot 是一个简化 Spring 应用程序开发的框架&#xff0c;通过自动配置、起步依赖和简化的配置方式&#xff0c;使开发人员能够更快速、方便地创建和配置 Spring 应用程序&#xff0c;提高开发效率和开发体验。 Spring Boot 的设计目标…

如何做一份干净的git提交记录

背景 毕业工作有一些年头了&#xff0c;之前在写工作代码或者给开源项目贡献的时候&#xff0c;提交代码都不是很规范&#xff0c;甚至可以说十分的随意&#xff0c;想到什么就提交什么&#xff0c;根本没有管理提交记录的概念或者想法&#xff08;当你身边的人都不怎么在意的…

基于 Wav2Lip-GFPGAN 深度学习模型的数字人Demo

写在前面 工作中遇到简单整理博文为 Wav2Lip-GFPGAN 环境搭建运行的 Demo理解不足小伙伴帮忙指正 对每个人而言&#xff0c;真正的职责只有一个&#xff1a;找到自我。然后在心中坚守其一生&#xff0c;全心全意&#xff0c;永不停息。所有其它的路都是不完整的&#xff0c;是…

kubernetes operator解析

您是否想过站点可靠性工程 (SRE) 团队如何有效地成功管理复杂的应用程序&#xff1f; 在 Kubernetes 生态中&#xff0c;只有一个答案&#xff1a;Kubernetes Operators&#xff01; 在本文中&#xff0c;我们将研究它们是什么以及它们是如何工作的。 Kubernetes Operator 概念…