【003_音频开发_基础篇_Linux进程通信(20种你了解几种?)】

003_音频开发_基础篇_Linux进程通信(20种你了解几种?)

文章目录

  • 003_音频开发_基础篇_Linux进程通信(20种你了解几种?)
    • 创作背景
    • `Linux` 进程通信类型
    • `fork()` 函数
      • `fork()` 输出 `2` 次
      • `fork()` 输出 `8` 次
      • `fork()` 返回值
      • `fork()` 创建子进程 方式一
      • `fork()` 创建子进程 方式二
      • `fork()` 创建子进程 方式三
      • `fork()` 创建子进程 方式四
      • `fork()` 复制父进程上下文
    • `Socket` 套接字
    • `Socket` - (`Linux IP` 协议)
      • 总体架构
      • `IP 协议` 协议重要结构体
      • `IP 协议 API函数`
      • `IP 协议族`
      • `IP 协议 socket` 类型
      • `IP 协议` 操作函数
    • `Socket` - `UDS` (待更新)
    • `IP 协议` VS. `UDS`
    • `UDS` 应用场景 —— `Docker Daemon`
    • `UDS` 应用场景 —— `Azure IoT Edge`
    • Socket Activation
    • 管道 `pipe`
      • 匿名管道 `Anonymous pipes`
      • 命名管道 `Named pipe/FIFOs`
    • 消息队列
    • 共享内存
    • 信号量
    • 文件锁
    • 共享文件
    • RPC (Remote Procedure Call)
    • Protocol Buffer
    • gRPC
    • RabbitQM
    • ZeroMQ
    • RPC over HTTP
    • FlatBuffers

创作背景

学历代表过去、能力代表现在、学习力代表将来。 一个良好的学习方法是通过输出来倒逼自己输入。写博客既是对过去零散知识点的总结和复盘,也是参加了 零声教育 写博客活动。

零声教育体验课:https://xxetb.xetslk.com/s/3fbO81

本文是开发过程中的知识点总结,供大家学习交流使用,如有任何错误或不足之处,请在评论区指出。

Linux 进程通信类型

如下表描述了Linux常用进程间通信方式了,包含了多种技术,例如基于系统调用、套接字、共享内存和消息队列等,用于实现进程之间的数据传输、同步和协作,以满足不同应用场景下的需求。

序号中文名英文名描述
1管道Pipe匿名管道 在父子进程或兄弟进程之间进行通信。
命名管道 独立进程间通信
2消息队列Message Queues进程之间通过消息队列进行通信,可以实现异步通信。
3共享内存Shared Memory进程可以通过映射共享内存区域来实现共享数据,提高通信效率。
4信号Signals进程可以通过信号来通知其他进程发生了某些事件。
5信号量Semaphores用于控制对共享资源的访问,防止多个进程同时访问造成冲突。
6文件锁File Locks进程可以通过文件锁来实现对共享文件的互斥访问。
7共享文件Shared Files进程可以通过读写共享文件来进行通信,但需要注意同步和并发访问的问题。
8Memory Mapped FilesMemory Mapped Files进程可以将文件映射到它们的地址空间中,实现对文件内容的共享访问。
9直接操作内存Direct Memory Access进程可以直接读写其他进程的内存来进行通信,但这通常需要特殊的权限和保护机制。
10Event LoopsEvent Loops进程可以使用事件循环来监听和处理事件,实现进程间的消息传递和通知。
11套接字/UDSUnixUnix域套接字(Unix Domain Socket),用于本地进程间通信。
12DBusdbusD-Bus 是一个进程间通信机制,常用于 Linux 桌面环境中实现进程间通信和协作。
13套接字/IPIPInternet套接字(Internet Domain Socket),用于在网络中进行通信。
14Remote Procedure CallsRPC允许进程调用另一个进程中的函数,实现远程通信和协作。
15RPC over HTTPRPC over HTTP使用HTTP协议作为传输层,通过远程过程调用(RPC)来进行进程间通信。
16ZeroMQZeroMQZeroMQ 是一个开源的消息队列库,提供了丰富的 API 和通信模式,用于实现进程间通信。
17Socket ActivationSocket Activationsystemd中的一种机制,允许在需要时才启动服务进程。通过UNIX域套接字传递连接。
18RabbitMQRabbitMQ基于AMQP协议的开源消息代理,用于实现可靠的异步通信。
19gRPCgRPCgRPC 是一个高性能、开源的远程过程调用(RPC)框架,可以用于实现进程间通信。
20Protocol BuffersProtocol Buffers使用序列化格式将数据结构编码后进行传输,实现进程间通信。
21FlatBuffersFlatBuffers使用序列化格式将数据结构编码后进行传输,实现进程间通信。

fork() 函数

  • fork() 是一个系统调用,用于创建一个与当前进程完全相同的新进程。
  • 原进程称为 父进程,新创建的进程称为 子进程
  • 在父进程中,fork() 返回子进程的进程 ID;在子进程中,fork() 返回 0
  • 在调用 fork() 时,两个内存空间具有相同的内容。
  • 一个进程进行的内存写操作、文件映射和解除映射操作不会影响另一个进程。
  • 注意: fork() 调用会有 2 次返回,正常我们的函数调用只有一次返回。

fork() 输出 2

fork() 函数调用后输出两次:当前进程 +  子进程

int main(void)
{printf("#### Start pid=%d, parent pid=%d\n\n", getpid(), getppid());fork();printf("#### Exit pid=%d, parent pid=%d\n", getpid(), getppid());return 0;
}

img_fork_output_twice

fork() 输出 8

int main(void)
{printf("#### Start pid=%d, parent pid=%d\n\n", getpid(), getppid());fork(); fork(); fork();printf("#### Exit pid=%d, parent pid=%d\n", getpid(), getppid());return 0;
}

img_fork_output_8_times

fork() 返回值

fork() 函数在父进程中返回子进程的进程 ID,而在子进程中返回 0。调用失败,它将返回一个负值,通常是 -1,表示创建新进程失败。

int main(void)
{printf("#### Start pid=%d, parent pid=%d\n\n", getpid(), getppid());pid_t pid = fork();if (0 == pid){printf("child pid=%d, parent pid=%d\n", getpid(), getppid());}else if (0 < pid){printf("pid=%d, parent pid=%d\n", getpid(), getppid());}else{printf("fork() failed.\n");}printf("#### Exit pid=%d, parent pid=%d\n", getpid(), getppid());return 0;
}

img_fork_return_value

fork() 创建子进程 方式一

父进程创建 2 个子进程

img_fork_way1

int main()
{printf("#### Start pid=%d, parent pid=%d\n\n", getpid(), getppid());// 1. parentpid_t id = fork();if (id == 0) // 2. new child{fork(); // 3. return twice (one is new child)}// total: 3 thread = 1 current + 2 childprintf("#### Exit pid=%d, parent pid=%d\n", getpid(), getppid());return 0;
}

img_fork_way1_test_result

fork() 创建子进程 方式二

父进程创建 4 个子进程

img_fork_way2

int main()
{printf("#### Start pid=%d, parent pid=%d\n\n", getpid(), getppid());    // 1. parentpid_t id = fork();if (id == 0) // 2. new child{id = fork();if (id == 0) // 3. new child{id = fork();if (id == 0) // 4. new child{fork(); // 5. return twice (one is new child)}}}    // total: 3 thread = 1 parent + 4 child    printf("#### Exit pid=%d, parent pid=%d\n", getpid(), getppid());return 0;
}

img_fork_way2_test_result

fork() 创建子进程 方式三

父进程创建 4 个子进程

img_fork_way3

int main(void) {printf("#### Start pid=%d, parent pid=%d\n\n", getpid(), getppid());    pid_t id[4];    // 1. parentfor (int i = 0; i < 4; i++){id[i] = fork();if (id[i] == 0) // 2. new 4 child, by the same parent.{printf("\tI'm child pid=%d, parent pid=%d\n", getpid(), getppid());break;}else if (id[i] > 0){printf("\tI'm parent pid=%d, parent pid=%d\n", getpid(), getppid());}else{printf("fork() failed.\n");}}    // total: 5 thread = 1 parent + 4 child    printf("#### Exit pid=%d, parent pid=%d\n", getpid(), getppid()); // print 5 timesreturn 0;
}

img_fork_way3_test_result

fork() 创建子进程 方式四

父进程比子进程先退出,子进程会变为“孤儿进程”,被1 号/init --user进程收养,进程编号也会变为 1

img_fork_way4

int main()
{printf("#### Start pid=%d, parent pid=%d\n\n", getpid(), getppid());pid_t id[4];// 1. parentfor (int i = 0; i < 4; i++){id[i] = fork();if (id[i] > 0) // 2. new 4 child, child create child.{break;}else if (id[i] == 0) // child exit{}else //failed {}}// total: 5 thread = 1 parent + 4 child    printf("#### Exit pid=%d, parent pid=%d\n", getpid(), getppid());return 0;
}

img_fork_way4_test_result

fork() 复制父进程上下文

char buffer[64] = "hello world!";
int main()
{printf("#### Start pid=%d, parent pid=%d\n\n", getpid(), getppid());pid_t pid = fork();if (0 < pid) // parent{printf("\tI'm parent pid=%d, parent pid=%d\n", getpid(), getppid());for (int i = 0; i < 10; i++){sleep(1);printf("\t%d)Parent (%s)\n", i, buffer);}}else if (0 == pid) // child{printf("\tI'm child pid=%d, parent pid=%d\n", getpid(), getppid());for (int i = 0; i < 5; i++){if (1 == i) // child thread modify buffer {strcpy(buffer, "Sub message.");}sleep(1);printf("\t%d)Sub (%s)\n", i, buffer);}}else{printf("fork() failed.\n");}printf("#### Exit pid=%d, parent pid=%d\n", getpid(), getppid());return 0;
}

img_fork_duplicate_parent

Socket 套接字

  • 套接字是一种软件对象,作为端点,建立了服务器端和客户端程序之间的双向网络通信链路。

  • 套接字允许在同一台或不同的机器上两个不同进程之间进行通信。

  • Socket 本意是 插座/插口 的意思,其实也可以这样理解,一台电脑(服务器)有很多插口,另一台电脑(客户端)有很多插头,把客户端电脑的一个插头,插入到服务端电脑的插孔种,这样 2 台电脑就建立了通信桥梁。

  • 下图左边是 服务端 创建socket流程,右边是 客户端 创建流程:
    img_socket_overview

Socket - (Linux IP 协议)

总体架构

img_socket_ip_protocol_overview

  • glibc: glibc 提供对系统调用的封装,可以使用标准 C 函数来进行 系统调用,而无需直接与系统调用接口打交道。
    • glibc(GNU C Library)GNU 项目中的一个重要组件,是 C 语言编程中常用的标准 C 库。
    • 系统调用 是操作系统提供给用户空间程序与内核进行交互的接口。当用户空间程序需要操作硬件设备、访问文件系统、进行网络通信等底层操作时,通常需要通过系统调用来实现。
  • INET: 提供了各种网络协议函数和接口,使用户空间程序能够通过系统调用来进行网络通信。INET 相关的文件通常位于 /proc/net/ 目录下,提供了关于网络状态、连接信息、路由表等的统计数据和配置信息。
  • VFS/virtual File System: 虚拟文件系统。操作系统中的一种抽象概念,用于管理和访问不同类型的文件系统,使用户和应用程序能够以统一的方式访问文件,而无需了解底层文件系统的细节。
  • ARP/Address Resolution Protocol: 地址解析协议。ARP 是用于将 IP 地址映射到物理硬件地址(如 MAC 地址)的协议。当计算机在本地网络中需要发送数据到另一台计算机时,它需要知道目标计算机的 MAC 地址。ARP 协议通过在本地网络上广播 ARP 请求来获取目标 IP 地址的 MAC 地址,然后将这个映射关系保存在 ARP 缓存中,以便后续通信中使用。
  • ICMP/Internet Control Message Protocol: 是因特网控制报文协议, 不需要指定端口。用于在 IP 网络上发送控制消息的协议,用于检测网络连接是否正常、诊断网络问题以及报告错误。还用于 ping 命令,用于测试与另一个主机之间的网络连接是否正常。

IP 协议 协议重要结构体

img_socket_ip_protocol_structure

  • state: 表示套接字当前所处的状态,如连接已建立、连接中等。
  • type: 套接字类型,表示套接字的通信方式,如常用的 流式套接字数据报套接字等。
  • flags: 套接字的标志,用于指示特定的套接字属性或配置。
  • ops: 指向协议特定套接字操作的指针,通常指向一组函数指针,用于执行套接字操作,如发送数据、接收数据等。
  • file: 这是指向套接字相关文件的指针。在 Linux 内核中,套接字也可以通过文件系统进行访问和操作,这个指针可能指向套接字关联的文件结构。
  • sk: 这是一个指向内部网络协议无关套接字表示的指针。它通常指向 struct sock 类型的数据结构,该结构包含了更底层的网络协议相关信息。
  • wq: 等待队列,用于处理各种套接字相关的等待事件,比如等待连接、等待数据等。

IP 协议 API函数

img_socket_ip_protocol_api

  • socket(): 创建新套接字。
  • bind(): 将套接字与地址绑定。
  • listen(): 将套接字设置为监听模式。
  • accept(): 接受连接请求并创建新套接字。
  • connect(): 建立与目标套接字的连接。
  • send(): 发送数据到连接的套接字。
  • recv(): 从套接字接收数据。
  • close(): 关闭套接字。
  • shutdown(): 关闭套接字的读、写或两者。
  • getsockopt(): 获取套接字选项。
  • setsockopt(): 设置套接字选项。

IP 协议族

img_socket_ip_protocl_family

  • 地址族和协议族其实是一样的,值也一样,都是用来识别不同协议的,为什么要搞两套东西呢?
  • 这是因为之前 Unix 有两种风格系统:BSD 系统和 POSIX 系统,对于 BSD 系统,一直用的是 AF,对于 POSIX 系统,一直用的是PFLinux 作为后起之秀,为了兼容,所以两种都支持,这样两种风格的 Unix 下的软件就可以在 Linux 上运行了。
  • POSIX 系统: Bell 实验室的 Ken ThompsonDennis Richie 一起发明了 Unix 系统。
  • BSD 系统: BSD 代表伯克利软件条件,是 20世界 70 年代,加州大学伯克利分校对贝尔实验室 Unix 进行了一系列修改后的版本,它最终发展成了一个完整的操作系统,有着自己的一套标准。

IP 协议 socket 类型

/* Types of sockets.  */
enum __socket_type
{SOCK_STREAM = 1, /* Sequenced, reliable, connection-based byte streams.  */SOCK_DGRAM = 2, /* Connectionless, unreliable datagrams of fixed maximum length.  */SOCK_RAW = 3, /* Raw protocol interface.  */SOCK_RDM = 4, /* Reliably-delivered messages.  */SOCK_SEQPACKET = 5, /* Sequenced, reliable, connection-based, datagrams of fixed maximum length.  */SOCK_DCCP = 6, /* Datagram Congestion Control Protocol.  */SOCK_PACKET = 10, /* Linux specific way of getting packets at the dev level.  For writing rarp and other similar things on the user level. *//* Flags to be ORed into the type parameter of socket and socketpair and used for the flags parameter of paccept.  */SOCK_CLOEXEC = 02000000, /* Atomically set close-on-exec flag for the new descriptor(s).  */SOCK_NONBLOCK = 00004000 /* Atomically mark descriptor(s) as non-blocking.  */
};
  • SOCK_STREAM: 顺序、可靠、基于连接的字节流,通常用于TCP协议。
  • SOCK_DGRAM: 无连接、不可靠的固定最大长度数据报,通常用于UDP协议。
  • SOCK_RAW: 原始协议接口,允许直接访问网络层以下的协议。
  • SOCK_RDM: 可靠交付的消息,不保证顺序。
  • SOCK_SEQPACKET: 顺序、可靠、基于连接的固定最大长度数据报,每个数据报保持连续性。
  • SOCK_DCCP: 用于 Datagram Congestion Control Protocol(DCCP) 的套接字类型。
  • SOCK_PACKET: Linux 特定的获取数据包的方式,用于在用户级别进行类似 RARP 等操作。
  • SOCK_CLOEXEC: 用于 socketsocketpair 的标志,用于原子性地设置新描述符的 close-on-exec标志。
  • SOCK_NONBLOCK: 用于 socketsocketpair 的标志,用于原子性地将描述符标记为非阻塞。

IP 协议 操作函数

应用层相应的函数,通过 glibc 封装的函数,进行系统调用,最后调用这里的函数。

struct proto_ops {int     family;struct module   *owner;int         (*release)      (struct socket *sock);int         (*bind)         (struct socket *sock,   struct sockaddr *myaddr,   int sockaddr_len);int         (*connect)      (struct socket *sock,   struct sockaddr *vaddr,    int sockaddr_len,     int flags);int         (*socketpair)   (struct socket *sock1,  struct socket *sock2);int         (*accept)       (struct socket *sock,   struct socket *newsock,    int flags,            bool kern);int         (*getname)      (struct socket *sock,   struct sockaddr *addr,     int peer);__poll_t    (*poll)         (struct file *file,     struct socket *sock,       struct poll_table_struct *wait);int         (*ioctl)        (struct socket *sock,   unsigned int cmd,          unsigned long arg);
#ifdef CONFIG_COMPATint         (*compat_ioctl) (struct socket *sock,   unsigned int cmd,        unsigned long arg);
#endifint         (*gettstamp)    (struct socket *sock,   void __user *userstamp,  bool timeval,           bool time32);int         (*listen)       (struct socket *sock,   int len);int         (*shutdown)     (struct socket *sock,   int flags);int         (*setsockopt)   (struct socket *sock,   int level, int optname,  char __user *optval,    unsigned int optlen);int         (*getsockopt)   (struct socket *sock,   int level, int optname,  char __user *optval,    int __user *optlen);
#ifdef CONFIG_COMPATint         (*compat_setsockopt)(struct socket *sock,   int level, int optname,    char __user *optval,     unsigned int optlen);int         (*compat_getsockopt)(struct socket *sock,   int level, int optname,    char __user *optval,     int __user *optlen);
#endifint         (*sendmsg)      (struct socket *sock,   struct msghdr *m,        size_t total_len);/* Notes for implementing recvmsg: msg->msg_namelen should get updated by the recvmsg handlers iff msg_name != NULL. * It is by default 0 to prevent returning uninitialized memory to user space.  The recvfrom handlers can assume that msg.msg_name is either          * NULL or has a minimum size of sizeof(struct sockaddr_storage).*/int         (*recvmsg)      (struct socket *sock,   struct msghdr *m,        size_t total_len,                int flags);int         (*mmap)         (struct file *file,     struct socket *sock,     struct vm_area_struct * vma);ssize_t     (*sendpage)     (struct socket *sock,   struct page *page,       int offset, size_t size,         int flags);ssize_t     (*splice_read)  (struct socket *sock,   loff_t *ppos,            struct pipe_inode_info *pipe,    size_t len, unsigned int flags);int         (*set_peek_off) (struct sock *sk,       int val);int         (*peek_len)     (struct socket *sock);/* The following functions are called internally by kernel with sock lock already held. */int         (*read_sock)      (struct sock *sk,     read_descriptor_t *desc, sk_read_actor_t recv_actor);int         (*sendpage_locked)(struct sock *sk,     struct page *page,       int offset,    size_t size,    int flags);int         (*sendmsg_locked) (struct sock *sk,     struct msghdr *msg,      size_t size);int         (*set_rcvlowat)   (struct sock *sk,     int val);
};
  • 如下是简易调用流程图:
    img_socket_ip_protocol_syscall

Socket - UDS (待更新)

IP 协议 VS. UDS

UDS 应用场景 —— Docker Daemon

UDS 应用场景 —— Azure IoT Edge

Socket Activation

管道 pipe

匿名管道 Anonymous pipes

命名管道 Named pipe/FIFOs

消息队列

共享内存

信号量

文件锁

共享文件

RPC (Remote Procedure Call)

Protocol Buffer

gRPC

RabbitQM

ZeroMQ

RPC over HTTP

FlatBuffers

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

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

相关文章

Diffusion Model原理剖析

目录 前言1. DDPM演算法初览2. 图像生成模型共同目标3. VAE: Lower bound of l o g P ( x ) logP(x) logP(x)4. Diffusion Model背后的数学原理5. 为什么需要Sample?6. Diffusion Model的应用7. Diffusion Model成功的关键总结参考 前言 接着上篇文章 图像生成模型浅析&#…

Three.js入门学习笔记

学习资料&#xff1a; 【Three.js】Three.js快速上手教程_three.module.js-CSDN博客 2024年了&#xff0c;是该学学Three.js了_three.js 2024-CSDN博客 一、three.js简介 three.js是JavaScript编写的WebGL第三方库。 three.js&#xff0c;webGL&#xff0c;openGL三者的关…

【Linux高性能服务器编程】两种高性能并发模式剖析——领导者/追随者模式

hello &#xff01;大家好呀&#xff01; 欢迎大家来到我的Linux高性能服务器编程系列之两种高性能并发模式介绍&#xff0c;在这篇文章中&#xff0c;你将会学习到高效的创建自己的高性能服务器&#xff0c;并且我会给出源码进行剖析&#xff0c;以及手绘UML图来帮助大家来理解…

SpringBoot自动配置底层源码分析

文章目录 1. 什么是SpringBoot的自动装配&#xff1f;2. SpringBoot自动装配的底层原理 1. 什么是SpringBoot的自动装配&#xff1f; Spring Boot的自动配置是一种机制&#xff0c;它使得开发者能够快速地开始构建Spring应用&#xff0c;而不需要手动编写大量的样板代码。Spri…

FRPC+PHP+MYSQL+APACHE2=个人网站

应用背景有公网需求,但是又不想去买又贵又低配置的服务器,然后方案就应运而生 frp/README_zh.md at dev fatedier/frp (github.com) 在这里, FRPC作为内网穿透服务, PHPMYSQLAPACHE2,作为网站搭建,具体细节不细讲, 但是在我的/var/www/html下面 linaroHinlink:/var/www/h…

CSS3新增特性(二)

四、2D 转换 • 属性名&#xff1a;transform &#xff08;可用于制作2D转换&#xff0c;也可用于制作3D转转换&#xff1b;2D转换是平面上的转换&#xff0c;3D转换是在三维立体空间的转换&#xff09; • 作用&#xff1a;对元素进行水平或垂直方向的移动、缩放、旋转、拉长…

二. 搭建Nginx 直播流程服务器

目录 1. 前言 2. 安装 Nginx 依赖 3.下载源码 4. 编译安装 5.配置 rtmp 服务 6.验证配置 1. 前言 服务器由 NGINX+RTMP 构成。 NGINX 是 HTTP 服务器, RTMP 是附加模块。 其中 NGINX 我选择的是用 源码编译方式 进行安装,因为这种方式可以自定义安装指定的…

DevOps(八)Jenkins的Maven和Git插件

一、Maven简介 Maven是一个构建生命周期管理和理解工具&#xff0c;用于Java项目。它提供了标准化的构建流程&#xff0c;并简化了从项目编译到文档生成等各种构建方面的管理。 Maven是由Apache软件基金会开发和维护的一个流行的项目管理工具。它的设计目的是简化Java项目的构…

Linux驱动开发:深入理解I2C时序

目录标题 I2C简介I2C时序关键点Linux内核中的I2C时序处理I2C适配器I2C算法I2C核心 代码示例&#xff1a;I2C设备访问调试I2C时序问题 在Linux驱动开发中&#xff0c;理解和正确处理I2C时序对于确保I2C设备正常工作至关重要。本文将详细介绍I2C通信协议的时序特征&#xff0c;并…

应用在防蓝光显示器中的LED防蓝光灯珠

相比抗蓝光眼镜、防蓝光覆膜、软体降低蓝光强度这些“软”净蓝手段&#xff0c;通过对LED的发光磷粉进行LED背光进行技术革新&#xff0c;可实现硬件“净蓝”。其能够将90%以上的有害蓝光转换为450nm以上的长波低能光线&#xff0c;从硬件的角度解决了蓝光危害眼睛的问题&#…

❤️新版Linux零基础快速入门到精通——第一部分❤️

❤️新版Linux零基础快速入门到精通——第一部分❤️ 非科班的我&#xff01;Ta&#xff01;还是来了~~~1. 来认识一下Linux吧!1.1 操作系统概述1.1.1 操作系统概述1.1.2 操作系统的发展史1.1.2.1 Unix1.1.2.2 Minix1.1.2.3 Linux 1.1.3 操作系统的发展 1.2 Linux初识1.2.1 Lin…

【MySQL】数据库操作指南:数据类型篇

&#x1f331;博客主页&#xff1a;青竹雾色间 &#x1f331;系列专栏&#xff1a;MySQL探险日记 &#x1f618;博客制作不易欢迎各位&#x1f44d;点赞⭐收藏➕关注 ✨人生如寄&#xff0c;多忧何为 ✨ 文章目录 1. 数值类型1.1 tinyint 类型1.2 bit 类型1.3 小数类型1.3.1 f…

nacos配置mysql(windows)

nacos默认是使用的内置数据库derby ,可通过配置修改成mysql,修改成mysql之后&#xff0c;之前配置在derby的数据会丢失 本文使用mysql版本为8.0.22 nacos版本为2.3.1 在mysql里面先创建一个数据库test(名称自定义&#xff0c;和后面配置文件里面的一样就好了) 在上面创建的数据…

Milvus 在哈啰的应用与落地

向量数据库还有哪些可能性&#xff1f; 本期的【User Tech】直播告诉你答案&#xff01;明晚的直播&#xff0c;我们邀请了来自哈啰的资深研发工程师王永辉&#xff0c;他将为我们详细讲解 Milvus 在本地出行及生活服务平台的应用及未来发展的诸多可能性&#xff0c;敬请期待&a…

如何在Windows服务做性能测试(CPU、磁盘、内存)

目录 前言1. 基本知识2. 参数说明 前言 由于需要做一些接口测试&#xff0c;测试是否有真的优化 1. 基本知识 该基本知识主要用来用到Performance Monitor&#xff0c;以下着重介绍下这方面的知识 性能监视器&#xff08;Performance Monitor&#xff09;&#xff1a;Windo…

C++ 核心编程 - 内存分区模型

文章目录 1.1 程序运行前1.2 程序运行后1.3 new 操作符 C 程序在执行时&#xff0c;将内存大致划分为 4个区域&#xff1a; 代码区&#xff1a;存放函数体的二进制代码&#xff0c;由操作系统进行管理&#xff1b;全局区&#xff1a;存放全局变量和静态变量以及常量&#xff1…

MT2041 三角形的个数

思路&#xff1a;找规律&#xff0c;推公式 4等分&#xff1a; 头朝上的三角形&#xff1a; 边长为1&#xff1a;1234s1&#xff1b; 边长为2&#xff1a;123s2&#xff1b; 边长为3&#xff1a;12s3&#xff1b; 边长为4&#xff1a;1s4&#xff1b; 即si12...n-i1(n-i2)*(n-i…

基于高斯混合模型的视频背景提取和人员跟踪算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 MATLAB2013B 3.部分核心程序 .............................................................................. %我们这里…

根据当年节假日和非工作时间计算请假时间-获取每个月的节假日,计算每个月的工作日时间进度,节假日每年更新

根据需求请假时间要排除法定节假日和非工作时间 1.获取当年的节假日 节假日是每年更新的&#xff0c;没有固定接口&#xff0c;需要手动录入 个人根据官方的节假日整理了当年的所有节假日&#xff0c;可以根据个人需求进行修改 // 获取每个月的节假日&#xff0c;如果当月没…

Java | 冒泡排序算法实现

大家可以关注一下专栏&#xff0c;方便大家需要的时候直接查找&#xff0c;专栏将持续更新~ 题目描述 编写一个Java程序&#xff0c;实现冒泡排序算法。程序需要能够接收一个整型数组作为输入&#xff0c;并输出排序后的数组。 冒泡排序是一种简单的排序算法&#xff0c;它…