IGKBoard(imx6ull)-PWM编程蜂鸣器编程控制

news2025/1/16 19:03:17

文章目录

    • 1- PWM介绍
    • 2- PWM使能
      • (1)添加配置
      • (2)export、unexport与npwm属性文件
      • (3)duty_cycle、enable和period属性文件
    • 3- PWM测试编程
      • (1)PWM8管脚连接
      • (2)流程介绍及源码
      • (3)运行结果
    • 4- pwm编程实现音乐播放


1- PWM介绍

PWM(Pulse Width Modulation),是脉冲宽度调制缩写,它是通过对一系列脉冲的宽度进行调制,等效出所需要的波形(包含形状以及幅值),对模拟信号电平进行数字编码,也就是说通过调节占空比的变化来调节信号、能量等的变化。
高电平占多一点,也是占空比大一点亮度就亮一点,占空比小一点亮度就没有那么亮,前提是PWM的频率要大于我们人眼识别频率(大约80Hz以上最好)。在电机驱动、无源蜂鸣器驱动、LCD屏幕背光调节、逆变电路等都会有应用。
我们来介绍一下PWM中涉及到的参数:

  • PWM的频率:
    是指1秒钟内信号从高电平到低电平再回到高电平的次数(如下图一个周期),即一秒钟PWM有多少个周期。50H表示1s有50个周期。

  • PWm周期:
    周期=1/频率,50Hz = 1/50 s = 0.02s = 20ms ,如果频率为50Hz ,也就是说一个周期是20ms那么一秒钟就有 50次PWM周期。

  • 占空比:
    是一个脉冲周期内,高电平(如下图的脉宽时间)的时间与整个周期时间的比例(百分数表示),如下图脉宽时间占总周期时间的比例,即占空比。

在这里插入图片描述


2- PWM使能

在开发板原理图我们可以看见40pin扩展口的PWM7和PWM8,实际上开发板上有4路PWM,如下:

PWM1 ---> backlight //LCD背光
PWM2 ---> beep //蜂鸣器
PWM7,PWM8 ---> 40pin扩展 //需要使能开启

在这里插入图片描述

(1)添加配置

我们需要修改相关配置文件才能使用40pin扩展口的PWM7和PWM8,如下修改(添加)配置文件,添加两个管脚的PWM支持,然后关机重启即可。

root@igkboard:~# vi /run/media/mmcblk1p1/config.txt
# Enable PWM overlays, PWM8 conflict with UART8(NB-IoT/4G module)
dtoverlay_pwm=7 8

(2)export、unexport与npwm属性文件

PWM 同样也是通过 sysfs 方式进行操控,进入到/sys/class/pwm 目录下,可以看到四个pwmchip?命名的文件夹,这4个文件夹其实就对应了IMX6ULL的4个PWM控制器(分别对应pwm1,pwm2,pwm7,pwm8):

root@igkboard:/sys/class/pwm# ls
pwmchip0 pwmchip1 pwmchip2 pwmchip3

进入pwmchip1查看文件我们发现三个属性文件。

  • npwm:这是一个只读属性,读取该文件可以得知该PWM控制器下共有几路PWM输出,如下所示:
root@igkboard:/sys/class/pwm/pwmchip1# cat npwm
1
  • export:与GPIO控制一样,在使用PWM之前,也需要将其导出,通过export属性进行导出,以下所示(可以看见多出来了pwm0,注意导出的编号(echo 0)必须小于npwm(1)的值)
root@igkboard:/sys/class/pwm/pwmchip1# echo 0 > export
root@igkboard:/sys/class/pwm/pwmchip1# ls
consumers device export npwm power pwm0 subsystem suppliers uevent
unexport
  • uexport:unexport:将导出的PWM删除。当使用完PWM之后,我们需要将导出的PWM删除,如下所示(可以看见pwm0不见了)
root@igkboard:/sys/class/pwm/pwmchip1# echo 0 > unexport
root@igkboard:/sys/class/pwm/pwmchip1# ls
consumers device export npwm power subsystem suppliers uevent unexport

(3)duty_cycle、enable和period属性文件

我们进入pwm0可以看见duty_cycle、enable和period三个文件属性:

  • enable:可读可写,写入"0"表示禁止PWM;写入"1"表示使能PWM。读取该文件获取PWM当前是禁止还是使能状态。
echo 0 > enable #禁止PWM输出
echo 1 > enable #使能PWM输出
  • period:用于配置PWM周期,可读可写;写入一个字符串数字值,以ns(纳秒)为单位,譬如配
    置PWM周期为10us(微秒)。
echo 10000 > period #PWM周期设置为10us(10 * 1000ns)
  • duty_cycle:用于配置PWM的占空比,可读可写;写入一个字符串数字值,同样也是以ns为单位。
echo 5000 > duty_cycle #PWM占空比设置为5us

3- PWM测试编程

(1)PWM8管脚连接

在这里插入图片描述
在这里插入图片描述

(2)流程介绍及源码

我们先来梳理一下流程:

  1. 获取终端输入的字符串,拼接字符串/sys/class/pwm/pwmchip/pwm0(?就是终端需要输入的访问哪一个PWM控制器)
  2. 判断上述路径文件是否存在,存在则修改其中的duty_cycle、enable和period文件属性,不存在就需要打开export属性文件写入0,再打开pwm0修改文件属性
  3. 修改文件属性自定义函数,就是打开文件写入即可

源码:
一些不常见的函数都有注释帮助了解。

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

char pwm_path[100];
static int pwm_config(const char *attr, const char *val);

int main(int argc, char *argv[])
{
    char temp[100];
    int fd = -1;//文件描述符

    /*运行的时候需要输入四个参数:执行文件,pwmchip?,周期,占空比*/
    if(4 != argc)
    {
        printf("Please enter four parameters: %s <id> <period> <duty>\n", argv[0]);
        exit(-1);//进程正常退出是exit(0),异常退出是exit(非0)
    }
    
    printf("Pwm config: id<%s> period<%s> duty<%s>\n", argv[1],argv[2],argv[3]);

    /*接下来就是打开文件执行相关命令*/
    memset(pwm_path, 0, sizeof(pwm_path));//有数组使用之前都需要memset一下
    snprintf(pwm_path, sizeof(pwm_path), "/sys/class/pwm/pwmchip%s/pwm0", argv[1]);

    /*如果pwm_path不能打开,export:与GPIO控制一样,在使用PWM之前,也需要将其导出,通过export属性进行导出*/
    /*
         int access(const char *pathname,int mode)参数:
         pathname:表示要测试的文件的路径
         mode:表示测试的模式可能的值有:
         R_OK:是否具有读权限
         W_OK:是否具有可写权限
         X_OK:是否具有可执行权限
         F_OK:文件是否存在
         返回值:若测试成功则返回0,否则返回-1 
    */
    if(access(pwm_path, F_OK))
    {
        memset(temp, 0, sizeof(temp));
        snprintf(temp, sizeof(temp), "/sys/class/pwm/pwmchip%s/export", argv[1]);
        fd = open(temp, O_WRONLY);
        if(fd < 0)
        {
            printf("open pwmchip%s error: %s\n", argv[1], strerror(errno));
            exit(-1);
        }
        /*写入文件0,1个字节*/
        if(1 != write(fd, "0", 1))
        {
            printf("write '0' to pwmchip%s/export error\n", argv[1]);
            close(fd);
            exit(-1);
        }
        printf("export Failed to export\n");
        close(fd);
    }
    /*配置pwm周期*/
    if(pwm_config("period", argv[2]))
    {
        //printf("Configuration cycle failure.\n");
        exit(-1);    
    }

    /*配置占空比*/
    if(pwm_config("duty_cycle", argv[3]))
    {
        //printf("Failed to configure the duty cycle.\n");
        exit(-1);    
    }

    /*使能pwm*/
    pwm_config("enable", "1");

    return 0;
}

/*pwm配置函数,attr:属性文件名字,val:属性的值*/
static int pwm_config(const char *attr, const char *val)
{
    char file_path[100];
    int fd = -1;
    int len;

    /*判断参数*/
    if(attr == NULL || val == NULL)
    {
        printf("[%s] argument error\n", __FUNCTION__);
        return -1;
    }
    memset(file_path, 0, sizeof(file_path));
    snprintf(file_path, sizeof(file_path), "%s/%s", pwm_path, attr);
    fd = open(file_path, O_WRONLY);
    if(fd < 0)
    {   
        printf("[%s] open %s error\n", __FUNCTION__, file_path);
        return fd;
    }
    len = strlen(val);
    /*如果顺利write()会返回实际写入的字节数*/
    if(len != write(fd, val, len))
    {
            printf("[%s] write %s to %s error\n", __FUNCTION__, val, file_path);
            close(fd);
            return -2;
    }
    close(fd);
    return 0;
}

Makefile文件:

CC=arm-linux-gnueabihf-gcc
APP_NAME=pwm_test

all:clean
	@${CC} ${APP_NAME}.c -o ${APP_NAME}

clean:
	@rm -f ${APP_NAME}

make之后生成了ARM架构上运行的文件了。

wangdengtao@wangdengtao-virtual-machine:~/wangdengtao/tftpboot$ make
wangdengtao@wangdengtao-virtual-machine:~/wangdengtao/tftpboot$ file pwm_test
pwm_test: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, BuildID[sha1]=c8161112e18f74d738f5e089f49ad0594037e73f, for GNU/Linux 3.2.0, not stripped

(3)运行结果

tftp服务器不会搭建的可以参考这篇文章:wpa_supplicant无线网络配置imx6ull以及搭建tftp服务器
tftp服务器下载文件到开发板:

root@igkboard:~# tftp -gr pwm_test 192.168.0.134
root@igkboard:~# chmod a+x pwm_test 

运行(pwmchip3(PWM8)):

root@igkboard:~# ./pwm_test 3 10000 1000 
PWM config: id<3>, period<10000>, duty<1000>
root@igkboard:~# ./pwm_test 3 10000 3000 
PWM config: id<3>, period<10000>, duty<3000>
root@igkboard:~# ./pwm_test 3 10000 7000 
PWM config: id<3>, period<10000>, duty<7000>
root@igkboard:~# ./pwm_test 3 10000 9000  
PWM config: id<3>, period<10000>, duty<9000> 

可以发现我们的LED灯越来越亮。

运行(pwmchip1( PWM1蜂鸣器)):

root@igkboard:~# ./pwm_test 1 10000 5000
PWM config: id<1>, period<10000>, duty<5000>
root@igkboard:~# ./pwm_test 1 10000 0
PWM config: id<1>, period<10000>, duty<0>

可以听到蜂鸣器一直在叫,占空比为0的时候就不会叫了,人多的时候还是别放了,挺吵的。


4- pwm编程实现音乐播放

我们先来熟悉一下流程:

  1. 在打开pwm0的基础上我们继续实现。
  2. 首先我们需要了解乐谱的相关信息,将低、中、高音频率分组方便调节,相当于不同的音调。如果是高音音调,只需要将上面的频率乘以 2,如果是低音音调,需要将上面的音频除以2。
    在这里插入图片描述
  3. 我们想要连续播放,就需要在一个循环中不断改变频率,于是需要数组,保存我们需要演奏的曲子乐谱,乐谱数组中就是我们的音调。当然还需要注意休眠的时间,ms级函数的实现。

源码(在第一个代码的基础上添加修改)

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>

typedef struct pwm_one_s
{
    unsigned int msec;//持续的时间,单位毫秒
    unsigned int freq;//频率
    unsigned char duty;//占空比,百分数*100
}pwm_one_t;

#define CX CM
static const unsigned short CL[8]  = {0, 131, 147, 165, 175, 196, 211, 248};
static const unsigned short CM[8]  = {0, 262, 294, 330, 350, 393, 441, 495};
static const unsigned short CH[8]  = {0, 525, 589, 661, 700, 786, 882, 990};

static unsigned short songP[] = 
{
    CX[1], CX[5], CX[5], CX[5], CX[6], CX[6], CX[5], CX[0],
    CX[4], CX[4], CX[3], CX[3], CX[2], CX[2], CX[1], CX[0],
    CX[5], CX[5], CX[4], CX[4], CX[3], CX[3], CX[2], CX[0],
};

static char pwm_path[100];
void mssleep(unsigned long ms);//毫秒级函数的实现
static int pwm_config(const char *attr, const char *val);//pwm配置函数
static int pwm_ring_one(pwm_one_t *pwm_ring);

int main(int argc, char *argv[])
{
    char temp[100];
    int fd = -1;//文件描述符
    pwm_one_t pwm_one_test;

    /*运行的时候需要输入四个参数:执行文件,pwmchip?,周期,占空比*/
    if(2 != argc)
    {
        printf("Please enter two parameters: %s <id>\n", argv[0]);
        exit(-1);//进程正常退出是exit(0),异常退出是exit(非0)
    }
    
    //printf("Pwm config: id<%s> period<%s> duty<%s>\n", argv[1],argv[2],argv[3]);

    /*接下来就是打开文件执行相关命令*/
    memset(pwm_path, 0, sizeof(pwm_path));//有数组使用之前都需要memset一下
    snprintf(pwm_path, sizeof(pwm_path), "/sys/class/pwm/pwmchip%s/pwm0", argv[1]);

    /*如果pwm_path不能打开,export:与GPIO控制一样,在使用PWM之前,也需要将其导出,通过export属性进行导出*/
    /*
         int access(const char *pathname,int mode)参数:
         pathname:表示要测试的文件的路径
         mode:表示测试的模式可能的值有:
         R_OK:是否具有读权限
         W_OK:是否具有可写权限
         X_OK:是否具有可执行权限
         F_OK:文件是否存在
         返回值:若测试成功则返回0,否则返回-1 
    */
    if(access(pwm_path, F_OK))
    {
        memset(temp, 0, sizeof(temp));
        snprintf(temp, sizeof(temp), "/sys/class/pwm/pwmchip%s/export", argv[1]);
        fd = open(temp, O_WRONLY);
        if(fd < 0)
        {
            printf("open pwmchip%s error: %s\n", argv[1], strerror(errno));
            exit(-1);
        }
        /*写入文件0,1个字节*/
        if(1 != write(fd, "0", 1))
        {
            printf("write '0' to pwmchip%s/export error\n", argv[1]);
            close(fd);
            exit(-1);
        }
        close(fd);
    }
    pwm_one_test.freq = 1000;
    pwm_one_test.duty = 50;
    pwm_one_test.msec = 100;
    pwm_config("enable","1");

    for(int i=0; i<(sizeof(songP)/sizeof(songP[0])); i++)
    {
        if(songP[i] == 0)
        {
            pwm_one_test.duty = 0;
        }
        else
        {
            pwm_one_test.duty = 15;
            pwm_one_test.freq = songP[i];
        }
        pwm_one_test.msec = 300;
        pwm_ring_one(&pwm_one_test);//这才是关键的函数
    }
    pwm_config("enable", "0");

    return 0;
}
static int pwm_ring_one(pwm_one_t *pwm_ring)
{
    unsigned long period = 0;
    unsigned long duty_cycle = 0;
    char period_str[20] = {};
    char duty_cycle_str[20] = {};

    /*占空比不可能大于100(0.1*100)*/
    if(!pwm_ring || pwm_ring->duty > 100)
    {
        printf("[INFO] %s argument error.\n", __FUNCTION__);
        return -1;
    }
    period = (unsigned long)((1.f / (double)pwm_ring -> freq)*1e9);//周期=1/频率(s)*1000 000 000ns
    duty_cycle = (unsigned long) (((double)pwm_ring->duty / 100.f)*(double)period);//15/100=15%,15%*一个周期 = 占空比(ns)

    snprintf(period_str, sizeof(period_str), "%ld", period);
    snprintf(duty_cycle_str, sizeof(duty_cycle_str), "%ld", duty_cycle);

    printf("period: %sns, duty_cycle_str: %sns\n", period_str, duty_cycle_str);

    if(pwm_config("period", period_str))
    {
        printf("pwm_config period failure.\n");
        return -1;
    }
    if(pwm_config("duty_cycle", duty_cycle_str))
    {
        printf("pwm_config duty_cycle failure.\n");
        return -2;
    }

    mssleep(pwm_ring->msec);

    if(pwm_config("duty_cycle", "0"))
    {
        printf("pwm_config duty_cycle failure.\n");
    }
    mssleep(20);
}

/*毫秒级函数的实现*/
void mssleep(unsigned long ms)
{
	struct timespec ts = { 
		  .tv_sec  = (long int) (ms / 1000), 
		  .tv_nsec = (long int) (ms % 1000) * 1000000ul 
	  };
	nanosleep(&ts, 0);
}

/*pwm配置函数,attr:属性文件名字,val:属性的值*/
static int pwm_config(const char *attr, const char *val)
{
    char file_path[100];
    int fd = -1;
    int len;

    /*判断参数*/
    if(attr == NULL || val == NULL)
    {
        printf("[%s] argument error\n", __FUNCTION__);
        return -1;
    }
    memset(file_path, 0, sizeof(file_path));
    snprintf(file_path, sizeof(file_path), "%s/%s", pwm_path, attr);
    fd = open(file_path, O_WRONLY);
    if(fd < 0)
    {   
        printf("[%s] open %s error\n", __FUNCTION__, file_path);
        return fd;
    }
    len = strlen(val);
    /*如果顺利write()会返回实际写入的字节数*/
    if(len != write(fd, val, len))
    {
            printf("[%s] write %s to %s error\n", __FUNCTION__, val, file_path);
            close(fd);
            return -2;
    }
    close(fd);
    return 0;
}
root@igkboard:~# tftp -gr pwm_music 192.168.0.134
root@igkboard:~# chmod a+x pwm_music 
root@igkboard:~# ./pwm_music 1
period: 3816793ns, duty_cycle_str: 572518ns
period: 2544529ns, duty_cycle_str: 381679ns
period: 2544529ns, duty_cycle_str: 381679ns
period: 2544529ns, duty_cycle_str: 381679ns
period: 2267573ns, duty_cycle_str: 340135ns
period: 2267573ns, duty_cycle_str: 340135ns
period: 2544529ns, duty_cycle_str: 381679ns
period: 2544529ns, duty_cycle_str: 0ns
period: 2857142ns, duty_cycle_str: 428571ns
period: 2857142ns, duty_cycle_str: 428571ns
period: 3030303ns, duty_cycle_str: 454545ns
period: 3030303ns, duty_cycle_str: 454545ns
period: 3401360ns, duty_cycle_str: 510204ns
period: 3401360ns, duty_cycle_str: 510204ns
period: 3816793ns, duty_cycle_str: 572518ns
period: 3816793ns, duty_cycle_str: 0ns
period: 2544529ns, duty_cycle_str: 381679ns
period: 2544529ns, duty_cycle_str: 381679ns
period: 2857142ns, duty_cycle_str: 428571ns
period: 2857142ns, duty_cycle_str: 428571ns
period: 3030303ns, duty_cycle_str: 454545ns
period: 3030303ns, duty_cycle_str: 454545ns
period: 3401360ns, duty_cycle_str: 510204ns
period: 3401360ns, duty_cycle_str: 0ns

还是Makefile编写之后编译成ARM架构上的文件,然后tftp服务器下载到开发板,给予可执行权限,运行就可以听见小星星的曲子了。


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

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

相关文章

京东JDBook笔记本怎么安装Win10系统使用?

京东JDBook笔记本怎么安装Win10系统使用&#xff1f;有用户使用的京东JDBook笔记本电脑系统是Win7系统的&#xff0c;最近想要去将系统升级到Win10来使用。那么如何将Win7的系统重装Win10呢&#xff1f;以下为大家带来详细的操作步骤图文教程。 准备工作&#xff1a; 1、U盘一个…

视频和视频帧:FFMPEG CPU解码API介绍

写在前面本文将介绍的如何用FFMPEG API做视频解码。视频解码&#xff0c;是将压缩后的视频&#xff08;压缩格式如H264&#xff09;通过对应解码算法还原为YUV视频流的过程&#xff1b;在计算机看来&#xff0c;首先输入一段01串&#xff08;压缩的视频&#xff09;&#xff0c…

用 @types 前缀的包是什么?有什么用?

前言 解决过 TypeScript 的项目大概都是从两个方向&#xff0c;Vue3 方向和 React Native 方向&#xff0c;而在 React Native 方向上我经常会遇到一个烦人的错误 Could not find a declaration file for module ‘juejin-type-study’. ‘d:/fe-project/nodejs/types-study/n…

看懂这篇文章-你就懂了信息安全的密码学

一、前言一个信息系统缺少不了信息安全模块&#xff0c;今天就带着大家全面了解并学习一下信息安全中的密码学知识&#xff0c;本文将会通过案例展示让你了解抽象的密码学知识&#xff0c;阅读本文你将会有如下收获&#xff1a; 熟悉现代密码学体系包含的主流密码技术 掌握Base…

SignalR 实时通讯

SignalR 实时通讯1.SignalR1.1.SignalR 简介1.2.SignalR 功能1.3.传输1.4.中心2.服务器2.1.配置中心2.2.上下文对象2.3.客户端对象2.4.创建2.5.中心功能实现4.客户端6.案例演示&#xff08;DotNet 客户端&#xff09;1.SignalR 1.1.SignalR 简介 SignalR 是一个开放源代码库&a…

内容感知、AI融合:让实景三维看山是山,看水是水

实景三维具备还原客观物理世界的优势性&#xff0c;但也正由于部分真实性的欠缺备受争议。这是因为传统的三维建模软件大多基于像元的匹配与计算的逻辑&#xff0c;对地物进行无差别的重建处理&#xff0c;最终生成的模型看起来扭曲怪异、残缺变形。常见的模型缺陷有&#xff1…

2022 OpenCV Spatial AI大赛前三名项目分享,开源、上手即用,优化了OAK智能双目相机的深度效果。

编辑&#xff1a;OAK中国 首发&#xff1a;oakchina.cn 喜欢的话&#xff0c;请多多&#x1f44d;⭐️✍ 内容可能会不定期更新&#xff0c;官网内容都是最新的&#xff0c;请查看首发地址链接。 ▌前言 Hello&#xff0c;大家好&#xff0c;这里是OAK中国&#xff0c;我是助手…

深圳居住证申领指南

打开广东政务服务网&#xff0c;在首页搜索【深圳经济特区居住证申领】在搜索结果中可以发现有如下链接&#xff0c;点击在线办理 会转到登陆界面&#xff0c;直接使用个人登录并用微信扫描登录 根据提示进行手机登录验证。 完成登录认证之后会自转到深圳经济特区居住证申领界…

二分查找由浅入深--算法--java

二分查找写在开头算法前提&#xff1a;算法逻辑算法实现简单实现leftright可能超过int表示的最大限度代码分析和变换更多需求&#xff1a;求索引最小的值java二分API应用基础题思考难度方法写在开头 二分查找应该是算比较简单的这种算法了&#xff0c;我本以为还可以。但有时候…

Word处理控件Aspose.Words功能演示:使用 Java 比较 MS Word 文档

Aspose.Words 是一种高级Word文档处理API&#xff0c;用于执行各种文档管理和操作任务。API支持生成&#xff0c;修改&#xff0c;转换&#xff0c;呈现和打印文档&#xff0c;而无需在跨平台应用程序中直接使用Microsoft Word。此外&#xff0c; Aspose API支持流行文件格式处…

动态规划初阶-爬楼梯问题

示例1&#xff1a; 输入&#xff1a;cost [10,15,20] 输出&#xff1a;15 解释&#xff1a;你将从下标为 1 的台阶开始。 - 支付 15 &#xff0c;向上爬两个台阶&#xff0c;到达楼梯顶部。 总花费为 15 。示例2&#xff1a; 输入&#xff1a;cost [1,100,1,1,1,100,1,1,10…

使用Docker安装MongoDB,整合SpringBoot

使用Docker安装MongoDB MongoDB 和 MySQL 都是常用的数据库管理系统&#xff0c;但它们的设计目标不同&#xff0c;因此在某些方面的性能表现也有所不同。 MongoDB 是一个文档型数据库&#xff0c;它采用了面向文档的数据模型&#xff0c;支持动态查询和索引&#xff0c;适合…

Docker部署实战

文章目录Docker部署应用准备制作容器镜像启动容器上传镜像docker exec数据卷&#xff08;Volume&#xff09;声明原理实践Docker部署 应用准备 这一次&#xff0c;我们来用 Docker 部署一个用 Python 编写的 Web 应用。这个应用的代码部分&#xff08;app.py&#xff09;非常…

【同步、共享和内容协作软件】上海道宁与​ownCloud让您的团队随时随地在任何设备上轻松处理数据

ownCloud是 一款开源文件同步、共享和 内容协作软件 可让团队随时随地 在任何设备上轻松处理数据 ownCloud开发并提供 用于内容协作的开源软件 使团队能够轻松地无缝 共享和处理文件 而无需考虑设备或位置 开发商介绍 ownCloud成立于2010年&#xff0c;是一个托管和同…

设计模式-笔记

文章目录七大原则单例模式桥模式 bridge观察者模式 observer责任链模式 Chain of Responsibility命令模式 Command迭代器模式 Iterator中介者模式 Mediator享元模式 Flyweight Pattern组合模式 composite装饰模式 Decorator外观模式 Facade简单工厂模式工厂方法模式工厂抽象模式…

Postgresql中的unlogged table

在PG中&#xff0c;有一种表的类型为unlogged table&#xff0c;名如其字&#xff0c;该种类型的表不会写入wal日志中&#xff0c;所以在写入的速度上比普通的堆表快很多&#xff0c;但是该表在数据库崩溃的时候&#xff0c;会被truncate,数据会丢失&#xff0c;而且该表也不支…

Leetcode21. 合并两个有序链表

一、题目描述&#xff1a; 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4]输出&#xff1a;[1,1,2,3,4,4] 示例 2&#xff1a; 输入&#xff1a;l1 [], l2…

Java程序开发中如何使用lntelliJ IDEA?

完成了IDEA的安装与启动&#xff0c;下面使用IDEA创建一个Java程序&#xff0c;实现在控制台上打印HelloWorld!的功能&#xff0c;具体步骤如下。 1.创建Java项目 进入New Project界面后&#xff0c;单击New Project选项按钮创建新项目&#xff0c;弹出New Project对话框&…

【k8s】Kubernetes的学习(1.k8s概念和架构)

目录 1.首先要知道&#xff0c;Kubernetes为什么简称为k8s? 2.Kubernetes概述 2.1 kubernetes基本介绍 2.2 kubernetes的特性 2.3 kubernetes集群架构组件 2.3.1 Master (主控节点) 2.3.2 node (工作节点) 2.4 k8s核心概念 2.4.1 Pod 2.4.2 controller 2.4.3 Se…

操作系统权限提升(十九)之Linux提权-SUID提权

系列文章 操作系统权限提升(十八)之Linux提权-内核提权 SUID提权 SUID介绍 SUID是一种特殊权限&#xff0c;设置了suid的程序文件&#xff0c;在用户执行该程序时&#xff0c;用户的权限是该程序文件属主的权限&#xff0c;例如程序文件的属主是root&#xff0c;那么执行该…