当前位置: 首页 > news >正文

Linux系统编程---精灵进程与守护进程

1、前言

        精灵进程又称守护进程、后台进程,在英文中称为 daemon 进程。精灵进程是运行在一个相对干净的环境、不受终端影响、常驻内存的进程,和神话中的精灵一样,拥有不死不灭的特性,长期稳定提供某种功能或服务。

        在Linux系统中,通过ps命令,可以看到许多以 -d 结尾的进程,它们大多都是守护进程,例如:

Snail@ubuntu:~/Desktop$ ps -ef | grep '.*d$'
root         376       1  0 19:45 ?        00:00:01 /lib/systemd/systemd-journald
root         394       1  0 19:45 ?        00:00:00 vmware-vmblock-fuse /run/vmblock-fuse -o rw,subtype=vmware-vmblock,default_permissions,allow_other,dev,suid
root         440       1  0 19:45 ?        00:00:01 /lib/systemd/systemd-udevd
systemd+     687       1  0 19:45 ?        00:00:00 /lib/systemd/systemd-oomd
systemd+     688       1  0 19:45 ?        00:00:00 /lib/systemd/systemd-resolved
systemd+     701       1  0 19:45 ?        00:00:00 /lib/systemd/systemd-timesyncd
root         725       1  0 19:45 ?        00:00:00 /usr/sbin/blkmapd
root         727       1  0 19:45 ?        00:00:00 /usr/sbin/nfsdcld
root         728       1  0 19:45 ?        00:00:00 /usr/sbin/rpc.idmapd
root         738       1  0 19:45 ?        00:00:01 /usr/bin/vmtoolsd
root         788       1  0 19:45 ?        00:00:00 /usr/sbin/acpid
root         803       1  0 19:45 ?        00:00:00 /usr/sbin/irqbalance --foreground
root         834       1  2 19:45 ?        00:00:08 /usr/lib/snapd/snapd
root         844       1  0 19:45 ?        00:00:00 /lib/systemd/systemd-logind
root         847       1  0 19:45 ?        00:00:00 /usr/libexec/udisks2/udisksd
colord       955       1  0 19:45 ?        00:00:00 /usr/libexec/colord
root        1097       1  0 19:45 ?        00:00:00 /usr/sbin/cups-browsed
statd       1109       1  0 19:45 ?        00:00:00 /sbin/rpc.statd
root        1112       1  0 19:45 ?        00:00:00 /usr/sbin/rpc.mountd
root        1312       1  0 19:45 ?        00:00:00 /usr/libexec/upowerd
root        1318       1 10 19:45 ?        00:00:34 /usr/libexec/packagekitd
Snail       1635    1522  0 19:48 ?        00:00:00 /usr/libexec/gvfsd
Snail       1848    1522  0 19:49 ?        00:00:00 /usr/libexec/gsd-keyboard
Snail       1875    1522  0 19:49 ?        00:00:00 /usr/libexec/gsd-smartcard
Snail       1880    1522  0 19:49 ?        00:00:00 /usr/libexec/gsd-sound
root        2407       1  4 19:49 ?        00:00:05 /usr/libexec/fwupd/fwupd

        有许多程序或服务理应成为这种“不死”的守护进程,比如提供系统网络服务的核心程序systemd-networkd,只要系统需要基于TCP/IP协议栈进行网络通信,它就应该一直常驻内存,永不退出。

        成为守护进程的关键在于使进程运行在一个相对独立、干净的环境,尽量不受各种事件的影响(除非断电、关机),接下来讲着重讲解守护进程相关的基础知识及守护进程创建的流程。

        其中,章节2为守护进程的基础铺垫,注意讲解在创建守护进程时,可能遇到的一些知识储备,在第三章主要讲解守护进程的创建流程及参考代码。

2、守护进程的基础铺垫

2.1、基本概念

        在创建守护进程的过程中,会跟如下诸多概念打交道,如进程组、前台进程组、后台进程组、会话、控制终端等,下图简略地反应了它们之间的关系:

        系统调度最小单位进程,若干进程可组成一个进程组,若干进程组可组成一个会话,可见这几个概念都只是进程的组织方式,之所以要构造进程组和会话,其根本目的是为了便于发送信号:通过给进程组或会话发送信号,便可使得其内所有的进程均可收到信号。

        控制终端指的是跟会话相关联的登录窗口程序,或伪终端程序(比如gnome-terminal),这些程序一般都有关联的输入设备,一般是键盘。可以使用控制终端设备来产生输入数据或信号,进而影响会话中的前台进程组,也可通过挂断操作来影响会话中的后台进程组。

2.2、进程组

①、什么是进程组

        进程是系统中的活跃个体,是系统的调度单位,进程就像现实世界中的活动的人,社会为了便于管理,一般都会将人归总到某一个集体中,比如公司、学校、组织等,系统中的进程也一样,他们可以按照实际所需进入某个进程组。进程组的好处在于,可以给组内的所有进程统一发送信号

        进程组API接口:

#include <sys/types.h>
#include <unistd.h>// 功能: 将进程pid的所在进程组设置为pgid
//       如果pid == 0,则设置本进程
//       如果pgid == 0,等价于pgid == pid
// 注意:若进程pid与进程组pgid不在同一会话内,会设置失败
int setpgid(pid_t pid, pid_t pgid); // 把进程 pid 设置到 进程组ID为pgid 的进程组中// 功能: 获取进程pid所在进程组ID
pid_t getpgid(pid_t pid); // 获取进程 pid 所属的进程组//函数setpgid( )使用细节:
// 将指定进程123加入进程组7799中
// 注意,进程组7799必须存在且与进程123同处相同的会话
setpgid(123, 7799);// 将本进程加入进程组7799中
// 注意,进程组7799必须存在且与本进程同处相同的会话
setpgid(0, 7799);// 创建一个ID等于本进程PID的进程组
// 并将本进程置入其中,成为进程组组长
setpgid(0, 0);  // 自己创建一个进程组并把自己设置组长
②、前台进程组

        一般而言,进程从终端启动时,会自动创建一个新进程组,并且该进程组内只包含这个创始进程,而其后代进程默认都将会被装载在该进程组内部,这个进程组被称为前台进程组

        前台进程组最大的特点是:可以接收控制终端发来的信号,所谓控制终端,一般就是指标准输入设备键盘。

        以下代码显示了一个子进程脱离父进程的前台进程组,从而脱离控制终端的过程:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>void display_process_id()
{printf("本进程ID:%d\t", getpid());printf("父进程ID:%d\t", getppid());printf("进程组ID:%d\t", getpgid(0));printf("所在会话ID:%d\n", getsid(0));
}int main()
{if(fork() == 0){display_process_id();// 将本进程的所属进程组,设置为等于本进程ID// 即:创建一个仅包含自身的进程组并将自身置入其中if(setpgid(0, 0) < 0)perror("setpgid() failed");elseshowid();}pause();
}

        通过上面的代码,使得子进程“自立门户”,不再与其父进程同处一个进程组,因此如果从控制终端按下 ctrl+c 时,那么这个快捷键触发的信号 SIGINT 只会发送给前台进程组子进程将不受影响

        注意:在一个会话中,前台进程组只有一个,而后台进组可以有多个!!!

③、后台进程组

        后台进程组,顾名思义,就是在后台运行的进程组。

        在终端运行程序时,可以加个 & 来使得进程进入后台进程组:

# 使 a.out 在后台进程组中运行
Snail@ubuntu:~/Desktop$ ./a.out &

        让一个进程在后台进程组中运行,通常是为了使其让出控制终端,不接受控制终端的输入和信号,但这并不意味着它不受控制终端控制(Cntl + C ),控制终端依然可向其发送挂断信号(kill -9 xxxx)

        上述后台进组进程 a.out 与即将要介绍的后台进程(或称精灵进程、守护进程)无关。

2.3、会话

        会话(session)原本指的是一个登录过程中所产生的的所有进程组的总和,可以理解为一个登录窗口就是一个会话。但在伪终端中,每打开一个窗口实际上也是创建了一个会话,例如:

        如上所述,会话可以理解为就是进程组的进程组,会话的作用可总结为:

  • 可关联一个控制终端(比如键盘)设备,并从控制终端获得输入信息(键盘的输入、键盘快捷方式产生的信号)
  • 可对会话内的所有进程组统一发送信号(关闭终端--> 相当于给该会话中的所有进程组发送挂断的信号)
  • 可将控制终端的关闭动作,转换为触发挂断信号并发送给所有进程

        当打开一个伪终端,或者打开一个远程登录工具输入账户密码的过程中,默认都调用了如下函数接口去创建一个新的会话。

#include <sys/types.h>
#include <unistd.h>pid_t setsid(void);

注意:

  1. 进程组组长不能调用该函数(组长没有权限去打开一个新的终端)。
  2. 新创建的会话没有关联控制终端,因此其内进程不受控制终端影响
  3. 创建会话的进程,称为该会话的创始进程,创始进程有权捕获一个控制终端(在编写守护进程时通常需要避免),会话的其余成员进程无权获得控制终端。

2.4、控制终端

        控制终端通常会关联一个输入设备给前台进程组发送数据或信号,平常使用的许多信号快捷键,就是通过控制终端发送给前台进程组内的进程的:

快捷键

对应信号

ctrl + c

SIGINT

ctrl + \

SIGQUIT

ctrl + z

SIGSTOP

        控制终端不仅可以向前台进程组发送数据也能向整个会话发送挂断信号(即SIGHUP),默认情况下收到SIGHUP的进程会被终止,因此,为了避免被控制终端“误杀”,常驻内存的守护进程的必备步骤须包括忽略掉SIGHUP、脱离控制终端、避免再次获取控制终端等操作。以下是示例代码:

// 忽略信号SIGHUP
signal(SIGHUP, SIG_IGN);// 脱离控制终端(新建一个会话)
setsid();// 避免会话再次关联控制终端(退出会话创始进程)
if(fork() > 0)exit(0);

3、守护进程的创建流程

3.1、忽略SIGHUP

        由于终端的关闭会触发SIGHUP并发送给终端所关联的会话的所有进程,而一开始进程尚未脱离原会话,因此应尽早忽略该信号避免被挂断信号误杀

        实现代码如下:

// 1,忽略挂断信号SIGHUP,防止被终端误杀
signal(SIGHUP, SIG_IGN);

3.2、产生子进程

        从终端(不管是远程登录窗口还是本地伪终端)启动的进程所在的会话都关联了控制终端,而控制终端会有各种数据或信号的输入干扰,为了避开这些干扰,需要脱离控制终端,而脱离控制终端的简单做法就是新建一个新的、没有控制终端的会话,但创建一个新会话的进程必须是非进程组组长,但Linux系统中,从终端启动的进程默认就是其所在进程组的组长,因此摆脱这一困境的简单做法就是让其产生一个子进程,退出原进程(即父进程)并让子进程继续下面的步骤即可。

        实现代码如下:

// 2,退出父进程(原进程组组长),为能成功创建新会话做准备
if(fork() > 0)exit(0);

3.3、创建新会话

        创建新会话,脱离原会话,脱离控制终端

        实现代码如下:

// 3,创建新会话,脱离原会话,脱离控制终端。
setsid();

3.4、产生孙子进程

        此时的进程是其所在的会话的创始进程,而创始进程拥有可以再次关联的控制终端的权限,为避免此种情况的发生,最简单的做法就是退出当前创始进程,改由其子进程(非创始进程)继续完成成为守护进程的使命。

        实现代码如下:

// 4,断绝重新关联控制终端的可能性
if(fork() > 0)exit(0);

3.5、进入新进程组

        虽然此时进程的父进程、祖父进程已经退出,但进程组是一直都在的,且处于新会话中的孙子进程一直都在其祖父进程的进程组之中,而进程组是可以传递信号的,因此为了与任何方面脱离关系,应“自立门户”创建新进程组,并将自身置入其中。

        实现代码如下:

// 5,脱离原进程组,创建并进入只包含自身的进程组
setgpid(0, 0);

3.6、关闭文件资源

        文件资源是可以在父子进程之间代际相传的,这其中也包括了标准输入输出文件,而作为守护进程,是一种在后台运行的程序,运行过程中一般无需交互,若有消息需要输出一般会以系统日志的方式输出到指定日志文件中。因此,为了节约系统资源,也为了避免不必要的逻辑谬误,守护进程一般都需要将所有从父辈进程继承下来的文件全部关闭

        实现代码如下:

// 6,关闭父辈继承下来的所有文件
for(int i=0; i<sysconf(_SC_OPEN_MAX); i++)  // 通过遍历把已经打开所有描述符进行逐个关闭close(i);

3.7、关闭文件权限掩码

        在Linux系统中创建一个新文件时,可以通过相关的函数参数指定文件的权限,比如:

// 试图在file.txt不存在的情况下,创建一个权限为0777的文件
int fd = open("file.txt", O_CREAT|O_RDWR, 0777); // 实际则是  0777  -  umask = 0775

        但其实被创建出来的文件的权限并非代码中指定的权限,该权限与系统当前的文件权限掩码做位与操作之后的值才是文件真正的权限,我们可以通过命令 umask 来查看当前系统默认的文件权限掩码的值:

Snail@ubuntu:~/Desktop/process$ umask
0002
Snail@ubuntu:~/Desktop/process$ 

        因此,上述创建的文件的权限最后不是0777,而是0775:

Snail@ubuntu:~/Desktop/process$ ls -l
-rwxrwxr-x 1 Snail Snail     0 Apr 23 20:57 file.txt
Snail@ubuntu:~/Desktop/process$ 

        为了让守护进程在后续工作过程创建文件时指定的权限不受系统文件权限掩码干扰,可以将umask设置为0

        实现代码如下:

// 7,避开系统文件权限掩码的干扰
umask(0);

3.8、切换进程工作路径

        任何一个进程都有一个当前工作路径,从终端启动的进程的工作路径就是启动时终端所在的系统路径。以下代码可以输出进程当前所在路径:

#include <stdio.h>
#include <unistd.h>int main(void)
{printf("%s\n", getcwd(NULL, 0));
}

        提醒:当一个进程的工作路径被卸载时,进程也会随时消亡。守护进程为了避免此种情况发生,最简单的做法就是将自身的工作路径切换到一个无法被卸载的路径下,比如根目录

        实现代码如下:

// 8,避免所在路径被卸载
chdir("/");

        守护进程创建的最后一步是修改进程运行的工作路径,因此在守护进程中所有访问文件的路径建议都使用绝对路径,避免打开、创建文件失败。

3.9、守护进程代码实例

#include<stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <stdlib.h>int main(void)
{pid_t a;int max_fd, i;/*********************************************
1. ignore the signal SIGHUP, prevent the
process from being killed by the shutdown
of the present controlling termination
**********************************************/signal(SIGHUP, SIG_IGN);/***************************************
2. generate a child process, to ensure
successfully calling setsid()
****************************************/a = fork();if(a > 0)exit(0);/******************************************************
3. call setsid(), let the first child process running
in a new session without a controlling termination
*******************************************************/setsid();/*************************************************
4. generate the second child process, to ensure
that the daemon cannot open a terminal file
to become its controlling termination
**************************************************/a = fork();if(a > 0)exit(0);/*********************************************************
5. detach the daemon from its original process group, to
prevent any signal sent to it from being delivered
**********************************************************/setpgrp();/*************************************************
6. close any file descriptor to release resource
**************************************************/max_fd = sysconf(_SC_OPEN_MAX);for(i=0; i<max_fd; i++)close(i);/******************************************
7. clear the file permission mask to zero
*******************************************/umask(0);/****************************************
8. change the process's work directory,
to ensure it won't be uninstalled
*****************************************/chdir("/");// Congratulations! Now, this process is a DAEMON!pause();return 0;
}

相关文章:

Linux系统编程---精灵进程与守护进程

1、前言 精灵进程又称守护进程、后台进程&#xff0c;在英文中称为 daemon 进程。精灵进程是运行在一个相对干净的环境、不受终端影响、常驻内存的进程&#xff0c;和神话中的精灵一样&#xff0c;拥有不死不灭的特性&#xff0c;长期稳定提供某种功能或服务。 在Linux系统中&a…...

《让机器人读懂你的心:情感分析技术融合奥秘》

机器人早已不再局限于执行简单机械的任务&#xff0c;人们期望它们能像人类伙伴一样&#xff0c;理解我们的喜怒哀乐&#xff0c;实现更自然、温暖的互动。情感分析技术&#xff0c;正是赋予机器人这种“理解人类情绪”能力的关键钥匙&#xff0c;它的融入将彻底革新机器人与人…...

科技项目必须进行验收测试吗?项目验收测试服务机构有哪些?

在现代科技迅猛发展的背景下&#xff0c;各类科技项目层出不穷&#xff0c;从智能硬件到软件系统&#xff0c;乃至工业自动化解决方案&#xff0c;项目的质量直接关系到企业的信誉、用户体验和市场竞争力。那么科技项目必须进行验收测试吗? 简短且明确的回答是&#xff1a;必…...

7.7 Axios+Redux+JWT全链路实战:打通前后端API通信最佳实践

Axios+Redux+JWT全链路实战:打通前后端API通信最佳实践 连接前端与后端 API:全链路数据交互设计指南 关键词:前后端通信架构设计、RESTful API 开发、Axios 请求拦截、Redux 状态管理、JWT 认证集成 1. 前后端通信架构设计原则 我们采用分层架构实现前后端解耦,通过 RES…...

零基础入门 Verilog VHDL:在线仿真与 FPGA 实战全流程指南

摘要 本文面向零基础读者,全面详解 Verilog 与 VHDL 两大主流硬件描述语言(HDL)的核心概念、典型用法及开发流程。文章在浅显易懂的语言下,配合多组可在线验证的示例代码、PlantUML 电路结构图,让你在 EDA Playground 上动手体验数字电路设计与仿真,并深入了解从 HDL 编写…...

[蓝桥杯 2025 省 Python B] 最多次数

import sysdef max_times() -> int:s sys.stdin.readline().strip()checked {l,q,b} # set()&#xff0c;不存在键值对&#xff0c;识别为set&#xff08;&#xff09;n len(s)time 0i 0while i < n - 2:sec s[i:i3]if set(sec) checked:i 3time 1else:i 1sys.…...

HTTP相关

目录 一、HTTP状态码 1XX信息性状态码 2XX成功状态码 3XX重定向状态码 4XX客户端错误状态码 5XX服务器错误状态码 二、GET/POST/PUT/DELETE请求 2.1GET 2.2POST 2.3PUT 2.4DELETE 2.5RESTful API例子 三、RESTful API 3.1什么是RESTful API 3.2RESTful API中的关…...

使用rclone迁移minio文件

文章目录 一、rclone简介1、工具说明2、核心特点2.1、跨平台支持2.2、多存储支持2.3、加密与安全2.4、增量同步与断点续传2.5、高性能 3、适用场景3.1、云存储迁移3.2、备份与同步3.3、跨云协作3.4、数据加密归档 二、常用命令1、基础操作2、文件传输3、文件管理4、高级功能5、…...

基于Java与MAVLink协议的多无人机(Cube飞控)集群控制与调度方案问题

基于Java与MAVLink协议的多无人机&#xff08;Cube飞控&#xff09;集群控制与调度方案问题 背景需求&#xff1a; 我们目前有一个基于Cube飞控的无人机系统&#xff0c;需实现以下核心功能&#xff1a; 多机通信&#xff1a;通过MAVLink协议同时连接并控制多架无人机&#x…...

Super-Vlan和MUX-Vlan的原理、配置、区别

Super-Vlan 原理 Super-Vlan也叫Aggregate-Vlan。 一般的三层交换机中&#xff0c;通常是采用一个VLAN对应一个vlanif接口的方式实现广播域之间的互通&#xff0c;这在某些情况下导致了IP地址的浪费。因为一个VLAN对应的子网中&#xff0c;子网号、子网定向广播地址、子网缺…...

数据一致性问题剖析与实践(二)——单机事务的一致性问题

一、前言 我们一般讲到单机事务&#xff0c;离不开的就是数据库&#xff0c;其最重要的定义就是&#xff0c;要么全部成功执行&#xff0c;要么全部不执行&#xff0c;保证安全的状态转化。 之前我们讨论了几种场景的一致性问题 冗余数据存储中的一致性问题分布式共识中的一…...

VUE Element-ui Message 消息提示组件自定义封装

为了让message 信息提示的更加方便快捷&#xff0c;减少不同地方的调用&#xff0c;避免代码的重复&#xff0c;特意再官方message 组件的基础上二次封装&#xff0c;使代码更加的优雅和高效。 实现效果&#xff1a; 代码组件&#xff1a; 封装成 message.js 文件&#xff0c;…...

HSTL详解

一、HSTL的基本定义 HSTL&#xff08;High-Speed Transceiver Logic&#xff09; 是一种针对高速数字电路设计的差分信号接口标准&#xff0c;主要用于高带宽、低功耗场景&#xff08;如FPGA、ASIC、高速存储器接口&#xff09;。其核心特性包括&#xff1a; 差分信号传输&…...

【PCB工艺】运放电路中的负反馈机制

通过运算方法器电路设计详细解释负反馈机制&#xff08;Negative Feedback&#xff09; 负反馈 是控制系统、电子电路、神经系统等多个领域中非常核心的概念。特别在运算放大器&#xff08;Op-Amp&#xff09;电路中&#xff0c;负反馈是实现精确控制和高稳定性的关键机制。 …...

玩转Docker | 使用Docker部署Neko自托管浏览器

玩转Docker | 使用Docker部署Neko自托管浏览器 前言一、Neko介绍简介主要特点二、系统要求环境要求环境检查Docker版本检查检查操作系统版本三、部署Neko服务下载镜像创建容器创建容器检查容器状态检查服务端口安全设置四、访问Neko服务访问Neko首页登录Neko五、基本使用设置键…...

聊聊自动化用例的维护

自动化测试中的农药悖论&#xff1a;为何长期维护至关重要 自动化测试常被视为"一次编写&#xff0c;永久有效"的解决方案&#xff0c;但随着时间的推移&#xff0c;即使设计最精良的测试套件也会逐渐失效。这种现象被称为农药悖论&#xff08;Pesticide Paradox&am…...

OpenCV 图形API(60)颜色空间转换-----将图像从 YUV 色彩空间转换为 RGB 色彩空间函数YUV2RGB()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 将图像从 YUV 色彩空间转换为 RGB。 该函数将输入图像从 YUV 色彩空间转换为 RGB。Y、U 和 V 通道值的常规范围是 0 到 255。 输出图像必须是 8…...

Docker配置带证书的远程访问监听

一、生成证书和密钥 1、准备证书目录和生成CA证书 # 创建证书目录 mkdir -p /etc/docker/tls cd /etc/docker/tls # 生成CA密钥和证书 openssl req -x509 -newkey rsa:4096 -keyout ca-key.pem \ -out ca-cert.pem -days 365 -nodes -subj "/CNDocker CA" 2、为…...

监督学习(Supervised Learning)与无监督学习(Unsupervised Learning)​

监督学习与无监督学习是机器学习的两大核心范式&#xff0c;主要区别在于数据是否包含明确的“标签”&#xff08;目标输出&#xff09;。 ​​1. 监督学习&#xff08;Supervised Learning&#xff09;​​ ​​定义​​&#xff1a; ​​数据形式​​&#xff1a;输入数据&…...

批量将多个 Excel 表格中的某张图片替换为新的图片

对于 Excel 文档&#xff0c;相信大家都不陌生&#xff0c;我们可以在 Excel 单元格中插入各种各样的图片&#xff0c;我们也可以将 Excel 表格中的图片替换为新的图片&#xff0c;常规的做法我们都是通过 Office 来进行单个处理的&#xff0c;但是如果我们遇到批量处理的场景&…...

数据一致性问题剖析与实践(三)——分布式事务的一致性问题

一、前言 之前我们讨论了几种场景的一致性问题 冗余数据存储中的一致性问题分布式共识中的一致性问题单机事务中的一致性问题 本文将围绕分布式事务中的一致性问题展开讨论。 二、分布式环境的最大难题 相对于单机环境&#xff0c;分布式环境中&#xff0c;一致性问题最大…...

分布式理论和事务

微服务和分布式 微服务 是一种软件架构风格&#xff0c;它将应用程序拆分成一系列小型、独立的服务&#xff0c;每个服务专注于单一功能&#xff0c;彼此通过轻量级通信机制&#xff08;如 API&#xff09;进行交互。微服务通常是松耦合的&#xff0c;可以独立开发、部署和扩展…...

基于Flask与Ngrok实现Pycharm本地项目公网访问:从零部署

目录 概要 1. 环境与前置条件 2. 安装与配置 Flask 2.1 创建虚拟环境 2.2 安装 Flask 3. 安装与配置 Ngrok 3.1 下载 Ngrok 3.2 注册并获取 Authtoken 4. 在 PyCharm 中创建 Flask 项目 5. 运行本地 Flask 服务 6. 启动 Ngrok 隧道并获取公网地址 7. 完整示例代码汇…...

flutter和vue3项目利用webview_flutter插件通信

近来需要实现一个功能: flutter项目的会员中心页面跳转到vue3项目的活动页,点击该活动页面的“签到”按钮后到flutter项目的积分中心页面进行签到,签到成功后手动返回上一个页面即vue3活动页面的按钮状态更新问题(需更新为“已签到”)。 实现方法:通过webview_flutter …...

sql 根据时间范围获取每日,每月,年月的模版数据

1&#xff1a;获取每日模版数据&#xff08;参数也支持跨年&#xff09; SELECT a.selected_date cdate FROM(SELECT adddate(1970-01-01,t4.i * 10000 t3.i * 1000 t2.i * 100 t1.i * 10 t0.i) selected_dateFROM( SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELEC…...

亚信安全与联通数科达成战略合作,成立联信事业部

4月22日&#xff0c;亚信安全与联通数字科技有限公司&#xff08;以下简称“联通数科”&#xff09;正式签署战略合作协议&#xff0c;双方宣布将联合成立“联信事业部”&#xff0c;仪式上&#xff0c;联通数科董事长孙江山与亚信安全董事长何政为“联信事业部”成立揭牌&…...

第五节:进阶特性高频题-Teleport与Suspense组件应用

Teleport&#xff1a;解决模态框/弹窗的DOM层级问题&#xff08;如挂载到body&#xff09; Suspense&#xff1a;处理异步组件加载状态&#xff08;fallback内容展示&#xff09; 深入解析 Vue3 的 Teleport 与 Suspense 组件 一、Teleport 组件&#xff1a;突破 DOM 层级限制…...

如何使用 uv 构建 Python 包并本地安装

本文将逐步指导你创建一个简单的 Python 包&#xff0c;并将其本地安装到机器或云环境中。完成本教程后&#xff0c;你将拥有一个可复用的 Python 库&#xff0c;可直接通过 pip 安装或在项目中导入使用。 步骤详解 Step 0: 选择构建工具 - 使用 uv 推荐理由&#xff1a;uv 是…...

集结号海螺捕鱼组件搭建教程与源码结构详解(第一篇)

本系列将基于 C Unity3D Java MySQL 构建的集结号海螺捕鱼平台&#xff0c;全面拆解组件架构、服务部署、客户端接入、数据库结构等内容&#xff0c;适合技术团队二次开发及运维部署。 一、整体架构说明 集结号海螺捕鱼平台采用三层结构&#xff1a; 客户端&#xff08;Uni…...

RabbitMQ复习笔记

文章目录 MQ 概述同步调用拓展性差的问题性能下降的问题级联失败问题 异步调用举例 技术选型 RabbitMQRabbitMQ 安装RabbitMQ 收发消息交换机队列绑定关系模拟发送消息 RabbitMQ 数据隔离用户管理virtual host 授权 SpringAMOPSpringAMOP 快速入门消息发送消息接收 Work Queues…...

游戏开发核心技术解析——从引擎架构到攻防体系的完整技能树

游戏开发必备的7大技术体系&#xff0c;涵盖从Unity/Unreal引擎应用、C/C#编程范式到图形渲染管线构建等核心技术&#xff0c;特别剖析MMO游戏开发中的网络安全架构设计要点。通过2023年某头部游戏公司DDoS攻击事件&#xff0c;揭示实时防御策略与合规审计的关键作用。一、游戏…...

Execl 最佳字体和大小推荐[特殊字符]

文章目录 ✅ **通用推荐字体与字号**&#x1f524; **字体说明**&#x1f4ca; 场景推荐&#x1f4c1; 办公文档&#xff08;如财务报表、周报等&#xff09;&#x1f4c8; 数据可视表格&#x1f4cb; 打印友好 &#x1f310; 多语言场景&#xff08;中英文混排&#xff09; ✅…...

JavaScript学习教程,从入门到精通,Ajax与Node.js Web服务器开发全面指南(24)

Ajax与Node.js Web服务器开发全面指南 一、初识Ajax 1.1 Ajax基本概念 语法知识点&#xff1a; Ajax (Asynchronous JavaScript and XML) 是一种无需重新加载整个网页的情况下&#xff0c;能够更新部分网页的技术核心对象&#xff1a;XMLHttpRequest工作原理&#xff1a; 创…...

VR 全景看车的独特优势​

全方位沉浸式体验​ VR 全景看车最显著的优势&#xff0c;就是为用户带来了全方位的沉浸式体验。通过 VR 技术&#xff0c;用户仿佛置身于真实的汽车展厅或试驾场景之中&#xff0c;能够 360 度无死角地观察车辆的外观、内饰、细节等各个方面 。无论是车辆的整体造型&#xff0…...

Kotlin高阶函数 vs Lambda表达式:关键区别与协作关系

先说结论&#xff1a; ✅ 高阶函数既可以用 Lambda 表达式&#xff0c;也可以用函数引用&#xff01; 在 Kotlin 中&#xff0c;高阶函数&#xff08;Higher-Order Function&#xff09;和 Lambda 表达式密切相关&#xff0c;但它们是两个不同的概念&#xff1a; ✅ 简单理解…...

SQL技术终极指南:从内核原理到超大规模应用

一、DDL核心应用场景与最佳实践 1.1 表结构设计场景矩阵 业务场景核心语法要素典型实现案例电商用户画像JSON字段虚拟列索引CREATE TABLE users (id INT, profile JSON, AS (profile->>$.age) VIRTUAL, INDEX idx_age((profile->>$.age)))物联网时序数据分区表压…...

Qt实现语言切换的完整方案

在Qt中实现语言动态切换需要以下几个关键步骤&#xff0c;我将提供一个完整的实现方案&#xff1a; 一、准备工作 在代码中使用tr()标记所有需要翻译的字符串 cpp button->setText(tr("Submit")); 创建翻译文件 在.pro文件中添加&#xff1a; qmake TRANSLATION…...

消息中间件RabbitMQ02:账号的注册、点对点推送信息

一、默认用户登录和账号注册 1.登录 安装好了RMQ之后&#xff0c;我们可以访问如下地址&#xff1a; RabbitMQ Management 输入默认的管理员密码&#xff0c;4.1.0的管理员账号和密码是&#xff1a; guest guest 2.添加账号 consumer consumer 添加成功后&#xff1a; 角色…...

php 支付宝官方 Alipay Easy SDK

使用 Alipay Easy SDK。 打造最好用的支付宝开放平台服务端SDK&#xff0c;Alipay Easy SDK让您享受极简编程体验&#xff0c;快速访问支付宝开放平台开放的各项核心能力。 要求&#xff1a; PHP版本 > 7.0安装PHP cURL扩展安装PHP OpenSSL扩展安装PHP fileinfo扩展 使用…...

深入理解 java synchronized 关键字

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…...

即时角色:使用可扩展的扩散变换器框架个性化任何角色

Paper Title: InstantCharacter: Personalize Any Characters with a Scalable Diffusion Transformer Framework 论文发布于2025年4月16日 Abstract部分 U-Net架构的局限性:传统的基于U-Net架构的定制方法存在一些问题,如泛化能力不足和生成图像质量的损失。 U-Net模型需要…...

开源作业调度框架Quartz框架详细使用说明

Quartz框架详细使用说明 Quartz 是一个功能强大的开源作业调度框架&#xff0c;广泛用于在Java应用程序中执行定时任务。以下是Quartz框架的详细使用说明、完整代码示例、同类框架对比以及总结表格。 1. Quartz框架概述 特点&#xff1a; 灵活的调度&#xff1a;支持多种调度方…...

配置Spark历史服务器,轻松查看任务记录

在大数据处理中&#xff0c;Spark是一个强大的分布式计算框架。但当Spark服务重启后&#xff0c;之前的运行记录就会消失&#xff0c;给我们排查问题和分析任务执行情况带来不便。这时&#xff0c;配置Spark历史服务器就显得尤为重要&#xff0c;它能帮助我们保存和查看历史任务…...

身份证实名认证:通往数字安全与便捷生活的钥匙

在数字化日益深入我们生活的今天&#xff0c;信息安全和隐私保护成为了每个人关心的焦点。而身份证实名认证作为保障个人信息安全的重要环节&#xff0c;正扮演着越来越关键的角色。它不仅是连接现实世界与数字世界的桥梁&#xff0c;更是确保个人在线活动安全、可靠的基础。 什…...

0基础可以考MySQL OCP么?备考时间需要多久?

最近被问爆的 “0 基础能不能考 MySQL OCP”“备考要多久” 终于来答疑啦&#xff01;作为过来人&#xff0c;负责任地说&#xff1a;0 基础完全能冲&#xff01; 0 基础真的能考 MySQL OCP&#xff1f; 很多姐妹担心自己是数据库小白&#xff0c;连 SQL 都没摸过&#xff0c…...

node.js 实战——(概念以及Buffer 知识点学习)

概念 node.js是一个开源的、跨平台的javascript运行环境&#xff1b;它可以开发服务器应用&#xff0c;可以开发工具类应用&#xff08;webpack、vite、Babel&#xff09;,也可以开发桌面端应用&#xff08;vscode、Figma、Postman) #mermaid-svg-0TkAt8LEFhyrVrsw {font-fami…...

论文阅读 | 大模型工具调用控制的策略优化

文章目录 I. 背景II. 方法细节2.1 问题定义2.2 工具集成RL2.3 PPO2.4 GRPO2.5 OTC-PO2.5.1 OTC-PPO2.5.2 OTC-GRPO2.5.3 工具集成奖励设计 III. 实验 题目&#xff1a; OTC: Optimal Tool Calls via Reinforcement Learning 论文地址&#xff1a; OTC: Optimal Tool Calls via…...

【论文阅读】Dual-branch Cross-Patch Attention Learning for Group Affect Recognition

【论文阅读】Dual-branch Cross-Patch Attention Learning for Group Affect Recognition 摘要1.介绍2.相关工作3.双分支交叉Patch注意力Transformer4.实验5.局限性 摘要 本篇博客参考IEEE 2022年收录的论文Dual-branch Cross-Patch Attention Learning for Group Affect Reco…...

centos stream 10 修改 metric

1. 查看当前网络连接 nmcli connection show 2. 查看当前网络连接的metric ip route show 3. 修改指定连接的 metric sudo nmcli connection modify "Wired connection 1" ipv4.route-metric 100 ipv6.route-metric 100 值越大&#xff0c;优先级越低&#xff…...

Java从入门到“放弃”(精通)之旅——String类⑩

Java从入门到“放弃”&#xff08;精通&#xff09;之旅&#x1f680;——String类⑩ 前言 在Java编程中&#xff0c;String类是最常用也是最重要的类之一。无论是日常开发还是面试&#xff0c;对String类的深入理解都是必不可少的。 1. String类的重要性 在C语言中&#xf…...