字符设备驱动基础5——驱动如何操控硬件

以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。

补充内容:字符设备驱动高级篇5——静态映射表、动态映射结构体方式操作寄存器

前言

上节字符设备驱动基础4——读写接口的操作实践中,驱动源代码中的test_chrdev_open()、test_chrdev_read()、test_chrdev_write()等函数,其内部只是一些简单的输出语句,以表示它们得到调用,从而演示应用层读写操作与驱动层的读写操作如何关联的。这些驱动源代码中的函数没有涉及到具体的硬件操作(比如寄存器操作这些行为)。

本节内容,将以“动静态映射操作LED”为例,细化驱动源代码中的读写操作函数,使其涉及到实际意义的硬件操作。这里的“映射”,是指物理地址和虚拟地址的对应关系;这里的“动静态”,是指映射的建立是一直存在的,还是根据需要随时建立与销毁的。

一、驱动如何操控硬件

1、OS与裸机操作硬件的异同点

(1)相同点

硬件物理原理不变;硬件操作接口(寄存器)不变;硬件操作代码不变。

(2)不同点

寄存器地址不同

原来是直接用物理地址,现在需要用(该物理地址相对应的)虚拟地址。

寄存器的物理地址是CPU设计时决定的,从datasheet中查找到的。

编程方法不同

裸机中习惯直接用函数指针操作寄存器地址。

kernel为了实现最大程序的可移植性,习惯用封装好的io读写函数来操作寄存器。

2、内核的虚拟地址映射方法

(1)虚拟地址映射的意义

见博文:为什么要使用虚拟地址空间与物理地址空间映射?

(2)虚拟地址映射方法

内核中有两套虚拟地址映射方法:静态映射、动态映射。

1)静态映射

  • 内核移植时以代码的形式硬编码,如果要更改必须改源代码后重新编译内核。

  • 在内核启动时建立静态映射表,到内核关机时销毁,中间一直有效。

  • 对于移植好的内核,你用不用它都在那里。

2)动态映射

  • 驱动程序根据需要随时动态的建立映射、使用、销毁映射。

  • 映射是短期临时的。

(3)如何选择虚拟地址映射方法

  • 两种映射并不排他,可以同时使用。

  • 静态映射类似于C语言中全局变量,动态方式类似于C语言中malloc堆内存。

  • 静态映射的好处是执行效率高,坏处是始终占用虚拟地址空间。

  • 动态映射的好处是按需使用虚拟地址空间,坏处是每次使用前后都需要代码去建立映射、销毁映射。

二、静态映射操作LED

1、静态映射表

静态映射表,其实就是头文件中的宏定义。

不同版本内核中静态映射表所在的目录位置、文件名可能不同。

不同SoC的静态映射表所在的目录位置、文件名可能不同。

2、三星版本内核中的静态映射表

CPU在安排寄存器地址时不是随意分布的,而是按照模块来组织的,比如GPIO模块、UART模块等等。每个模块里,寄存器的地址一般是连续的,所以内核在定义寄存器地址时,都是先定义某个模块的基地址,然后再用“基地址+偏移量”来表示具体的一个寄存器地址。

驱动源代码因为要操作LED,涉及到GPIO模块,因此这里讲述下GPIO的相关内容。

(1)GPIO模块的虚拟基地址

文件arch/arm/plat-s5p/include/plat/map-s5p.h中定义了几个模块(GPIO、UART等)的虚拟基地址,其中GPIO模块的虚拟基地址定义如下:

//……
#define S5P_VA_GPIO        S3C_ADDR(0x00500000)
//……

其中S3C_ADDR定义在arch/arm/plat-samsung/include/plat/map-base.h。

#define S3C_ADDR_BASE	(0xFD000000)#ifndef __ASSEMBLY__
#define S3C_ADDR(x)	((void __iomem __force *)S3C_ADDR_BASE + (x))
#else
#define S3C_ADDR(x)	(S3C_ADDR_BASE + (x))
#endif

其中 #define S3C_ADDR_BASE   (0xFD000000) , S3C_ADDR_BASE 是三星移植时确定的静态映射表的基地址,所有模块的虚拟基地址都是以这个地址+偏移量来指定的。

(2)GPIO模块中每个端口的虚拟基地址

GPIO模块包含许多端口,比如GPA0、GPJ0等(这些端口包含着许多IO口,比如GPA0_1,GPA0_2等),每个端口都有一个虚拟基地址,定义在arch/arm/mach-s5pv210/include/mach/regs-gpio.h文件中,如下所示。

由此可知,端口的虚拟基地址,都是是由“GPIO模块的虚拟基地址 + 偏移量”组成的。

/* Base addresses for each of the banks */#define S5PV210_GPA0_BASE		(S5P_VA_GPIO + 0x000)
#define S5PV210_GPA1_BASE		(S5P_VA_GPIO + 0x020)
#define S5PV210_GPB_BASE 		(S5P_VA_GPIO + 0x040)
#define S5PV210_GPC0_BASE		(S5P_VA_GPIO + 0x060)
#define S5PV210_GPC1_BASE		(S5P_VA_GPIO + 0x080)
#define S5PV210_GPD0_BASE		(S5P_VA_GPIO + 0x0A0)
#define S5PV210_GPD1_BASE		(S5P_VA_GPIO + 0x0C0)
#define S5PV210_GPE0_BASE		(S5P_VA_GPIO + 0x0E0)
#define S5PV210_GPE1_BASE		(S5P_VA_GPIO + 0x100)
#define S5PV210_GPF0_BASE		(S5P_VA_GPIO + 0x120)
//省略……

(3)GPIO具体寄存器的虚拟地址

GPIO具体寄存器的虚拟地址,定义在arch/arm/mach-s5pv210/include/mach/gpio-bank.h文件中。它们都是以“GPIO端口的虚拟基地址+偏移量”组成。如下所示。

//省略……
#define S5PV210_GPJ0CON			(S5PV210_GPJ0_BASE + 0x00)
#define S5PV210_GPJ0DAT			(S5PV210_GPJ0_BASE + 0x04)
//省略……

3、静态映射操作LED实践

步骤1:添加LED亮灭操作代码

参考裸机内容,添加LED亮、灭操作的代码。为了测试代码的可行性,先在chrdev_init()和chrdev_exit()init函数中分别添加点亮和熄灭LED的代码,如下。

#include <linux/module.h>		// module_init  module_exit
#include <linux/init.h>			// __init   __exit
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <mach/regs-gpio.h>
#include <mach/gpio-bank.h>  // arch/arm/mach-s5pv210/include/mach/gpio-bank.h
#include <linux/string.h>#define GPJ0CON		S5PV210_GPJ0CON
#define GPJ0DAT		S5PV210_GPJ0DAT#define rGPJ0CON	*((volatile unsigned int *)GPJ0CON)
#define rGPJ0DAT	*((volatile unsigned int *)GPJ0DAT)// 模块安装函数
static int __init chrdev_init(void)
{	printk(KERN_INFO "chrdev_init helloworld init\n");rGPJ0CON = 0x11111111;rGPJ0DAT = ((0<<3) | (0<<4) | (0<<5));		// 亮return 0;
}// 模块卸载载函数
static void __exit chrdev_exit(void)
{printk(KERN_INFO "chrdev_exit helloworld init\n");	rGPJ0DAT = ((1<<3) | (1<<4) | (1<<5));  //灭
}module_init(chrdev_init);
module_exit(chrdev_exit);MODULE_LICENSE("GPL");				// 描述模块的许可证
MODULE_AUTHOR("aston");				// 描述模块的作者
MODULE_DESCRIPTION("module test");	// 描述模块的介绍信息
MODULE_ALIAS("alias xxx");			// 描述模块的别名信息
[root@xjh mnt]# insmod module_test.ko 
[19261.861366] chrdev_init helloworld init //此时三盏LED亮
[root@xjh mnt]# rmmod module_test.ko 
[19307.270997] chrdev_exit helloworld init 
[root@xjh mnt]# rmmod module_test.ko      //此时三盏LED由亮转灭

步骤2:分别在test_chrdev_open(release)函数里添加LED亮(灭)代码

见最后的代码。

步骤3:在驱动源代码中细化test_chrdev_write()写函数

1)先定义应用和驱动之间的控制接口,比如应用写"1"表示灯亮,写"0"表示让灯灭。

2)见最后的代码。

步骤4:写应用来测试写函数

因为针对LED,在应用层里不好表示读操作,所以在应用层只测试了写函数。

另外,在运行应用层app.c文件前,先安装驱动获得主设备号,然后以“mknod /dev/test c 主设备 次设备号”的方式创建设备文件。

应用层app.c代码如下:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>#define FILE	"/dev/test"		
char buf[100];int main(void)
{int fd = -1;int i = 0;fd = open(FILE, O_RDWR);if (fd < 0){printf("open %s error.\n", FILE);return -1;}printf("open %s success..\n", FILE);while (1){memset(buf, 0 , sizeof(buf));printf("请输入 on 或者 off 或者 flash 或者 quit :\n");scanf("%s", buf);if (!strcmp(buf, "on")){write(fd, "1", 1);}else if (!strcmp(buf, "off")){write(fd, "0", 1);}else if (!strcmp(buf, "flash")){for (i=0; i<3; i++){write(fd, "1", 1);sleep(1);write(fd, "0", 1);sleep(1);}}	else if (!strcmp(buf, "quit")){break;}elsebreak;}close(fd);	return 0;
}

步骤5:在驱动源代码中添加读函数

见最后的代码。

步骤6:填充struct file_operations变量

见最后的代码。

附录:最后的代码

#include <linux/module.h>		// module_init  module_exit
#include <linux/init.h>			// __init   __exit
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <mach/regs-gpio.h>
#include <mach/gpio-bank.h>  // arch/arm/mach-s5pv210/include/mach/gpio-bank.h
#include <linux/string.h>#define MYMAJOR		200
#define MYNAME		"testchar"#define GPJ0CON		S5PV210_GPJ0CON
#define GPJ0DAT		S5PV210_GPJ0DAT
//这里已经是虚拟地址了,在内核中已经定义好S5PV210_GPJ0CON
//所谓的静态映射就体现在这里!
//这个是在内核中写死的,如果要修改,就要把内核代码相关部分修改,然后重新编译#define rGPJ0CON	*((volatile unsigned int *)GPJ0CON)
#define rGPJ0DAT	*((volatile unsigned int *)GPJ0DAT)int mymajor;
char kbuf[100];			// 内核空间的bufstatic int test_chrdev_open(struct inode *inode, struct file *file)
{// 这个函数中真正应该放置的是打开这个设备的硬件操作代码部分printk(KERN_INFO "test_chrdev_open\n");rGPJ0CON = 0x11111111;rGPJ0DAT = ((0<<3) | (0<<4) | (0<<5));		// 亮return 0;
}static int test_chrdev_release(struct inode *inode, struct file *file)
{printk(KERN_INFO "test_chrdev_release\n");rGPJ0DAT = ((1<<3) | (1<<4) | (1<<5));  //灭return 0;
}ssize_t test_chrdev_read(struct file *file, char __user *ubuf, \size_t count, loff_t *ppos)
{int ret = -1;printk(KERN_INFO "test_chrdev_read\n");ret = copy_to_user(ubuf, kbuf, count);if (ret){printk(KERN_ERR "copy_to_user fail\n");return -EINVAL;}printk(KERN_INFO "copy_to_user success..\n");return 0;
}//写函数的本质就是将应用层传递过来的数据先复制到内核中,
//然后将之以正确的方式写入硬件完成操作。
static ssize_t test_chrdev_write(struct file *file, const char __user *ubuf,\size_t count, loff_t *ppos)
{int ret = -1;printk(KERN_INFO "test_chrdev_write\n");// 使用该函数将应用层传过来的ubuf中的内容拷贝到驱动空间中的一个buf中//memcpy(kbuf, ubuf);		// 不行,因为2个不在同一个地址空间中memset(kbuf, 0, sizeof(kbuf));ret = copy_from_user(kbuf, ubuf, count);if (ret){printk(KERN_ERR "copy_from_user fail\n");return -EINVAL;}printk(KERN_INFO "copy_from_user success..\n");if (kbuf[0] == '1'){rGPJ0DAT = ((0<<3) | (0<<4) | (0<<5));}else if (kbuf[0] == '0'){rGPJ0DAT = ((1<<3) | (1<<4) | (1<<5));}return 0;
}// 自定义一个file_operations结构体变量,并且去填充
static const struct file_operations test_fops = {.owner		= THIS_MODULE,		  // 惯例,直接写即可	.open		= test_chrdev_open,	   // 将来应用open打开这个设备时实际调用的.release	= test_chrdev_release,	// 就是这个.open对应的函数.write 		= test_chrdev_write,.read		= test_chrdev_read,
};// 模块安装函数
static int __init chrdev_init(void)
{	printk(KERN_INFO "chrdev_init helloworld init\n");// 在module_init宏调用的函数中去注册字符设备驱动// major传0进去表示要让内核帮我们自动分配一个合适的空白的没被使用的主设备号// 内核如果成功分配就会返回分配的主设备号;如果分配失败会返回负数mymajor = register_chrdev(0, MYNAME, &test_fops);if (mymajor < 0){printk(KERN_ERR "register_chrdev fail\n");return -EINVAL;}printk(KERN_INFO "register_chrdev success... mymajor = %d.\n", mymajor);/*rGPJ0CON = 0x11111111;rGPJ0DAT = ((0<<3) | (0<<4) | (0<<5));		// 亮*/return 0;
}// 模块卸载载函数
static void __exit chrdev_exit(void)
{printk(KERN_INFO "chrdev_exit helloworld exit\n");	// 在module_exit宏调用的函数中去注销字符设备驱动unregister_chrdev(mymajor, MYNAME);//	rGPJ0DAT = ((1<<3) | (1<<4) | (1<<5)); //灭
}module_init(chrdev_init);
module_exit(chrdev_exit);// MODULE_xxx这种宏作用是用来添加模块描述信息
MODULE_LICENSE("GPL");				// 描述模块的许可证
MODULE_AUTHOR("aston");				// 描述模块的作者
MODULE_DESCRIPTION("module test");	// 描述模块的介绍信息
MODULE_ALIAS("alias xxx");			// 描述模块的别名信息

三、动态映射操作LED

1、建立动态映射

首先使用request_mem_region()函数向内核申请需要映射的内存资源。

然后使用ioremap()函数来实现映射,传给它一个物理地址,返回一个虚拟地址。

也就是说,要先申请(不一定申请成功),然后再映射,然后再使用。

2、销毁动态映射

首先使用iounmap()函数解除映射,然后使用release_mem_region()函数释放申请。

也就是说,使用完要解除映射时,先解除映射,然后再释放申请。

3、代码实践

#include <linux/module.h>		// module_init  module_exit
#include <linux/init.h>			// __init   __exit
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <mach/regs-gpio.h>
#include <mach/gpio-bank.h>	// arch/arm/mach-s5pv210/include/mach/gpio-bank.h
#include <linux/string.h>
#include <linux/io.h>
#include <linux/ioport.h>#define MYNAME		"testchar"#define GPJ0CON_PA	0xe0200240  //物理地址
#define GPJ0DAT_PA 	0xe0200244unsigned int *pGPJ0CON;
unsigned int *pGPJ0DAT;int mymajor;
char kbuf[100];			// 内核空间的buf//************省略部分代码*****************// 模块安装函数
static int __init chrdev_init(void)
{	printk(KERN_INFO "chrdev_init helloworld init\n");mymajor = register_chrdev(0, MYNAME, &test_fops);if (mymajor < 0){printk(KERN_ERR "register_chrdev fail\n");return -EINVAL;}printk(KERN_INFO "register_chrdev success... mymajor = %d.\n", mymajor);// 使用动态映射的方式来操作寄存器if (!request_mem_region(GPJ0CON_PA, 4, "GPJ0CON"))/*参数含义:起始地址(或者说寄存器的原始地址)寄存器的长度(一般32bit,因此4字节)这段空间的名字*/return -EINVAL;if (!request_mem_region(GPJ0DAT_PA, 4, "GPJ0CON"))return -EINVAL;pGPJ0CON = ioremap(GPJ0CON_PA, 4);//参数含义和上一样,返回一个指针pGPJ0DAT = ioremap(GPJ0DAT_PA, 4);*pGPJ0CON = 0x11111111;*pGPJ0DAT = ((0<<3) | (0<<4) | (0<<5));		// 亮return 0;
}// 模块卸载函数
static void __exit chrdev_exit(void)
{printk(KERN_INFO "chrdev_exit helloworld exit\n");//想要熄灯,必要要在解除映射的前面*pGPJ0DAT = ((1<<3) | (1<<4) | (1<<5));	 //熄灯// 解除映射iounmap(pGPJ0CON);iounmap(pGPJ0DAT);release_mem_region(GPJ0CON_PA, 4);release_mem_region(GPJ0DAT_PA, 4);// 在module_exit宏调用的函数中去注销字符设备驱动unregister_chrdev(mymajor, MYNAME);
}module_init(chrdev_init);
module_exit(chrdev_exit);// MODULE_xxx这种宏作用是用来添加模块描述信息
MODULE_LICENSE("GPL");				// 描述模块的许可证
MODULE_AUTHOR("aston");				// 描述模块的作者
MODULE_DESCRIPTION("module test");	// 描述模块的介绍信息
MODULE_ALIAS("alias xxx");			// 描述模块的别名信息

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

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

相关文章

Android----使用代码 建立gprs 闹钟 连接

Android&#xff1a;实用代码&#xff08;开启启动、建立GPRS连接、闹钟等&#xff09; 分类&#xff1a; Android2012-04-21 18:06312人阅读评论(0)收藏举报androidactionstringservice手机j2me1&#xff1a;查看是否有存储卡插入String statusEnvironment.getExternalStorage…

句法依存分析_复旦大学邱锡鹏教授:词法、句法分析研究进展综述

本文为第十六届自然语言处理青年学者研讨会 YSSNLP2019 报告《词法、句法分析研究进展综述》的简要文字整理&#xff0c;本报告主要回顾词法、句法领域的最新研究进展。 关于报告人&#xff1a;邱锡鹏&#xff0c;复旦大学计算机科学技术学院副教授&#xff0c;博士生导师。于复…

【struts2】Struts2的运行流程

1&#xff09;前提条件 在讲解流程之前&#xff0c;假设我们已经建立了的一个名为strutsDeepen的web工程&#xff0c;该工程仅仅实现了简单的用户登陆与欢迎界面。具体的实现为&#xff1a; 在web.xml中配置了Struts2的过滤器写了一个Action类&#xff0c;名称为loginAction在s…

获取系统信息2——linux中使用随机数

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 一、随机数和伪随机数 随机数是随机出现&#xff0c;没有任何规律的一组数列。真正的完全随机的数列是不存在的&#xff0c;只是一种理想情况。我们一般只能通过一些算法得到一个伪随机数序列。平时…

11. 类对象简介

11. 类对象简介1.1 类是一个模板&#xff0c;是一种类型&#xff0c;“物以类聚”1.2 对象是类的一个具体实现1.3例如&#xff1a;汽车模型和生产出来的汽车猫和我家的那只猫1.4 实例人骑车public class Test3{public static void main(String[] args){Person p new Person();…

python 建筑计算_制图小技巧:巧用Python和ELK瞬间完成总图建筑名称标注

哎呦&#xff0c;又到了每周一次的制图教室啦。经过前面两次制图教程的分享&#xff0c;相信大家对于白模填色和写实渲染这两种表达方式肯定有了较好的掌握。那么今天我们就转战制图技巧篇&#xff0c;和童鞋们聊一下总平面图中的建筑名称标注问题。对于总平面图&#xff0c;各…

在MacOSX上重新安装Python (10.8) python 自然语言处理的前戏

因为想学python自然语言处理就想在mac上重新配置一下python。 在网上找了很久才找到两篇有用的教程http://765i.cn/%E5%9C%A8macosx%E4%B8%8A%E9%87%8D%E6%96%B0%E5%AE%89%E8%A3%85python-10-8/ http://woodpecker.org.cn/diveintopython3/installing-python.html 第一篇文章基…

获取系统信息3——proc文件系统介绍和使用

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 一、proc文件系统介绍 1、操作系统级别的调试一般很困难 简单的程序可以单步调试&#xff1b;复杂一点的程序可以printf、cout等打印信息调试&#xff08;即输出信息到控制台&#xff09;&#xff0…

阻止函数源码在控制台输出

这是一个很贱的技能&#xff0c;我在谷歌控制台源码里看到的。相信大家都知道&#xff0c;在控制台里只输入函数名&#xff0c;不输入 () 然后按回车&#xff0c;就可以输出源码。 都不会陌生吧&#xff0c;这也有助于我们调试&#xff0c;是个很棒的技巧。不过系统内置的就会输…

值不值得入手_iPhone11现在还值不值得入手?真实用户说出心里话

iPhone11作为苹果走量的一款机型&#xff0c;自发布以来就备受争议&#xff0c;有的朋友说真香&#xff0c;A13iOS只卖4000多&#xff0c;还有的朋友吐槽大黑边、828P的屏幕、信号不好还有充电太慢&#xff0c;特别是现在同价位能买到的安卓旗舰&#xff0c;要5G有5G、要高刷新…

设备驱动,字符设备驱动、(总线)设备驱动模型、sysfs文件系统、平台设备驱动

以下内容转载于微信公众号&#xff1a;嵌入式企鹅圈。如有侵权&#xff0c;请告知删除。 学习Linux设备驱动开发的过程中自然会遇到字符设备驱动、平台设备驱动、设备驱动模型和sysfs等相关概念和技术。 对于初学者来说会非常困惑&#xff0c;甚至对Linux有一定基础的工程师而言…

写文章最难写的是标题

最近做事情有点沉不下心来&#xff0c;不知道是不是在家一个月养成的坏毛病还没改过来还是怎么回事。但仔细想了想&#xff0c;其实这只是个借口。自从高中以来&#xff0c;我这个毛病好像就有了&#xff0c;大概是高二的时候一直到现在&#xff0c;老是不能全心全意的静下心来…

对于局部变量_对于SQL常用查询优化方法的整理

查询进行优化&#xff0c;应尽量避免全表扫描&#xff0c;首先应考虑在where 及order by 涉及的列上建立索引:尝试下面的技巧以避免优化器错选了表扫描&#xff1a;使用ANALYZE TABLE tbl_name为扫描的表更新关键字分布。对扫描的表使用FORCE INDEX告知MySQL&#xff0c;相对于…

wampServer2.1错误(Could not execute menu item (internal error)

安装wampServer2.1后提示以下错误Could not execute menu item (internal error) [Exception] Could not perform service action 服务尚未启动错误原因&#xff1a;08端口被占用&#xff08;因为安装好wampServer后&#xff0c;默认的端口为80&#xff09;解决方法&#xff1a…

黄聪:如何使用CodeSmith批量生成代码(原创系列教程)

在上一篇我们已经用PowerDesigner创建好了需要的测试数据库,下面就可以开始用它完成批量代码生成的工作啦. 下面我会一步步的解释如何用CodeSmith实现预期的结果的,事先声明一下,在此只做一个简单的Demo,并不详细的讲解CodeSmith各个强大的功能,有兴趣的朋友可以打开CodeSmith的…

字符设备驱动基础2——用开发板来调试驱动的步骤

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 步骤1&#xff1a;获取编译后的内核源码与镜像 描述 该内核源码主要用来编译驱动源码。该内核源码必须与开发板运行的内核源码的版本一致&#xff0c;否则编译后的驱动程序在开发版上运行时&#xf…

c语音异或运算符_C语言中的按位异或运算符有什么用处?

原标题&#xff1a;C语言中的按位异或运算符有什么用处&#xff1f;想知道C语言中的按位异、运算符有什么用处&#xff0c;首先C语言中^为按位异或运算符&#xff0c;若两个二进制位相同&#xff0c;则结果为0&#xff0c;不同为1例&#xff1a;#include "stdio.h"ma…

Android 开发笔记 一

参考 : http://www.cnblogs.com/nightkidzxc/archive/2011/12/14/2379010.html 1.得到 SD 卡的目录 : String SDPATH Environment.getExternalStorageDriectory() "/"; 2.Activity 相当于 From Activity 以 Dialog形式显示在 Manifest中设置 : android:theme&qu…

超短的判断IE javascript代码

首先说明该代码只能在IE 6~8中有效&#xff0c;再高级的IE已经修复这个BUG <script type’text/javascript’> var ie !-[1,]; alert(ie); //如果是ie&#xff0c;弹出true </script> 原因&#xff1a; 首先[1,]是个数组&#xff0c;由于有个逗号&#xff…

mysql命令导出数据库_MYSQL 数据库导入导出命令

在不同操作系统或MySQL版本情况下&#xff0c;直接拷贝文件的方法可能会有不兼容的情况发生。所以一般推荐用SQL脚本形式导入。下面分别介绍两种方法。MySQL命令行导出数据库1&#xff0c;进入MySQL目录下的bin文件夹&#xff1a;cd MySQL中到bin文件夹的目录如我输入的命令行&…