Linux系统GPIO应用编程

news2025/1/14 18:40:36

目录

  • 应用层如何操控GPIO
  • GPIO 应用编程之输出
  • GPIO 应用编程之输入
  • GPIO 应用编程之中断
  • 在开发板上测试
    • GPIO 输出测试
    • GPIO 输入测试
    • GPIO 中断测试

本章介绍应用层如何控制GPIO,譬如控制GPIO 输出高电平、或输出低电平。

应用层如何操控GPIO

与LED 设备一样,GPIO 同样也是通过sysfs 方式进行操控,进入到/sys/class/gpio 目录下,如下所示:

在这里插入图片描述

可以看到该目录下包含两个文件export、unexport 以及5 个gpiochipX(X 等于0、32、64、96、128)命名的文件夹。

⚫ gpiochipX:当前SoC 所包含的GPIO 控制器,我们知道I.MX6UL/I.MX6ULL 一共包含了5 个GPIO控制器,分别为GPIO1、GPIO2、GPIO3、GPIO4、GPIO5,在这里分别对应gpiochip0、gpiochip32、gpiochip64、gpiochip96、gpiochip128 这5 个文件夹,每一个gpiochipX 文件夹用来管理一组GPIO。随便进入到其中某个目录下,可以看到这些目录下包含了如下文件:

在这里插入图片描述

在这个目录我们主要关注的是base、label、ngpio 这三个属性文件,这三个属性文件均是只读、不可写。
base:与gpiochipX 中的X 相同,表示该控制器所管理的这组GPIO 引脚中最小的编号。每一个GPIO引脚都会有一个对应的编号,Linux 下通过这个编号来操控对应的GPIO 引脚。

在这里插入图片描述

label:该组GPIO 对应的标签,也就是名字。

在这里插入图片描述

ngpio:该控制器所管理的GPIO 引脚的数量(所以引脚编号范围是:base ~ base+ngpio-1)。

在这里插入图片描述

对于给定的一个GPIO 引脚,如何计算它在sysfs 中对应的编号呢?其实非常简单,譬如给定一个GPIO引脚为GPIO4_IO16,那它对应的编号是多少呢?首先我们要确定GPIO4 对应于gpiochip96,该组GPIO 引脚的最小编号是96(对应于GPIO4_IO0),所以GPIO4_IO16 对应的编号自然是96 + 16 = 112;同理
GPIO3_IO20 对应的编号是64 + 20 = 84。

⚫ export:用于将指定编号的GPIO 引脚导出。在使用GPIO 引脚之前,需要将其导出,导出成功之后才能使用它。注意export 文件是只写文件,不能读取,将一个指定的编号写入到export 文件中即可将对应的GPIO 引脚导出,譬如:

echo 0 > export # 导出编号为0 的GPIO 引脚(对于I.MX6UL/I.MX6ULL 来说,也就是
GPIO1_IO0)

在这里插入图片描述

导出成功之后会发现在/sys/class/gpio 目录下生成了一个名为gpio0 的文件夹(gpioX,X 表示对应的编号),如图16.1.7 所示。这个文件夹就是导出来的GPIO 引脚对应的文件夹,用于管理、控制该GPIO 引脚,稍后再给大家介绍。

在这里插入图片描述
⚫ unexport:将导出的GPIO 引脚删除。当使用完GPIO 引脚之后,我们需要将导出的引脚删除,同样该文件也是只写文件、不可读,譬如:

echo 0 > unexport # 删除导出的编号为0 的GPIO 引脚

删除成功之后,之前生成的gpio0 文件夹就会消失!

以上就给大家介绍了/sys/class/gpio 目录下的所有文件和文件夹,控制GPIO 引脚主要是通过export 导出之后所生成的gpioX(X 表示对应的编号)文件夹,在该文件夹目录下存在一些属性文件可用于控制GPIO引脚的输入、输出以及输出的电平状态等。

Tips:需要注意的是,并不是所有GPIO 引脚都可以成功导出,如果对应的GPIO 已经在内核中被使用了,那便无法成功导出,打印如下信息:
在这里插入图片描述

那也就是意味着该引脚已经被内核使用了,譬如某个驱动使用了该引脚,那么将无法导出成功!

gpioX
将指定的编号写入到export 文件中,可以导出指定编号的GPIO 引脚,导出成功之后会在/sys/class/gpio目录下生成对应的gpioX(X 表示GPIO 的编号)文件夹,以前面所生成的gpio0 为例,进入到gpio0 目录,该目录下的文件如下所示:
在这里插入图片描述
我们主要关心的文件是active_low、direction、edge 以及value 这四个属性文件,接下来分别介绍这四个属性文件的作用:

⚫ direction:配置GPIO 引脚为输入或输出模式。该文件可读、可写,读表示查看GPIO 当前是输入还是输出模式,写表示将GPIO 配置为输入或输出模式;读取或写入操作可取的值为"out"(输出模式)和"in"(输入模式),如下所示:
在这里插入图片描述
⚫ value:在GPIO 配置为输出模式下,向value 文件写入"0"控制GPIO 引脚输出低电平,写入"1"则控制GPIO 引脚输出高电平。在输入模式下,读取value 文件获取GPIO 引脚当前的输入电平状态。譬如:

# 获取GPIO 引脚的输入电平状态
echo "in" > direction
cat value

# 控制GPIO 引脚输出高电平
echo "out" > direction
echo "1" > value

⚫ active_low:这个属性文件用于控制极性,可读可写,默认情况下为0,譬如:

# active_low 等于0
echo "0" > active_low
echo "out" > direction
echo "1" > value 	#输出高
echo "0" > value 	#输出低

# active_low 等于1
$ echo "1" > active_low
$ echo "out" > direction
$ echo "1" > value 	#输出低
$ echo "0" > value 	#输出高

由此看出,active_low 的作用已经非常明显了,对于输入模式来说也同样适用。
⚫ edge:控制中断的触发模式,该文件可读可写。在配置GPIO 引脚的中断触发模式之前,需将其设置为输入模式:
非中断引脚:echo “none” > edge
上升沿触发:echo “rising” > edge
下降沿触发:echo “falling” > edge
边沿触发:echo “both” > edge

当引脚被配置为中断后可以使用poll()函数监听引脚的电平状态变化,在后面的示例中将向大家介绍。

GPIO 应用编程之输出

上一小节已经向大家介绍了如何通过sysfs 方式控制开发板上的GPIO 引脚,本小节我们编写一个简单地测试程序,控制开发板上的某一个GPIO 输出高、低不同的电平状态,其示例代码如下所示:

本例程源码对应的路径为:开发板光盘->11、Linux C 应用编程例程源码->16_gpio->gpio_out.c。

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

static char gpio_path[100];

static int gpio_config(const char *attr, const char *val)
{
    char file_path[100];
    int len;
    int fd;

    sprintf(file_path, "%s/%s", gpio_path, attr);
    if (0 > (fd = open(file_path, O_WRONLY))) {
        perror("open error");
        return fd;
    }

    len = strlen(val);
    if (len != write(fd, val, len)) {
        perror("write error");
        close(fd);
        return -1;
    }

    close(fd);  //关闭文件
    return 0;
}

int main(int argc, char *argv[])
{
    /* 校验传参 */
    if (3 != argc) {
        fprintf(stderr, "usage: %s <gpio> <value>\n", argv[0]);
        exit(-1);
    }

    /* 判断指定编号的GPIO是否导出 */
    sprintf(gpio_path, "/sys/class/gpio/gpio%s", argv[1]);

    if (access(gpio_path, F_OK)) {//如果目录不存在 则需要导出

        int fd;
        int len;

        if (0 > (fd = open("/sys/class/gpio/export", O_WRONLY))) {
            perror("open error");
            exit(-1);
        }

        len = strlen(argv[1]);
        if (len != write(fd, argv[1], len)) {//导出gpio
            perror("write error");
            close(fd);
            exit(-1);
        }

        close(fd);  //关闭文件
    }

    /* 配置为输出模式 */
    if (gpio_config("direction", "out"))
        exit(-1);

    /* 极性设置 */
    if (gpio_config("active_low", "0"))
        exit(-1);

    /* 控制GPIO输出高低电平 */
    if (gpio_config("value", argv[2]))
        exit(-1);

    /* 退出程序 */
    exit(0);
}

执行程序时需要传入两个参数,argv[1]指定GPIO 的编号、argv[2]指定输出电平状态(0 表示低电平、1 表示高电平)。

上述代码中首先使用access()函数判断指定编号的GPIO 引脚是否已经导出,也就是判断相应的gpioX目录是否存在,如果不存在则表示未导出,则通过"/sys/class/gpio/export"文件将其导出;导出之后先配置了GPIO 引脚为输出模式,也就是向direction 文件中写入"out";接着再配置极性,通过向active_low 文件中写入"0"(不用配置也可以);最后再控制GPIO 引脚输出相应的电平状态,通过对value 属性文件写入"1"或"0"来使其输出高电平或低电平。

使用交叉编译工具编译应用程序,如下所示:

在这里插入图片描述

GPIO 应用编程之输入

本小节我们编写一个读取GPIO 电平状态的测试程序,其示例代码如下所示:
本例程源码对应的路径为:开发板光盘->11、Linux C 应用编程例程源码->16_gpio->gpio_in.c。

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

static char gpio_path[100];

static int gpio_config(const char *attr, const char *val)
{
    char file_path[100];
    int len;
    int fd;

    sprintf(file_path, "%s/%s", gpio_path, attr);
    if (0 > (fd = open(file_path, O_WRONLY))) {
        perror("open error");
        return fd;
    }

    len = strlen(val);
    if (len != write(fd, val, len)) {
        perror("write error");
        close(fd);
        return -1;
    }

    close(fd);  //关闭文件
    return 0;
}

int main(int argc, char *argv[])
{
    char file_path[100];
    char val;
    int fd;

    /* 校验传参 */
    if (2 != argc) {
        fprintf(stderr, "usage: %s <gpio>\n", argv[0]);
        exit(-1);
    }

    /* 判断指定编号的GPIO是否导出 */
    sprintf(gpio_path, "/sys/class/gpio/gpio%s", argv[1]);

    if (access(gpio_path, F_OK)) {//如果目录不存在 则需要导出

        int len;

        if (0 > (fd = open("/sys/class/gpio/export", O_WRONLY))) {
            perror("open error");
            exit(-1);
        }

        len = strlen(argv[1]);
        if (len != write(fd, argv[1], len)) {//导出gpio
            perror("write error");
            close(fd);
            exit(-1);
        }

        close(fd);  //关闭文件
    }

    /* 配置为输入模式 */
    if (gpio_config("direction", "in"))
        exit(-1);

    /* 极性设置 */
    if (gpio_config("active_low", "0"))
        exit(-1);

    /* 配置为非中断方式 */
    if (gpio_config("edge", "none"))
        exit(-1);

    /* 读取GPIO电平状态 */
    sprintf(file_path, "%s/%s", gpio_path, "value");

    if (0 > (fd = open(file_path, O_RDONLY))) {
        perror("open error");
        exit(-1);
    }

    if (0 > read(fd, &val, 1)) {
        perror("read error");
        close(fd);
        exit(-1);
    }

    printf("value: %c\n", val);

    /* 退出程序 */
    close(fd);
    exit(0);
}

执行程序时需要传入一个参数,argv[1]指定要读取电平状态的GPIO 对应的编号。
上述代码中首先使用access()函数判断指定编号的GPIO 引脚是否已经导出,若未导出,则通过
“/sys/class/gpio/export"文件将其导出;导出之后先配置了GPIO 引脚为输入模式,也就是向direction 文件中写入"in”;接着再配置极性、设置GPIO 引脚为非中断模式(向edge 属性文件中写入"none")。
最后打开value 属性文件,读取GPIO 的电平状态并将其打印出来。
使用交叉编译工具编译应用程序,如下所示:
在这里插入图片描述

GPIO 应用编程之中断

在应用层可以将GPIO 配置为中断触发模式,譬如将GPIO 配置为上升沿触发、下降沿触发或者边沿触发,本小节我们来编写一个测试程序,将GPIO 配置为边沿触发模式并监测中断触发状态。其示例代码如下所示:
本例程源码对应的路径为:开发板光盘->11、Linux C 应用编程例程源码->16_gpio->gpio_intr.c。

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

static char gpio_path[100];

static int gpio_config(const char *attr, const char *val)
{
    char file_path[100];
    int len;
    int fd;

    sprintf(file_path, "%s/%s", gpio_path, attr);
    if (0 > (fd = open(file_path, O_WRONLY))) {
        perror("open error");
        return fd;
    }

    len = strlen(val);
    if (len != write(fd, val, len)) {
        perror("write error");
        return -1;
    }

    close(fd);  //关闭文件
    return 0;
}

int main(int argc, char *argv[])
{
    struct pollfd pfd;
    char file_path[100];
    int ret;
    char val;

    /* 校验传参 */
    if (2 != argc) {
        fprintf(stderr, "usage: %s <gpio>\n", argv[0]);
        exit(-1);
    }

    /* 判断指定编号的GPIO是否导出 */
    sprintf(gpio_path, "/sys/class/gpio/gpio%s", argv[1]);

    if (access(gpio_path, F_OK)) {//如果目录不存在 则需要导出

        int len;
        int fd;

        if (0 > (fd = open("/sys/class/gpio/export", O_WRONLY))) {
            perror("open error");
            exit(-1);
        }

        len = strlen(argv[1]);
        if (len != write(fd, argv[1], len)) {//导出gpio
            perror("write error");
            exit(-1);
        }

        close(fd);  //关闭文件
    }

    /* 配置为输入模式 */
    if (gpio_config("direction", "in"))
        exit(-1);

    /* 极性设置 */
    if (gpio_config("active_low", "0"))
        exit(-1);

    /* 配置中断触发方式: 上升沿和下降沿 */
    if (gpio_config("edge", "both"))
        exit(-1);

    /* 打开value属性文件 */
    sprintf(file_path, "%s/%s", gpio_path, "value");

    if (0 > (pfd.fd = open(file_path, O_RDONLY))) {
        perror("open error");
        exit(-1);
    }

    /* 调用poll */
    pfd.events = POLLPRI; //只关心高优先级数据可读(中断)

    read(pfd.fd, &val, 1);//先读取一次清除状态
    for ( ; ; ) {

        ret = poll(&pfd, 1, -1);    //调用poll
        if (0 > ret) {
            perror("poll error");
            exit(-1);
        }
        else if (0 == ret) {
            fprintf(stderr, "poll timeout.\n");
            continue;
        }

        /* 校验高优先级数据是否可读 */
        if(pfd.revents & POLLPRI) {
            if (0 > lseek(pfd.fd, 0, SEEK_SET)) {//将读位置移动到头部
                perror("lseek error");
                exit(-1);
            }

            if (0 > read(pfd.fd, &val, 1)) {
                perror("read error");
                exit(-1);
            }

            printf("GPIO中断触发<value=%c>\n", val);
        }
    }

    /* 退出程序 */
    exit(0);
}

执行程序时需要传入一个参数,argv[1]指定要读取电平状态的GPIO 对应的编号。
上述代码中首先使用access()函数判断指定编号的GPIO 引脚是否已经导出,若未导出,则通过
"/sys/class/gpio/export"文件将其导出。
对GPIO 进行配置:配置为输入模式、配置极性、将触发方式配置为边沿触发。
打开value 属性文件,获取到文件描述符,接着使用poll()函数对value 的文件描述符进行监视,这里为什么要使用poll()监视、而不是直接对文件描述符进行读取操作?这里简单的描述一下。
13.2.3 小节给大家详细介绍了poll()函数,这里不再重述!poll()函数可以监视一个或多个文件描述符上的I/O 状态变化,譬如POLLIN、POLLOUT、POLLERR、POLLPRI 等,其中POLLIN 和POLLOUT 表示普通优先级数据可读、可写,而POLLPRI 表示有高优先级数据可读取,中断就是一种高优先级事件,当中断触发时表示有高优先级数据可被读取。当然,除此之外还可使用13.4 小节所介绍的异步I/O 方式来监视
GPIO 中断触发。
使用交叉编译工具编译应用程序,如下所示:
在这里插入图片描述

在开发板上测试

前面我们编写了3 个测试程序,并编译得到了对应的可执行文件,本小节一个一个进行测试。在测试之前,选择一个测试引脚,这里笔者以板子上的GPIO1_IO01 引脚为例,该引脚在底板上已经引出,如下所示:
在这里插入图片描述
Mini 开发板可以通过背面丝印标注的名称或原理图进行确认。

GPIO 输出测试

将示例代码16.2.1 编译的到的可执行文件拷贝到开发板Linux 系统用户家目录下,执行该应用程序控制开发板上的GPIO1_IO01 引脚输出高或低电平:

./testApp 1 1 		#控制GPIO1_IO01 输出高电平
./testApp 1 0 		#控制GPIO1_IO01 输出低电平

在这里插入图片描述
执行相应的命令后,可以使用万用表或者连接一个LED 小灯进行检验,以验证实验结果!

GPIO 输入测试

将示例代码16.3.1 编译的到的可执行文件拷贝到开发板Linux 系统用户家目录下,执行该应用程序以读取GPIO1_IO01 引脚此时的电平状态,是高电平还是低电平?
首先通过杜邦线将GPIO1_IO01 引脚连接到板子上的3.3V 电源引脚上,接着执行命令读取GPIO 电平状态:
在这里插入图片描述
打印出的value 等于1,表示读取到GPIO 的电平确实是高电平;接着将GPIO1_IO01 引脚连接到板子上的GND 引脚上,执行命令:
在这里插入图片描述
打印出的value 等于0,表示读取到GPIO 的电平确实是低电平;测试结果与实际相符合!

GPIO 中断测试

将示例代码16.4.1 编译的到的可执行文件拷贝到开发板Linux 系统用户家目录下,执行该应用程序可以监测GPIO 的中断触发。
执行应用程序监测GPIO1_IO01 引脚的中断触发情况,如下所示:

./testApp 1 	# 监测GPIO1_IO01 引脚中断触发

在这里插入图片描述
当执行命令之后,我们可以使用杜邦线将GPIO1_IO01 引脚连接到GND 或3.3V 电源引脚上,来回切换,使得GPIO1_IO01 引脚的电平状态发生由高到低或由低到高的状态变化,以验证GPIO 中断的边沿触发情况;当发生中断时,终端将会打印相应的信息,如上图所示。

Tips:测试完成后按Ctrl+C 退出程序!

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

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

相关文章

【办公类05-03】Python批量修改文件名前面的序号(已有的序号错了,需要改成正确的号码)

背景需求下载教程&#xff0c;手动输入编号&#xff0c;有一个编号错误&#xff0c;导致后面所有编号都错了。30实际是29&#xff0c;以此类推怎样才能快速修改编号数字&#xff1f;前期考虑到可能要改编号&#xff0c;所以在每个编号后面加“ ”&#xff08;空格&#xff09;&…

python版协同过滤算法图书管理系统

基于协同过滤算法的图书管理系统 一、简介&#xff08;v信&#xff1a;1257309054&#xff09; ​ 本系统基于推荐算法给用户实现精准推荐图书。 ​ 根据用户对物品或者信息的偏好&#xff0c;发现物品或者内容本身的相关性&#xff0c;或者是发现用户的相关性&#xff0c;然…

Typora上传文档图片链接失效的问题+PicGo布置图床在Github

文章目录typora图片链接失效原因PicGO开源图床布置先配置Github2.1先创建新仓库、用于存放图片2.2生成一个token&#xff0c;用picGo访问github3.下载picGo,并进行配置3.1 配置v4.1typora图片链接失效原因 因为你是保存在本地的&#xff0c;因此图片是不能访问&#xff0c;可以…

laravel 邮件发送

配置 Laravel 的邮件服务可以通过 config/mail.php 配置文件进行配置。 邮件中的每一项都在配置文件中有单独的配置项&#xff0c;甚至是独有的「传输方式」&#xff0c;允许你的应用使用不同的邮件服务发送邮件 mailers > [smtp > [transport > smtp,host > env(M…

【超级猜图案例上半部分的实现 Objective-C语言】

一、超级猜图这么一个案例: 1.实现之后的效果是这样的: 1)中间有一个图片,点一下,能放大,背景变半透明的黑色: 2)再点一下图片,或者点周围黑色的阴影,图片回归原状, 3)右边有一个“大图”按钮,点一下,实现跟点图片一样的效果, 4)左边有一个“提示”按钮,点…

【Java学习笔记】4.Java 对象和类

前言 本章介绍Java的对象和类。 Java 对象和类 Java作为一种面向对象语言。支持以下基本概念&#xff1a; 多态继承封装抽象类对象实例方法重载 本节我们重点研究对象和类的概念。 对象&#xff1a;对象是类的一个实例&#xff08;对象不是找个女朋友&#xff09;&#x…

为什么人们宁可用Lombok,也不把成员设为public?

目录专栏导读一、从零了解JavaBean1、基本概念2、JavaBean的特征3、JavaBean的优点二、定义最简单的JavaBean三、思考一个问题&#xff0c;为何属性是private&#xff0c;然后用get/set方法&#xff1f;四、下面系统的分析以下&#xff0c;why?五、不和谐的声音&#xff0c;禁…

MySQL实战解析底层---行锁功过:怎么减少行锁对性能的影响

目录 前言 从两阶段锁说起 死锁和死锁检测 前言 MySQL 的行锁是在引擎层由各个引擎自己实现的但并不是所有的引擎都支持行锁&#xff0c;比如MyISAM 引擎就不支持行锁不支持行锁意味着并发控制只能使用表锁&#xff0c;对于这种引擎的表&#xff0c;同一张表上任何时刻只能有…

[深入理解SSD系列综述 1.5] SSD固态硬盘参数图文解析_选购固态硬盘就像买衣服?

版权声明&#xff1a;付费作品&#xff0c;未经许可&#xff0c;不可转载前言SSD &#xff08;Solid State Drive&#xff09;&#xff0c;即固态硬盘&#xff0c;通常是一种以半导体闪存&#xff08;NAND Flash&#xff09;作为介质的存储设备。SSD 以半导体作为介质存储数据&…

Python进阶-----面对对象4.0(面对对象三大特征之--继承)

目录 前言&#xff1a; Python的继承简介 1.什么是继承 2.继承的好处 3.object类 继承的相关用法 1.继承的定义与法则 2.对继承的重写 3.&#xff08;单继承&#xff09;多层继承 4.多继承 5.多继承重写时调用父类方法 前言&#xff1a; 在讲之前&#xff0c;我想说说中…

servlet注解开发

文章目录servlet注解开发内容回顾响应对象 HttpServletResponse重定向与请求转发ServletConfig简介案例ServletContext简介案例Servlet 注解开发简介注解使用案例WebServlet 注解详细参数综合的增删改查案例登录注册功能servlet注解开发 内容回顾 响应对象 HttpServletRespon…

推荐一个日历转换开源工具库,支持C#、Java、PHP等主流的语言

更多开源项目请查看&#xff1a;一个专注推荐.Net开源项目的榜单 日历对我们来说&#xff0c;最熟悉的就是阳历和农历&#xff0c;在中国每年都有固定的节日、节气、中国特有传统节日&#xff0c;有些节日是固定的&#xff0c;但是节气这些都需要我们经过一定规则换算出来。 所…

【JavaSE】数组的定义和使用(上)

数组的定义和使用&#xff08;上&#xff09;6-数组的定义与使用1. 数组的基本概念1.1 为什么要使用数组1.2 什么是数组1.3 数组的创建及初始化1.3.1 数组的创建1.3.2 数组的初始化1.4 数组的使用1.4.1 数组中元素的访问1.4.2 遍历数组2. 数组是引用类型2.1 初始JVM的内存分布2…

【Python - Matplotlib】P1 Matplotlib2D 快速入门

Matplotlib 2D什么是&#xff0c;为什么选择快速上手三层结构图像层结构一览图画图三步法补充画布设置设定图像的长宽以及清晰度代码将图片保存前言 本节为 Matplotlib 简单专题第一节&#xff0c;简单介绍 Matplotlib 的结构&#xff0c;画图三步法&#xff0c;以及介绍一个简…

认识Spring(上)

作者&#xff1a;~小明学编程 文章专栏&#xff1a;Spring框架 格言&#xff1a;热爱编程的&#xff0c;终将被编程所厚爱。 目录 什么是spring 什么是IOC 传统开发 IOC DI spring的创建使用 pom.xml spring.xml 取出bean对象 ApplicationContext BeanFactory App…

【NLP相关】PyTorch多GPU并行训练(DataParallel和DistributedDataParallel介绍、单机多卡和多机多卡案例展示)

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️&#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

@Transactional详解

一、事务的概念 百度百科&#xff1a; 事务&#xff08;Transaction&#xff09;&#xff0c;一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执 行单元(unit)。事务通常由高级数据库操纵语言或编程语言&#xff08;如SQL&#x…

第十四届蓝桥杯三月真题刷题训练——第 1 天

目录 题目1&#xff1a;数列求值 代码&#xff1a; 题目2&#xff1a;质数 代码&#xff1a; 题目3&#xff1a;饮料换购 代码&#xff1a; 题目1&#xff1a;数列求值 题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出…

vulnhub five86-1

总结:私钥登录&#xff0c;隐藏文件很多 目录 下载地址 漏洞分析 信息收集 网站渗透 爆破密码 提权 下载地址 Five86-1.zip (Size: 865 MB)Download (Mirror): https://download.vulnhub.com/five86/Five86-1.zip使用&#xff1a;下载以后打开压缩包&#xff0c;使用vm直…

数据结构(二)(嵌入式学习)

大 家 好 今天讲讲算法和哈希函数&#xff0c;数据结构基础请跳转数据结构&#xff08;一&#xff09; 数据结构干货总结&#xff08;二&#xff09;算法常见的数据结构及算法你以为我要都讲嘛&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#…