Tiny6410 LED字符设备驱动
1.查看用户手册
led1、led2、led3、led4 连接的分别是 GPK4、GPK5、GPK6、GPK7
2、查询6410芯片手册
下面还需要3个步骤:
1、设置GPIO为OUTPUT。
将GPK4、GPK5、GPK6、GPK7设置为输出output=0001
即GPKCON0的19:28都配置为0001
2、设置GPIO的数据。
将GPKDATA的4:7位赋值为0
3、设置GPKUP为上拉。
将GPKUP的4:7位设置为10
3、代码
led_driver.c
- #include <linux/module.h> /*它定义了模块的 API、类型和宏(MODULE_LICENSE、MODULE_AUTHOR等等),所有的内核模块都必须包含这个头文件。*/
- #include <linux/kernel.h> /*使用内核信息优先级时要包含这个文件,一般在使用printk函数时使用到优先级信息*/
- #include <linux/fs.h>
- #include <asm/uaccess.h> /* copy_to_user,copy_from_user */
- #include <linux/pci.h> /*readl writel*/
- #include <mach/map.h>
- #include <mach/regs-gpio.h>
- #include <mach/gpio-bank-k.h>
- #define LED_MAJOR 243
- #define LED_ON 1
- #define LED_OFF 0
- #define LED_1_ON 2
- #define LED_1_OFF 3
- #define LED_2_ON 4
- #define LED_2_OFF 5
- #define LED_3_ON 6
- #define LED_3_OFF 7
- #define LED_4_ON 8
- #define LED_4_OFF 9
- static int led_open (struct inode *inode,struct file *filp)
- {
- unsigned tmp;
- tmp = readl(S3C64XX_GPKCON);
- tmp = (tmp&0x0000ffff)| 0x1111ffff;
- writel(tmp, S3C64XX_GPKCON);
- printk("#########open######\n");
- return 0;
- }
- static int led_read (struct file *filp, char __user *buf, size_t count,loff_t *f_pos)
- {
- return count;
- }
- static int led_write (struct file *filp, const char __user *buf, size_t count,loff_t *f_pos)
- {
- char wbuf[10];
- unsigned tmp;
- if(copy_from_user(wbuf,buf,count))
- return -EFAULT;
- switch(wbuf[0])
- {
- case LED_ON:
- tmp = readl(S3C64XX_GPKDAT);
- tmp &= (0x0f);
- writel(tmp, S3C64XX_GPKDAT);
- printk("turn on!\n");
- break;
- case LED_OFF:
- tmp = readl(S3C64XX_GPKDAT);
- tmp |= (0xf0);
- writel(tmp, S3C64XX_GPKDAT);
- printk("turn off!\n");
- break;
- case LED_1_ON:
- tmp = readl(S3C64XX_GPKDAT);
- tmp &= (0xef);
- writel(tmp, S3C64XX_GPKDAT);
- printk("turn off!\n");
- break;
- case LED_1_OFF:
- tmp = readl(S3C64XX_GPKDAT);
- tmp |= (0xf0);
- writel(tmp, S3C64XX_GPKDAT);
- printk("turn on!\n");
- break;
- case LED_2_ON:
- tmp = readl(S3C64XX_GPKDAT);
- tmp &= (0xdf);
- writel(tmp, S3C64XX_GPKDAT);
- printk("turn off!\n");
- break;
- case LED_2_OFF:
- tmp = readl(S3C64XX_GPKDAT);
- tmp |= (0xf0);
- writel(tmp, S3C64XX_GPKDAT);
- printk("turn on!\n");
- break;
- case LED_3_ON:
- tmp = readl(S3C64XX_GPKDAT);
- tmp &= (0xbf);
- writel(tmp, S3C64XX_GPKDAT);
- printk("turn off!\n");
- break;
- case LED_3_OFF:
- tmp = readl(S3C64XX_GPKDAT);
- tmp |= (0xf0);
- writel(tmp, S3C64XX_GPKDAT);
- printk("turn on!\n");
- break;
- case LED_4_ON:
- tmp = readl(S3C64XX_GPKDAT);
- tmp &= (0x7f);
- writel(tmp, S3C64XX_GPKDAT);
- printk("turn off!\n");
- break;
- case LED_4_OFF:
- tmp = readl(S3C64XX_GPKDAT);
- tmp |= (0xf0);
- writel(tmp, S3C64XX_GPKDAT);
- printk("turn on!\n");
- break;
- default :
- break;
- }
- return 0;
- }
- int led_release (struct inode *inode, struct file *filp)
- {
- printk("#########release######\n");
- return 0;
- }
- struct file_operations led_fops =
- {
- .owner = THIS_MODULE,
- .open = led_open,
- .read = led_read,
- .write = led_write,
- .release = led_release,
- };
- int __init led_init (void)
- {
- int rc;
- printk ("Test led dev\n");
- rc = register_chrdev(LED_MAJOR,"led",&led_fops);
- if (rc <0)
- {
- printk ("register %s char dev error\n","led");
- return -1;
- }
- printk ("ok!\n");
- return 0;
- }
- void __exit led_exit (void)
- {
- unregister_chrdev(LED_MAJOR,"led");
- printk ("module exit\n");
- return ;
- }
- module_init(led_init);
- module_exit(led_exit);
Makefile
- obj-m := led_driver.o
- KDIR :=/home/workdir/kernel/linux-2.6.38
- all:
- make -C $(KDIR) M=$(shell pwd) modules
- install:
- cp driver_led.ko /tftpboot/
- clean:
- make -C $(KDIR) M=$(shell pwd) clean
测试文件
test_led.c
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #define LED_OFF 0
- #define LED_ON 1
- #define LED_1_ON 2
- #define LED_1_OFF 3
- #define LED_2_ON 4
- #define LED_2_OFF 5
- #define LED_3_ON 6
- #define LED_3_OFF 7
- #define LED_4_ON 8
- #define LED_4_OFF 9
- int main (void)
- {
- int i=0;
- int fd;
- char buf[10]={
- LED_ON , LED_OFF ,
- LED_1_ON, LED_1_OFF,
- LED_2_ON, LED_2_OFF,
- LED_3_ON, LED_3_OFF,
- LED_4_ON, LED_4_OFF,
- };
- fd = open("/dev/led",O_RDWR);
- if (fd < 0)
- {
- printf ("Open /dev/led file error\n");
- return -1;
- }
- while(i<10)
- {
- write(fd,&buf[i],4);
- sleep(1);
- i++;
- }
- close (fd);
- return 0;
- }
上述编译没有问题,就可以下到板子测试了。
加载驱动 insmod led_driver.ko
创建设备文件 mknod /dev/led c 243 0 其中243要跟驱动文件中的设备号一致
运行测试文件 ./test_led
完成。
------------------------------------------------------------------------------------------
参考资料:
#include <linux/module.h>/*它定义了模块的 API、类型和宏(MODULE_LICENSE、MODULE_AUTHOR等等),所有的内核模块都必须包含这个头文件。/
#include <linux/kernel.h>/*使用内核信息优先级时要包含这个文件,一般在使用printk函数时使用到优先级信息*/
#include <linux/init.h>//头文件:module_init、module_exit等宏定义。
#include <linux/fs.h>////struct file_operations
#include <asm/irq.h>
#include <mach/regs-gpio.h>// S3C2410 GPIO寄存器定义
#include <mach/hardware.h>// s3c2410_gpio_setpin, s3c2410_gpio_cfgpin等
#include <linux/device.h>//class_create device_create(注意,有些2.6.27以前是的可能是class_device_create,如果出现implicate 错误时,看一下这个头问题里边是哪一个),udev,自动在/dev下创建设备节点
#include <linux/cdev.h>//字符设备节点注册,函数有cdev_init,cdev_add,cdev_del等早期的办法是register_chrdev,unregister_chrdev这种方法应避免使用。
#define DEVICE_NAME "leds" /* 加载模式后,执行”cat /proc/devices”命令看到的设备名称 */
#define LED_MAJOR 231 /* 主设备号 */
/* 应用程序执行ioctl(fd, cmd, arg)时的第2个参数 */
#define IOCTL_LED_ON 1
#define IOCTL_LED_OFF 0
/* 用来指定LED所用的GPIO引脚 */
static unsigned long led_table [] =
{
S3C2410_GPB5,
S3C2410_GPB6,
S3C2410_GPB7,
S3C2410_GPB8,
};
/* 用来指定GPIO引脚的功能:输出 */
static unsigned int led_cfg_table [] =
{
S3C2410_GPB5_OUTP,
S3C2410_GPB6_OUTP,
S3C2410_GPB7_OUTP,
S3C2410_GPB8_OUTP,
};
struct leds_type
{
struct cdev cdev;
};
struct leds_type *my_leds_dev;
/* 应用程序对设备文件/dev/EmbedSky-leds执行open(...)时,
* 就会调用EmbedSky_leds_open函数
*/
static int EmbedSky_leds_open(struct inode *inode, struct file *file)
{
int i;
for (i = 0; i < 4; i++)
{
// 设置GPIO引脚的功能:本驱动中LED所涉及的GPIO引脚设为输出功能
s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);
}
return 0;
}
/* 应用程序对设备文件/dev/EmbedSky-leds执行ioclt(...)时,
* 就会调用EmbedSky_leds_ioctl函数
*/
static int EmbedSky_leds_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
if (arg > 4)
{
return -EINVAL;
}
switch(cmd)
{
case IOCTL_LED_ON:
// 设置指定引脚的输出电平为0
s3c2410_gpio_setpin(led_table[arg], 0);
return 0;
case IOCTL_LED_OFF:
// 设置指定引脚的输出电平为1
s3c2410_gpio_setpin(led_table[arg], 1);
return 0;
default:
return -EINVAL;
}
}
/* 这个结构是字符设备驱动程序的核心
* 当应用程序操作设备文件时所调用的open、read、write等函数,
* 最终会调用这个结构中指定的对应函数
*/
static struct file_operations EmbedSky_leds_fops =
{
.owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
.open = EmbedSky_leds_open,
.ioctl = EmbedSky_leds_ioctl,
};
static char __initdata banner[] = "TQ2440/SKY2440 LEDS, (c) 2008,2009 www.embedsky.net/n";
static struct class *led_class;
/*
* 执行“insmod EmbedSky_leds.ko”命令时就会调用这个函数
*/
static int __init EmbedSky_leds_init(void)
{
int ret;
dev_t devno=MKDEV(LED_MAJOR,0);
printk("init led/n");
printk(banner);
/* 注册字符设备驱动程序
* 参数为主设备号、设备名字、file_operations结构;
* 这样,主设备号就和具体的file_operations结构联系起来了,
* 操作主设备为LED_MAJOR的设备文件时,就会调用EmbedSky_leds_fops中的相关成员函数
ret = register_chrdev_region(devno, 1,DEVICE_NAME);//获得设备编号
my_leds_dev=kmalloc(sizeof(struct leds_type),GFP_KERNEL);
/*这个必须有不然会在加载模块时出现Unable to handle kernel NULL pointer dereference at virtual addres 00000000 错误,这是由于在这里my_leds_dev仅仅是个指针,没有相应大小的分配内存,所以使用时会出错,,,寻找这个错误是比较麻烦的*/
if(!my_leds_dev)
{
ret=-ENOMEM;
goto fail_malloc;
}
memset(my_leds_dev,0,sizeof(struct leds_type));
cdev_init(&(my_leds_dev->cdev),&EmbedSky_leds_fops);
ret=cdev_add(&(my_leds_dev->cdev),devno,1);
/*注意:与早期的设备注册方法不同,早期的直接register_chrdev()就可以,*/
if(ret)printk(KERN_NOTICE"ERROR %d",ret);
//注册一个类,使mdev可以在"/dev/"目录下面建立设备节点
led_class = class_create(THIS_MODULE, DEVICE_NAME);
if(IS_ERR(led_class))
{
printk("Err: failed in EmbedSky-leds class. /n");
return -1;
}
//创建一个设备节点,节点名为DEVICE_NAME
device_create(led_class, NULL, MKDEV(LED_MAJOR, 0), NULL, DEVICE_NAME);
printk(DEVICE_NAME " initialized/n");
return 0;
fail_malloc: unregister_chrdev_region(devno,1);
return ret;
}
/*
* 执行”rmmod EmbedSky_leds.ko”命令时就会调用这个函数
*/
static void __exit EmbedSky_leds_exit(void)
{
/* 卸载驱动程序 */
unregister_chrdev(LED_MAJOR, DEVICE_NAME);
device_destroy(led_class, MKDEV(LED_MAJOR, 0)); //删掉设备节点
class_destroy(led_class); //注销类
}
/* 这两行指定驱动程序的初始化函数和卸载函数 */
module_init(EmbedSky_leds_init);
module_exit(EmbedSky_leds_exit);
/* 描述驱动程序的一些信息,不是必须的 */
MODULE_AUTHOR("http://www.embedsky.net"); // 驱动程序的作者
MODULE_DESCRIPTION("TQ2440/SKY2440 LED Driver"); // 一些描述信息
MODULE_LICENSE("GPL"); // 遵循的协议
上面代码中,led_table数组相当于对应了GPB的四个IO口的索引,通过这四个值,对这四个IO口进行相关操作。例如:
S3C2410_GPB5 = S3C2410_GPIONO(S3C2410_GPIO_BANKB, 5)
= S3C2410_GPIO_BANKB + 5
= 32*1 + 5
在s3c2410_gpio_setpin(S3C2410_GPB5,0)中,该函数首先通过S3C2410_GPB5获得GPB的虚拟地址和偏移地址,再对GPB5的GPBDAT寄存器进行操作,具体
void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
{
void __iomem *base = S3C2410_GPIO_BASE(pin);
unsigned long offs = S3C2410_GPIO_OFFSET(pin);
unsigned long flags;
unsigned long dat;
local_irq_save(flags);
dat = __raw_readl(base + 0x04);//读取GPIO的DAT数据到dat
dat &= ~(1 << offs); //先将要设置的IO口拉低
dat |= to << offs; //再将形参的to值赋给dat
__raw_writel(dat, base + 0x04);//最后将DAT值写进GPIO的DAT
local_irq_restore(flags);
}
上面的 函数调用了两个子函数,具体定义如下
#define S3C2410_GPIO_BASE(pin) ((((pin) & ~31) >> 1) + S3C24XX_VA_GPIO)
#define S3C2410_GPIO_OFFSET(pin) ((pin) & 31)
其中S3C24XX_VA_GPIO定义如下:
#define S3C24XX_VA_GPIO S3C2410_ADDR(0x00E00000)
#define S3C2410_ADDR(x) (0xF0000000 + (x))
这里S3C2410_ADDR的基地址为0xF0000000(??),也即2440所有寄存器的虚拟地址的基地址。0x00E00000表示2440的GPIO的偏移地址,也就是说其GPIO的虚拟地址首地址为0xF0E00000。
再看看S3C2410_GPIO_BASE(pin)的定义,我们不仿把S3C2410_GPB5的值放进去计算,可以得到(S3C2410_GPB5&~31)=32。其目的就是去掉GPB的偏移值,然后再右移一位,和GPIO的虚拟地址首地址相加。因此,S3C2410_GPIO_BASE(pin)只代表了对应GPIO组的虚拟地址,如GPB的虚拟地址为10000(B)+0xF0E00000=0xF0E00010。依此类推,可以得到所有GPIO的偏移地址,具体如下表:
BANK
(pin&~31)
(pin&~31)>>1
S3C2410_GPIO_BASE(pin)
GPA
32*0
0000,0000
0x00
0xF0E00000
GPB
32*1
0010,0000
0x10
0xF0E00010
GPC
32*2
0100,0000
0x20
0xF0E00020
GPD
32*3
0110,0000
0x30
0xF0E00030
GPE
32*4
1000,0000
0x40
0xF0E00040
GPF
32*5
1010,0000
0x50
0xF0E00050
GPG
32*6
1100,0000
0x60
0xF0E00060
GPH
32*7
1110,0000
0x70
0xF0E00070
S3C2410_GPIO_OFFSET用于获得具体GPIO的偏移地址。如GPB5,则S3C2410_GPIO_OFFSET(pin) = (pin)&31 = (32*1 + 5) & 31 = 5。有了*base和off,就可以操作具体的寄存器了。
函数s3c2410_gpio_cfgpin()用于配置GPCON寄存器。具体代码
void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
{
void __iomem *base = S3C2410_GPIO_BASE(pin);
unsigned long mask;
unsigned long con;
unsigned long flags;
if (pin < S3C2410_GPIO_BANKB)
{
mask = 1 << S3C2410_GPIO_OFFSET(pin);//GPA的寄存器只占一位
}
else
{
mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;//非GPA的寄存器占两位
}
local_irq_save(flags);
con = __raw_readl(base + 0x00);//先保留GPCON的值
con &= ~mask; //再将要设置的管脚的CON值清零
con |= function; //然后将形参传进来的配置赋给CON
__raw_writel(con, base + 0x00); //最后将CON值写进GPCON寄存器
local_irq_restore(flags);
}
上面的LED驱动程序中,led_cfg_table数组给出了GPB相应管脚的属性设置,调用上面的函数后即设置为Output。
到此为止,整个S3C2440的IO口操作,应该就一目了然了
#define __raw_writel(v,a) (__chk_io_ptr(a), *(volatile unsigned int __force *)(a) = (v))
# define __chk_io_ptr(x) (void)0
__chk_io_ptr()是编译器为了更细致地检查参数的属性,用于调试,正常编译时没有作用。
volatile为了防止Compiler优化。
内核中,对所有的地址都是通过虚拟地址进行访问的.因此,不能直接访问0x56000010的物理地址,如果要对0x56000010的物理地址进行访问(一般是外设寄存器),那么需要把0x56000010的物理地址映射为虚拟地址,然后对该虚拟地址进行访问就是对实际的物理地址进行访问了。
需要注意的是:在进行映射时,该虚拟地址需要disable cache和Write Buffer, 否则就是加了volatile也是没有用的
这个IOREMAP的实现过程中
/*
* figure out the physical address offset in a page size
* PAGE_MASK = (1 << 10)
*/
offset = phys_addr &~ PAGE_MASK;
/*
* figure out physical address with page align
*/
phys_addrs &= PAGE_MASK;
/*
* get the real size with page align
*/
size = PAGE_ALIGN(last_addr) - phys_addrs;
下面是通过vmlist中查找以size大小的空闲块,所以从这里可以看出,已经做过了页的对齐,只以映射的大小
杂项设备(misc device)
杂项设备也是在嵌入式系统中用得比较多的一种设备驱动。在 Linux 内核的include/linux目录下有Miscdevice.h文件,要把自己定义的misc device从设备定义在这里。其实是因为这些字符设备不符合预先确定的字符设备范畴,所有这些设备采用主编号10 ,一起归于misc device,其实misc_register就是用主标号10调用register_chrdev()的。
也就是说,misc设备其实也就是特殊的字符设备。
字符设备(char device)
使用register_chrdev(LED_MAJOR,DEVICE_NAME,&dev_fops)注册字符设备驱动程序时,如果有多个设备使用该函数注册驱动程序,LED_MAJOR不能相同,否则几个设备都无法注册(我已验证)。如果模块使用该方式注册并且 LED_MAJOR为0(自动分配主设备号 ),使用insmod命令加载模块时会在终端显示分配的主设备号和次设备号,在/dev目录下建立该节点,比如设备leds,如果加载该模块时分配的主设备号和次设备号为253和0,则建立节点:mknod leds c 253 0。使用register_chrdev (LED_MAJOR,DEVICE_NAME,&dev_fops)注册字符设备驱动程序时都要手动建立节点 ,否则在应用程序无法打开该设备。
__raw_readl和__raw_writel
Linux对I/O的操作都定义在asm/io.h中,相应的在arm平台下,就在asm-arm/io.h中。
#define __raw_writeb(v,a) (__chk_io_ptr(a), *(volatile unsigned char __force *)(a) = (v))
#define __raw_writew(v,a) (__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v))
#define __raw_writel(v,a) (__chk_io_ptr(a), *(volatile unsigned int __force *)(a) = (v))在include/linux/compiler.h中:
#ifdef __CHECKER__……
extern void __chk_io_ptr(void __iomem *);
#else……
# define __chk_io_ptr(x) (void)0……
#endif
__raw_readl(a)展开是:((void)0, *(volatile unsigned int _force *)(a))。在定义了__CHECKER__的时候先调用__chk_io_ptr检查该地址,否则__chk_io_ptr什么也不做,*(volatile unsigned int _force *)(a)就是返回地址为a处的值。(void)xx的做法有时候是有用的,例如编译器打开了检查未使用的参数的时候需要将没有用到的参数这么弄一下才能编译通过。
CPU对I/O的物理地址的编程方式有两种:一种是I/O映射,一种是内存映射。__raw_readl和__raw_writel等是原始的操作I/O的方法,由此派生出来的操作方法有:inb、outb、_memcpy_fromio、readb、writeb、ioread8、iowrite8等。
Tiny6410 LED字符设备驱动的更多相关文章
- fl2440 platform总线led字符设备驱动
首先需要知道的是,设备跟驱动是分开的.设备通过struct device来定义,也可以自己将结构体封装到自己定义的device结构体中: 例如:struct platform_device: 在inc ...
- LED字符设备驱动实例及测试代码
驱动代码如下: #include <linux/kernel.h>//内核头文件 #include <linux/init.h>//__init等 #include <l ...
- Linux LED字符设备驱动
// 申请IO资源 int gpio_request(unsigned gpio, const char *label); // 释放IO资源 void gpio_free(unsigned gpio ...
- 嵌入式Linux驱动学习之路(十)字符设备驱动-my_led
首先贴上代码: 字符设备驱动代码: /** *file name: led.c */#include <linux/sched.h> #include <linux/signal.h ...
- 深入理解Linux字符设备驱动
文章从上层应用访问字符设备驱动开始,一步步地深入分析Linux字符设备的软件层次.组成框架和交互.如何编写驱动.设备文件的创建和mdev原理,对Linux字符设备驱动有全面的讲解.本文整合之前发表的& ...
- Linux字符设备驱动结构(一)--cdev结构体、设备号相关知识机械【转】
本文转载自:http://blog.csdn.net/zqixiao_09/article/details/50839042 一.字符设备基础知识 1.设备驱动分类 linux系统将设备分为3类:字符 ...
- 【转】linux设备驱动程序之简单字符设备驱动
原文网址:http://www.cnblogs.com/geneil/archive/2011/12/03/2272869.html 一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用 ...
- Linux字符设备驱动
一.字符设备基础 字符设备 二.字符设备驱动与用户空间访问该设备的程序三者之间的关系 三.字符设备模型 1.Linux内核中,使用 struct cdev 来描述一个字符设备 动态申请(构造)cdev ...
- 字符设备驱动1:新的方式添加cdev + 在open函数中将文件私有数据指向设备结构体
本例中,驱动入口处,使用cdev_add添加驱动,这点也可与字符设备驱动0:一个简单但完整的字符设备驱动程序对比一下. 另外主要讲xx_open实现文件私有数据指向设备结构体. 引子: 偶然看到,在j ...
随机推荐
- 第十一篇、RxSwift
三. 什么是函数式编程? 什么是函数式编程呢? 函数式编程其实是一种编程思想, 代码写出来只是它的表现形式. 在面向对象的编程思想中, 我们将要解决的一个个问题, 抽象成一个个类, 通过给类定义属性和 ...
- Smarty模板引擎技术二
Smarty模板引擎技术 内建函数 include_php内建函数 作用:载入一个php文件,将载入的文件的内容赋值给一个变量 注意:该内建函数只能在2.0中使用,如果使用的话,必须得实例化Sma ...
- java 内部类定义在局部时需要注意的情况
/*内部类定义在局部时,1,不可以被成员修饰符修饰2,可以直接访问外部类中的成员,因为还持有外部类中的引用. 但是不可以访问它所在的局部中的变量.只能访问被final修饰的局部变量.*/clas ...
- Python快速入门学习笔记(三)——函数的定义与调用
定义函数 Python中定义函数的格式为: def fun([参数列表]): ... 函数在执行到return语句时结束,并将结果返回.如果没有return语句,函数执行完毕后返回None. 例: d ...
- java web中cookie的永久创建与撤销
一.首先是创建cookie 当在数据库中查找知道所输入的用户名和密码正确之后,就开始创建: String cb=request.getParameter("cb");//cb就是登 ...
- 压力测试 tpcc-mysql
TPCC-MYSQL是由percona发布一个用来测试数据库的压力工具,模拟一个电商的业务, 主要的业务有新增订单,库存查询,发货,支付等模块的测试 1.下载 2.安装 1.解压 cd scr ; ...
- manifest save for self
一.使用html5的缓存机制 1.先上规则代码:m.manifest CACHE MANIFEST # 2015-04-24 14:20 #直接缓存的文件 CACHE: /templates/spec ...
- Spark Streaming揭秘 Day31 集群模式下SparkStreaming日志分析(续)
Spark Streaming揭秘 Day31 集群模式下SparkStreaming日志分析(续) 今天延续昨天的内容,主要对为什么一个处理会分解成多个Job执行进行解析. 让我们跟踪下Job调用过 ...
- uva401 - Palindromes结题报告
题目地址 : http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_probl ...
- Beaglebone Back学习二(功能测试)
开发板测试 买到开发板后,首先要测试一下板子的功能,这个可以参考官方的步骤(Getting Started)进行. 1 首先下载最新的镜像文件http://beagleboard.org/latest ...