linux驱动和应用的数据交互ioctl函数和copy_from_user、copy_to_user

2023-11-13

一、应用程序中的ioctl接口

首先,我们需要规定一些命令码,这些命令码在应用程序和驱动程序中需要保持一致。应用程序只需向驱动程序下发一条指令码,用来通知它执行哪条命令。如何解读这条指令和怎么实现相关操作,就是驱动程序自己要做的事。
应用程序的接口函数为ioctl,参考官方文档,函数原型为

#include <sys/ioctl.h>
int ioctl(int fd, unsigned long request, ...);

下面我们解释各个参数的含义。
1)fd是文件描述符。当我们的设备作为特殊文件被open()函数打开后,会返回一个文件描述符,通过操作这个文件描述符达到操作设备文件的目的。
2)request是命令码,应用程序通过下发命令码来控制驱动程序完成对应操作。
3)第三个参数“…”是可变参数arg,一些情况下应用程序需要向驱动程序传参,参数就通过arg来传递。ioctl函数中的“…”只能传递一个参数,但内核不会检查这个参数的类型。那么,就有两种传参方式:只传一个整数,或者传递一个无符号类型指针。
如果ioctl执行成功,它的返回值就是驱动程序中ioctl接口给的返回值,驱动程序可以通过返回值向用户程序传参。但驱动程序最好返回一个非负数,因为用户程序中的ioctl运行失败时一定会返回-1并设置全局变量errorno。
errono不同的值代表的含义如下:
EBADF:fd是一个无效的文件描述符。
EFAULT:在arg是指针的前提下,argp指向一个不可访问的内存空间。
EINVAL:request或argp是无效的。
ENOTTY:fd没有关联到一个字符特殊设备,或该request不适用于文件描述符fd引用的对象类型。(说人话就是fd没有指向一个字符设备,或fd指向的文件不支持ioctl操作)
因此,在用户空间调用ioctl时,可以使用如下的错误判断处理。包括的两个头文件,string.h声明了strerror函数,errno.h定义了错误码errno。

#include <string.h>
#include <errno.h>

int ret;
ret = ioctl(fd, MYCMD);
if (ret == -1)
    printf("ioctl: %s\n", strerror(errno));

二、驱动程序中的ioctl接口
在驱动程序的ioctl函数体中,实现了一个switch-case结构,每一个case对应一个命令码,case内部是驱动程序实现该命令的相关操作。
ioctl的实现函数要传递给file_operations结构体中对应的函数指针,函数原型为

#include <linux/ioctl.h>
long (*unlocked_ioctl) (struct file * fp, unsigned int request, unsigned long args);
long (*compat_ioctl) (struct file * fp, unsigned int request, unsigned long args);

unlocked_ioctl在无大内核锁(BKL)的情况下调用。64位用户程序运行在64位的kernel,或32位的用户程序运行在32位的kernel上,都是调用unlocked_ioctl函数。
compat_ioctl是64位系统提供32位ioctl的兼容方法,也在无大内核锁的情况下调用。即如果是32位的用户程序调用64位的kernel,则会调用compat_ioctl。如果驱动程序没有实现compat_ioctl,则用户程序在执行ioctl时会返回错误Not a typewriter。
另外,如果32位用户态和64位内核态发生交互时,第三个参数的长度需要保持一致,否则交互协议会出错。

int (*ioctl) (struct inode *inode, struct file *fp, unsigned int request, unsigned long args);

在2.6.35.7及以前的内核版本中,file_operations还定义了ioctl()接口,与unlocked_ioctl是等价的。但是在2.6.36以后就不再支持这个接口,全部使用unlocked_ioctl了。
以上函数参数的含义如下。
1)inode和fp用来确定被操作的设备。
2)request就是用户程序下发的命令。
3)args就是用户程序在必要时传递的参数。
返回值:可以在函数体中随意定义返回值,这个返回值也会被直接返回到用户程序中。通常使用非负数表示正确的返回,而返回一个负数系统会判定为ioctl调用失败。

ioctl使用的简单实例——整数传参

本例中,我们让ioctl传递三个命令,分别是一个无参数、写参数、读参数三个指令。首先我们需要确定两个头文件,命名为ioctl_test.h和user_ioctl.h,用来分别定义内核空间和用户空间下的命令码协议。两个头文件中除了引用不同的头文件外,其他内容需要完全一致,以保证协议的一致性。

我们使用字符’a’作为幻数,三个命令的作用分别是用户程序让驱动程序打印一句话,用户程序从驱动程序读一个int型数,用户程序向驱动程序写一个int型数。
编写驱动程序ioctl_test.c。核心函数是demo_ioctl,使用一个switch-case完成用户程序下发的指令。

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include "ioctl_test.h"

MODULE_LICENSE("GPL");
MODULE_AUTHOR("zz");

#define CH36x_GET_IO_BASE_ADDR			0x00000001
#define CH36x_SET_IO_BASE_ADDR			0x00000002
#define CH36x_GET_MEM_BASE_ADDR			0x00000003
#define CH36x_SET_MEM_BASE_ADDR			0x00000004
#define CH36x_READ_CONFIG_BYTE			0x00000005
#define CH36x_WRITE_CONFIG_BYTE			0x00000006
#define CH36x_GET_INT_LINE				0x00000007
#define CH36x_SET_INT_LINE				0x00000008
#define CH36x_READ_IO_BYTE				0x00000009
#define CH36x_READ_IO_WORD				0x0000000a
#define CH36x_READ_IO_DWORD				0x0000000b
#define CH36x_WRITE_IO_BYTE				0x0000000c
#define CH36x_WRITE_IO_WORD				0x0000000d
#define CH36x_WRITE_IO_DWORD			0x0000000e
#define CH36x_READ_MEM_BYTE				0x0000000f
#define CH36x_READ_MEM_WORD				0x00000010
#define CH36x_READ_MEM_DWORD			0x00000011
#define CH36x_WRITE_MEM_BYTE			0x00000012
#define CH36x_WRITE_MEM_WORD			0x00000013
#define CH36x_WRITE_MEM_DWORD			0x00000014
#define CH36x_READ_MEM_BLOCK			0x00000015
#define CH36x_WRITE_MEM_BLOCK			0x00000016
#define CH36x_READ_IO_BLOCK				0x00000017
#define CH36x_WRITE_IO_BLOCK			0x00000018
#define CH36x_READ_CONFIG_WORD			0x00000019
#define CH36x_WRITE_CONFIG_WORD			0x0000001a
#define CH36x_READ_CONFIG_DWORD			0x0000001b
#define CH36x_WRITE_CONFIG_DWORD		0x0000001c
#define CH36x_ENABLE_INT				0x0000001d
#define CH36x_DISABLE_INT				0x0000001e
#define CH36x_GET_DRV_VERSION			0x000000ff

static dev_t devno;

static int demo_open(struct inode *ind, struct file *fp)
{
	printk("demo open\n");
	return 0;
}

static int demo_release(struct inode *ind, struct file *fp)
{
	printk("demo release\n");
	return 0;
}

static long demo_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
{
	int rc = 0;
	int arg_w;
	const int arg_r = 566;
	switch(cmd) {
		case CH36x_GET_IO_BASE_ADDR:
			printk("cmd 0: no argument.\n");
			rc = 0;
			break;
		case CH36x_READ_MEM_BLOCK:
			printk("cmd 1: ioc read, arg = %d.\n", arg_r);
			arg = arg_r;
			rc = 1;
			break;
		case CH36x_READ_CONFIG_WORD:
			arg_w = arg;
			printk("cmd 2: ioc write, arg = %d.\n", arg_w);
			rc = 2;
			break;
		default:
			pr_err("%s: invalid command.\n", __func__);
			return -ENOTTY;
	}
	return rc;
}

static struct file_operations fops = {
	.open = demo_open,
	.release = demo_release,
	.unlocked_ioctl = demo_ioctl,
};

static struct cdev cd;

static int demo_init(void)
{
	int rc;
	rc = alloc_chrdev_region(&devno, 0, 1, "test");
	if(rc < 0) {
		pr_err("alloc_chrdev_region failed!");
		return rc;
	}
	printk("MAJOR is %d\n", MAJOR(devno));
	printk("MINOR is %d\n", MINOR(devno));

	cdev_init(&cd, &fops);
	rc = cdev_add(&cd, devno, 1);
	if (rc < 0) {
		pr_err("cdev_add failed!");
		return rc;
	}
	return 0;
}

static void demo_exit(void)
{
	cdev_del(&cd);
	unregister_chrdev_region(devno, 1);
	return;
}

module_init(demo_init);
module_exit(demo_exit);

编写用户程序user_ioctl.c,主要作用就是打开设备节点,依次下发三条指令,打印参数和ioctl的返回值,关闭设备节点。

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include "user_ioctl.h"

int main()
{
	int rc;
	int arg_r;
	const int arg_w = 233;
	int fd = open("/dev/test_chr_dev", O_RDWR);
	if (fd < 0) {
		printf("open file failed!\n");
		return -1;
	}

	rc = ioctl(fd, CH36x_GET_IO_BASE_ADDR);
	printf("rc = %d.\n", rc);

	rc = ioctl(fd, CH36x_READ_MEM_BLOCK, arg_r);
	printf("ioc read arg = %d, rc = %d.\n", arg_r, rc);

	rc = ioctl(fd, CH36x_READ_CONFIG_WORD, arg_w);
	printf("ioc write arg = %d, rc = %d.\n", arg_w, rc);

	close(fd);
	return 0;
}

编写Makefile。

ifneq ($(KERNELRELEASE),)
	obj-m := ioctl_test.o
else
	KDIR    := /lib/modules/$(shell uname -r)/build
	PWD     := $(shell pwd)
all:
	make -C $(KDIR) M=$(PWD) modules
	gcc user_ioctl.c -o user
clean:
	make -C $(KDIR) M=$(PWD) clean
	rm -rf user
endif

用户层和内核层传递复杂参数

上面的实例只在用户程序和驱动程序中传递了一个简单的整形参数。实际使用中我们可能需要传递更复杂的参数,或者传递多个参数,这时我们就只能传递参数的地址,或者将多个参数打包成一个结构体再传递该结构体的地址。

但是请注意,在Linux系统中,用户空间和内核空间之间是相互隔离开的。驱动程序运行在内核空间中,给出的地址也是在内核空间中的地址,运行在用户空间下的用户程序即使拿到这个地址,也不能访问内核空间。这时,我们需要使用到copy_to_user()函数,将要传递的内容从内核空间拷贝到用户空间,用户程序再访问用户空间中的该内容即可。
(1)内核地址空间和驱动地址空间是隔绝的,不能使用memcpy()函数,必须使用专门的拷贝函数;
(2)在拷贝大量数据时使用copy_to_user()和copy_from_user()函数,拷贝单个数据时,比如某个int型变量,则优先使用put_user()和get_user()函数;

copy_to_user函数的原型如下。

unsigned long copy_to_user(void *to, const void *from, unsigned long n)

参数含义:
1)to:目标地址(用户空间)
2)from:源地址(内核空间)
3)n:需要拷贝的数据的字节数
返回值:成功返回0,失败返回没有拷贝成功的数据字节数。
同理,也有从用户空间向内核空间拷贝的函数copy_from_user(),原型如下。

unsigned long copy_from_user(void *to, const void *from, unsigned long n)

参数含义:
1)to:目标地址(内核空间)
2)from:源地址(用户空间)
3)n:需要拷贝的数据的字节数
返回值:成功返回0,失败返回没有拷贝成功的数据字节数。
下面举个实例,来详细介绍如何在用户空间和内核空间中通过传递地址参数的方法来传递复杂参数。这里我们传递两个参数char arg1和int arg2,将这两个参数打包进一个结构体struct IOC_ARGS中。这个结构体在用户程序和驱动程序中也需要保持一致。
同样我们还需要定义用户程序和驱动程序之间命令码,我们定义两个命令码,分别用来读参数和写参数。
用户程序的头文件user_ioctl.h
用户程序user_ioctl.c。

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include "user_ioctl.h"

int main()
{
	int rc;
	struct IOC_ARGS args_r;
	struct IOC_ARGS args_w = {'u', 233};
	int fd = open("/dev/test_chr_dev", O_RDWR);

	rc = ioctl(fd, CMD_IOC_0, &args_r);
	if (rc < 0)
		printf("ioctl: %s\n", strerror(errno));
	else
		printf("ioc read arg1 = %c, arg2 = %d.\n", args_r.arg1, args_r.arg2);

	rc = ioctl(fd, CMD_IOC_1, &args_w);
	if (rc < 0)
		printf("ioctl: %s\n", strerror(errno));
	else
		printf("ioc write arg1 = %c, arg2 = %d.\n", args_w.arg1, args_w.arg2);

	close(fd);
	return 0;
}
内核驱动程序ioctl_test.c。

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include "ioctl_test.h"

MODULE_LICENSE("GPL");
MODULE_AUTHOR("zz");

static dev_t devno;

static int demo_open(struct inode *ind, struct file *fp)
{
	printk("demo open\n");
	return 0;
}

static int demo_release(struct inode *ind, struct file *fp)
{
	printk("demo release\n");
	return 0;
}

static long demo_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
{
	int rc = 0;
	struct IOC_ARGS args_r = {'k', 566};
	struct IOC_ARGS args_w;
	if (_IOC_TYPE(cmd) != CMD_IOC_MAGIC) {
		pr_err("%s: command type [%c] error.\n", __func__, _IOC_TYPE(cmd));
		return -ENOTTY;
	}

	switch(cmd) {
		case CMD_IOC_0:
			rc = copy_to_user((char __user *)arg, &args_r, sizeof(IOC_ARGS));
			if (rc) {
				pr_err("%s: copy_to_user failed", __func__);
				return rc;
			}
			printk("%s: ioc read arg1 = %c, arg2 = %d", __func__, args_r.arg1, args_r.arg2);
			break;
			break;
		case CMD_IOC_1:
			rc = copy_from_user(&args_w, (char __user *)arg, sizeof(IOC_ARGS));
			if (rc) {
				pr_err("%s: copy_from_user failed", __func__);
				return rc;
			}
			printk("%s: ioc write arg1 = %c, arg2 = %d", __func__, args_w.arg1, args_w.arg2);
			break;
		default:
			pr_err("%s: invalid command.\n", __func__);
			return -ENOTTY;
	}
	return rc;
}

static struct file_operations fops = {
	.open = demo_open,
	.release = demo_release,
	.unlocked_ioctl = demo_ioctl,
};

static struct cdev cd;

static int demo_init(void)
{
	int rc;
	rc = alloc_chrdev_region(&devno, 0, 1, "test");
	if(rc < 0) {
		pr_err("alloc_chrdev_region failed!");
		return rc;
	}
	printk("MAJOR is %d\n", MAJOR(devno));
	printk("MINOR is %d\n", MINOR(devno));

	cdev_init(&cd, &fops);
	rc = cdev_add(&cd, devno, 1);
	if (rc < 0) {
		pr_err("cdev_add failed!");
		return rc;
	}
	return 0;
}

static void demo_exit(void)
{
	cdev_del(&cd);
	unregister_chrdev_region(devno, 1);
	return;
}

module_init(demo_init);
module_exit(demo_exit);

除此之外,还有put_user()函数和get_usr()函数,在用户层和内核层拷贝单个数据时,比如某个int型变量,则优先使用put_user()和get_user()函数;使用方法和copy_from_user,copy_to_user差不多

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux驱动和应用的数据交互ioctl函数和copy_from_user、copy_to_user 的相关文章

  • Flex 的远程版本误解了我的规则

    我使用 flex 和 bison 编写了一个小汇编程序 可以在我的机器 ubuntu 10 10 上构建并运行正常 现在其他人正在尝试在 arch linux 上构建它 并且他们安装的 flex 产生了不同的 lex yy c 这是不匹配的
  • “./somescript.sh”和“. ./somescript.sh”有什么区别

    今天我按照一些说明在 Linux 中安装软件 有一个需要首先运行的脚本 它设置一些环境变量 指令告诉我执行 setup sh 但是我执行时犯了一个错误 setup sh 所以环境没有设置 最后我注意到了这一点并继续进行 我想知道这两种调用脚
  • php56 - CentOS - Remi 仓库

    我刚刚在测试盒上安装了 php 5 6 正常的 cli php 解释器似乎不存在 gt php v bash php command not found gt php56 v PHP 5 6 13 cli built Sep 3 2015
  • 如何从 Linux 命令行确定 LCD 显示器是否打开

    如何通过 Linux 命令行判断计算机的显示器是否打开 关闭 我传统上认为显示器是仅输出的设备 但我注意到 Gnome 显示器首选项对话框具有 检测显示器 功能 这可以推广到确定显示器是否物理关闭吗 VESA DDC 连接是I2C http
  • 我们可以在 Bash 脚本中使用 PHP 吗?

    我有一个 bash 脚本abcd sh bin sh for i in seq 8 do ssh w i uptime ps elf grep httpd wc l free m mpstat done pid sleep 1 kill 9
  • 期待、互动,然后再次期待

    有几篇关于相同内容的帖子 但我仍然无法使我的期望脚本正常工作 我的目的是自动化一切 但保留用户输入的密码 所以脚本有 3 个部分 自动登录 给予用户交互以输入密码 将控制权交还给 Expect 脚本以继续工作 所以我有一个将生成的脚本 其中
  • 如何从外部模块导出符号?

    我在内核源代码树之外进行编码 有两个模块 第一个printt有一个功能printtty 将字符串打印到当前 tty 以及第二个模块hello这会调用printtty 在初始化期间 我已经添加了EXPORT SYMBOL printtty 在
  • 为什么“script”命令会生成 ^[ 和 ^M 字符以及如何使用 vim 搜索和替换删除它们?

    在linux上 使用bash shell 当我使用script命令时 生成的文件称为typescript 当我用 vim 打开该文件时 每一行都包含 M字符 并且有几行 由于我的彩色命令提示符 包含一个字符 我想用任何东西替换这些字符 从而
  • 将 bash 脚本作为守护进程运行

    我有一个脚本 它每 X 次运行我的 PHP 脚本 bin bash while true do usr bin php f my script php echo Waiting sleep 3 done 我怎样才能将它作为守护进程启动 要从
  • 为什么 proc/ID/maps 有多个共享库条目

    我正在查看嵌入式Linux下的proc ID maps 我注意到一些共享库在进程的内存映射中出现了几次 为什么会这样呢 40094000 400d9000 r xp 00000000 b3 09 723 system lib libc so
  • 如何从命令行执行 PHP 代码?

    我想执行单个 PHP 语句 例如if function exists my func echo function exists 直接使用命令行 无需使用单独的 PHP 文件 这怎么可能 如果您要在命令行中执行 PHP 我建议您安装phpsh
  • X 服务器使用什么像素格式?

    X 服务器使用什么像素格式 RGBA ARBG BGRA 如果有任何特定格式的话 Update 我专门寻找有关颜色分量顺序和位模式的信息 你的意思是帧缓冲区格式 或者所有支持的像素图格式 无论是哪一种 都取决于您的图形硬件 驱动程序和配置
  • _dl_runtime_resolve -- 共享对象何时加载到内存中?

    我们有一个对性能要求很高的消息处理系统 最近我们注意到第一条消息比后续消息花费的时间要长很多倍 当它通过我们的系统时 会发生大量转换和消息增强 其中大部分是通过外部库完成的 我刚刚描述了这个问题 使用 callgrind 将仅一条消息的 运
  • OS X 对 /usr/local/lib 的权限被拒绝

    我正在寻找有关权限问题的任何建议 直觉 线索 答案 自从我切换到新的 Macbook Pro 以来 这个问题一直困扰着我 这就是困境 某些程序在安装期间复制 usr local lib 下的库 并且在运行这些程序时出现崩溃 我认为这与此文件
  • 我如何知道用户在使用 ncurses (Linux) 的控制台中按下了 ESC 键?

    I have a problem in detecting whether I just got a plain ESC key just code 27 or whether it was another special key such
  • 如何在树莓派上更新到最新的 python 3.5.1 版本?

    我昨天拿到了 Raspberry Pi 我已经在尝试用它来编写代码了 我有一个计划在其上运行的程序 但它仅与 Python 版本 3 5 0 或 3 5 1 兼容 并且我在互联网上找到的所有内容似乎都已经过时 与 Python 2 有关 或
  • 在 4.x 内核上的 64 位内存中查找系统调用表

    我正在尝试编写一个简单的内核模块来查找 Linux 中的 sys call table 但遇到了一些麻烦 我在这里找到了 32 位 Linux 的基本指南 https memset wordpress com 2011 03 18 sysc
  • Python 线程与 Linux 中的多处理

    基于此question https stackoverflow com questions 807506 threads vs processes in linux我假设创建新流程应该几乎和创造新线程在Linux中 然而 很少的测试显示出截
  • 如何使用 shell 脚本解压所有 .tar.gz?

    我试过这个 DIR path tar gz if ls A DIR 2 gt dev null then echo not gz else tar zxvf path tar gz C path tar fi 如果该文件夹有一个 tar 则
  • 如何将字符串推送到标准输入?在启动时通过 stdin 提供输入,然后以交互方式读取 stdin 输入 [重复]

    这个问题在这里已经有答案了 有没有办法在调用程序时将字符串 推送 到程序的标准输入流 这样我们就可以达到这样的效果 echo something my program 但不是在之后读取 EOF something my program将从原

随机推荐

  • 机器学习——SVM之python实现数据样本标准化和归一化

    目录 一 标准化和归一化的目的 1 标准化 2 归一化 二 标准化和归一化常用的理论公式 1 归一化 2 标准化 三 python实现SVM样本数据标准化和归一化 1 标准化 2 归一化 本文源代码 机器学习 支持向量机SVM之python
  • Python基础知识

    基础知识 基础知识包括输入输出 变量 数据类型 表达式 运算符这5个方面 1 输入输出 Python有很多函数 后面我们会细讲 但这里先将两个最基本的函数 输入和输出 输出函数print 在前面我们已经用过了 语法就是 print 要输出的
  • 前端案例——轮播图的实现(定时切换图片)

    显示效果为 主页图片每三秒更换一次
  • Windows平台安装GDB调试器

    首先我们需要知道GDB 调试器无法直接安装到 Windows 平台上 如果想在 Windows 系统中使用 GDB 调试器 需要一个中间媒介 常用的就是 MinGW MinGw 全称 Minimalist GNU for Windows 作
  • 关于Keil打开未响应卡死的问题

    跟同事经常互传一些keil工程 由于两人之间的keil的版本不一致 他的keil5 我的keil4 导致我给他的keil4工程他能打开 他给我的keil5工程我用keil4打开就卡死 究其原因是跟工程同目录下的 同名 uvopt文件导致的
  • 例说数据结构&STL(十)——hash_set/unordered_set

    1 白话hash set unordered set 这一章节 我们来了解两个新的结构体hash set和unorderd set 我将这两者放在一个博文中介绍是因为它们都属于基于哈希表 hash table 构建的数据结构 并且是关键字与
  • Apache Archiva 任意目录删除(CVE-2022-40309) 和 任意文件读取(CVE-2022-40308)

    声明 出品 先知社区 ID l3yx 以下内容 来自先知社区的l3yx作者原创 由于传播 利用此文所提供的信息而造成的任何直接或间接的后果和损失 均由使用者本人负责 长白山攻防实验室以及文章作者不承担任何责任 CVE 2022 40309
  • Git删除远端最后一次提交

    git log 查看提交历史 找到最后一次提交之前的commit id 执行git reset回退本地代码到正确的代码版本 git reset hard 版本号 如果是回到最后一条的前一条 用 git reset hard HEAD 强制推
  • VR头显Unity下如何实现毫秒级延迟的RTMP或RTSP播放?

    技术背景 虚拟现实 VR 技术的互动性和沉浸感 为我们提供了一种全新的视觉体验 不过 如果需要实现真正的沉浸式体验 VR播放的延迟问题非常重要 好多VR场景下 如果存在延迟 用户在移动头部时可能会感觉到画面反应不及时 导致影响视频的流畅度
  • Android开发--实现Android登录注册页面(下)

    前面我们已经完成了登录注册页面的布局 下面我们实现验证登录和记住密码的功能 我们这里还没用到数据库 所以我们的验证的账号密码 是写死的 首先进入登录页面 可以从这里跳转到注册页面 注册成功后 账号密码的输入框会自动获取刚刚注册的账号密码 无
  • MySQL处理大量数据的一些方法

    一 复刻一张表的数据到另一张表 结构相同 从当前表查询所有数据到快照表 注 快照表只比当前表多一个快照时间字段CKTIME 由于使用框架查询出来之后再插入到快照表会牺牲掉很大性能 所以直接采用sql脚本的方式将数据迁移到快快照表 SQL如下
  • DVWA的安装教程和通关详解

    DVWA的安装教程和通关详解 目录 一 环境搭建 1 下载和安装phpstudy 2 DVWA下载 3 DVWA安装 更改配置信息 解决爆红错误 二 Brute Force 1 LOW级别 2 Medium级别 3 High级别 三 Com
  • 生物统计学

    多元回归与相关 一元回归是因变量Y在一个自变量X上的回归 它仅仅涉及到两个变量的关系问题 多元回归 multiple regress 一个变量 因变量 对其他两个或两个以上变量 自变量 的线性回归关系 若因变量Y同时受到m个自变量X1 X2
  • Linux 快速定位日志 排查bug命令 实用性100%

    当项目中有异常 我么你只知道关键日志 要从服务器上一个老大的日志文件中找到那一行可以使用如下命令 cat app log grep n abc cat app log 打开app log日志文件 管道符 意思是把上一个命令的内容用于下一个命
  • PyTorch torch.optim.lr_scheduler 学习率设置 调参-- CyclicLR

    torch optim lr scheduler 学习率设置 CyclicLR 学习率的参数调整是深度学习中一个非常重要的一项 Andrew NG 吴恩达 认为一般如果想调参数 第一个一般就是学习率 作者初步学习者 有错误直接提出 热烈欢迎
  • 蓝桥杯备赛---------跳蚱蜢

    一 题目描述 如下图所示 有 9 只盘子 排成 1 个圆圈 其中 8 只盘子内装着 8 只蚱蜢 有一个是空盘 我们把这些蚱蜢顺时针编号为 1 8 每只蚱蜢都可以跳到相邻的空盘中 也可以再用点力 越过一个相邻的蚱蜢跳到空盘中 请你计算一下 如
  • HttpServletRequest 各种方法总结

    HttpServletRequest HttpServletRequest对象代表客户端的请求 当客户端通过HTTP协议访问服务器时 HTTP请求头中的所有信息都封装在这个对象中 开发人员通过这个对象的方法 可以获得客户这些信息 reque
  • JVM各个垃圾收集器区别

    默认收集器 jdk1 7 Parallel Scavenge 新生代 Parallel Old 老年代 jdk1 8 Parallel Scavenge 新生代 Parallel Old 老年代 jdk1 9 G1 虚拟机启动检测主机是否为
  • java实现websocket握手协议

    String str new String data CHARSET String arr str split r n String temp arr 0 split Map
  • linux驱动和应用的数据交互ioctl函数和copy_from_user、copy_to_user

    一 应用程序中的ioctl接口 首先 我们需要规定一些命令码 这些命令码在应用程序和驱动程序中需要保持一致 应用程序只需向驱动程序下发一条指令码 用来通知它执行哪条命令 如何解读这条指令和怎么实现相关操作 就是驱动程序自己要做的事 应用程序