嵌入式Linux驱动开发日记
嵌入式Linux驱动开发日记
主机硬件环境
开发机:虚拟机Ubuntu12.04
内存: 1G
硬盘:80GB
目标板硬件环境
CPU: SP5V210 (开发板:QT210)
SDRAM: 512M (4片K4T1G164Q )
Nand flash: 512M (K9F4G08)
以太网芯片: SMSC LAN9220
工具介绍
仿真器: 暂无
电缆: 串口线,USB线
Windows 操作系统软件环境
ADS编译工具: 暂无
仿真器软件:暂无
调试软件: 终端(ADB)、eclipse
Linux操作系统软件环境
GNU交叉编译工具: arm-linux-gcc 4.4.1、JDK1.6、git 1.7、gcc 4.5、python 2.7
Section ONE:最简单的驱动程序:hello world
首先我们写一个最简单的模块。编辑hello_module.c
#include<linux/init.h> //module_init(),module_exit()
#include<linux/module.h> //MODULE_AUTHOR(),MODULE_LICENSE()
#include<linux/kernel.h> //KERN_EMERG static int hello_init(void){
printk(KERN_EMERG "hello world enter\n");
return 0;
} void hello_exit(void){
printk(KERN_EMERG "hello world exit\n");
} module_init(hello_init);
module_exit(hello_exit); MODULE_AUTHOR("CHSRY");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("A simple Hello World Module");
MODULE_ALIAS("a simplest module");
编写Makefile
obj-m := hello.o
all:
make -C /lib/modules/$(shell uname -r)/build SUBDIRS=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build SUBDIRS=$(PWD) clean
运行#make
生成hello.ko,然后使用insmod 命令存入模块:insmod hello.ko
使用lsmod 就能看到你新插入的模块: lsmod | grep hello
使用rmmod移除模块:rmmod hello
最简单的驱动就完成了。
由于Linux内核的级别控制,导致printk打印的内容不一定都能从控制台正常输出
最好的办法是打开另外的一个终端,用一个终端不停地监视并且打印输出当前系统的日志信息:
在终端下输入:
while true
do
sudo dmesg -c
sleep 1
done
这样这个终端就会每1秒查看当前系统的日志并清空。
Section TWO:LED驱动程序
思维导图设计
2.1 QT210 开发板 LED驱动程序和测试程序
驱动文件:hello.c
/************************************************
LED的驱动,在Real210A开发板上做测试 维护记录: 2011-10-31 V1.0 linux内核:2.6.35.7 驱动用法:
设备名称:Real210-led
点亮一个灯:LED_ON
熄灭一个灯:LED_OFF
点亮所有灯:ALL_LED_ON
熄灭所有灯:ALL_LED_OFF
*************************************************/
#include<linux/init.h>
#include<linux/module.h> #include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/device.h>
#include <linux/gpio.h> #define DEVICE_NAME "Real210-led" /* 设备名称 */
static int LED_Major = 0; /* 主设备号 ,系统自动分配*/ #define LED_OFF 0
#define LED_ON 1
#define ALL_LED_OFF 3
#define ALL_LED_ON 4 /* 用来指定LED所用的GPIO引脚 */
static unsigned long led_table [] =
{
//S5PV210_GPH0(_nr);
//在头文件“~/kernel/arch/arm/mach-s5pv210/include/mach/” S5PV210_GPH0(6),
S5PV210_GPH0(7),
S5PV210_GPH0(4),
S5PV210_GPH0(5),
}; static int Real210_led_open(struct inode *inode, struct file *file)
{
// MOD_INC_USE_COUNT;
printk("Real210-LED Driver Open Called!\n");
return 0;
} static int Real210_led_release(struct inode *inode, struct file *file)
{
// MOD_DEC_USE_COUNT;
printk("Real210-LED Driver Release Called!\n");
return 0;
} static int Real210_led_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
int i;
if (arg > 4)
{
return -EINVAL;
}
switch(cmd)
{
case LED_ON: //set the pin
gpio_set_value (led_table[arg], 0);
break; case LED_OFF: //clr the pin
gpio_set_value (led_table[arg], 1);
break; case ALL_LED_ON: //set all pin
for (i = 0; i < 4; i++)
gpio_set_value (led_table[i], 0);
break; case ALL_LED_OFF: //clr all pin
for (i = 0; i < 4; i++)
gpio_set_value (led_table[i], 1);
break; default:
return -EINVAL;
}
} static struct file_operations Real210_led_fops =
{
.owner = THIS_MODULE,
.open = Real210_led_open,
.release = Real210_led_release,
.ioctl = Real210_led_ioctl,
}; static struct class *led_class; static int __init Real210_led_init(void)
{ printk("Real210 LED DRIVER MODULE INIT\n"); LED_Major = register_chrdev(0, DEVICE_NAME, &Real210_led_fops);
if (LED_Major < 0)
{
printk(DEVICE_NAME " can't register major number\n");
return LED_Major;
}
printk("register Real210-LED Driver OK! Major = %d\n", LED_Major); led_class = class_create(THIS_MODULE, DEVICE_NAME);
if(IS_ERR(led_class))
{
printk("Err: failed in Real210-LED class. \n");
return -1;
} device_create(led_class, NULL, MKDEV(LED_Major, 0), NULL, DEVICE_NAME); //IO初始化 //IO方向配置
gpio_direction_output (S5PV210_GPH0(6), 1);
gpio_direction_output (S5PV210_GPH0(7), 1);
gpio_direction_output (S5PV210_GPH0(4), 1);
gpio_direction_output (S5PV210_GPH0(5), 1);
//IO初始化
gpio_set_value (S5PV210_GPH0(6), 1);
gpio_set_value (S5PV210_GPH0(7), 0); printk(DEVICE_NAME " initialized\n");
return 0;
} static void __exit Real210_led_exit(void)
{
printk("Real210 LED DRIVER MODULE EXIT\n");
unregister_chrdev(LED_Major, DEVICE_NAME);
device_destroy(led_class, MKDEV(LED_Major, 0));
class_destroy(led_class);
} module_init(Real210_led_init);
module_exit(Real210_led_exit); //MODULE_LICENSE("Dual BSD/GP"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("wzl");
MODULE_DESCRIPTION("This is an example of hello drivers");
MODULE_ALIAS("A simplest module.");
Makefile文件:
obj-m := hello.o
KDIR := /home/work/QT210/qt210_ics_kernel3.0.8
all:
make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-eabi-
clean:
rm -f *.ko *.o *.mod.o *.mod.c *.symvers
测试文件:led.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include <sys/ioctl.h> int main(int argc, char **argv)
{
unsigned int on;
unsigned int led_num;
int fd;
printf("Enter the test led !\n");
fd = open("/dev/Real210-led", 0);
if (fd < 0)
{
perror("open device led");
exit(1);
} ioctl(fd, 1, 0); //可修改本句代码 close(fd);
return 0;
}
Makefile文件:
all: led
led:led.c
arm-none-linux-gnueabi-gcc -o led led.c -static
arm-none-linux-gnueabi-strip led
clean:
@rm -vf led *.o *~
下面是调试信息:
adb shell
#mkdir mydev
#exit
adb push d:\android_led.ko /mydev
adb shell
#cd mydev
#chmod 777 android_led.ko
#insmod android_led.ko
#lsmod //查看是否加载上了。卸载命令 rmmod android_led 不要加.ko
# cat /proc/devices //也可以查看设备号和设备名。
#ls -l /dev/myled //同样。
此时myled 权限需要修改。
#chmod 777 /dev/myled
2.2 QT210 开发板 LED流水灯 驱动程序
water_led.c的代码
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/workqueue.h> static struct delayed_work my_work; //static int watercount=0;
volatile unsigned long *gph0con = NULL;
volatile unsigned long *gph0dat = NULL;
static void waterfun(void)
{
static int watercount=0;
*gph0dat = 0x1 << ((watercount++)%4);//流水灯
//printk("waterfun:watercount:%d\n",watercount);
schedule_delayed_work(&my_work,msecs_to_jiffies(1000));
} static int __init waterinit(void)
{ int ret;
gph0con = (volatile unsigned long *)ioremap(0xE0200c00, 16);
gph0dat = gph0con + 1;
*gph0con |=0x1111 ;
*gph0con &=~0xf;
INIT_DELAYED_WORK(&my_work,waterfun);
ret = schedule_delayed_work(&my_work,msecs_to_jiffies(1000));
printk("water init:ret:%d\n",ret); return 0; }
static void __exit waterexit(void)
{
cancel_delayed_work(&my_work);
//destroy_wor(my_work);
//_work(&my_work);
iounmap(gph0con); } module_init(waterinit);
module_exit(waterexit);
MODULE_LICENSE("GPL");
Makefile的代码:
obj-m :=water_led.o #KDIR :=/home/kernal_driver/linux-tiny6410/
KDIR :=/home/work/QT210/qt210_ics_kernel3.0.8
PWD :=$(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
rm -f *.o *.bak *.order *.symvers
可以看到开发板子的 D6 D7 D8呈现流水灯(D5无法控制),证明驱动成功了。
2.3 QT210 开发板 LED驱动程序和android应用程序
目的: 编写一个android应用程序来控制开发板上led灯的亮与灭.
编译环境: Ubuntu12.04
Android系统: android4.0 (linux3.0.8)
一.驱动
1. 查看原理图,QT210开发板上led D5, D6, D7, D8 对应引脚为EINT0, EINT1, EINT2, EINT3.
2. 根据底板上的EINT引脚,在核心板上找到与之相对应的引脚,最终对应到了GPIO的GPH0_0, GPH0_1, GPH0_2, GPH0_3
3. 接下来在三星 S5PV210芯片手册上找到相应寄存器.控制led灯实际就是控制相应寄存器.
S5PV210_EVT1_Usermanual_20100218.pdf
4. 编写驱动文件led.c
#include <linux/module.h>
#include <linux/kernel.h>
//#include <linux/io.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/pci.h>
#include <linux/ioctl.h>
#include <linux/init.h>
#include <linux/delay.h> #define DEVICE_NAME "leds" //设备名(/dev/leds)
#define LED_MAJOR 240 unsigned long *gph0con = NULL;
unsigned long *gph0dat = NULL; int major; static int led_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
printk(KERN_ALERT"\ncmd = %d arg = %d \n", cmd, arg);
switch(cmd)
{
case 0:
printk(KERN_ALERT"led%d off\n", arg);
switch(arg)
{
case 0:
*gph0dat &= ~0x01;
break;
case 1:
*gph0dat &= ~0x02;
break;
case 2:
*gph0dat &= ~0x04;
break;
case 3:
*gph0dat &= ~0x08;
break;
default:
break;
}
break;
case 1:
printk(KERN_ALERT"led%d on\n", arg);
switch(arg)
{
case 0:
*gph0dat |= 0x01;
break;
case 1:
*gph0dat |= 0x02;
break;
case 2:
*gph0dat |= 0x04;
break;
case 3:
*gph0dat |= 0x08;
break;
default:
break;
} break;
case 11:
printk(KERN_ALERT"led all on\n");
*gph0dat |= 0xf;
break;
case 10:
printk(KERN_ALERT"led all off\n");
*gph0dat &= ~0xf;
break;
default:
break;
} return 0;
} struct file_operations led_fops={
.owner = THIS_MODULE,
.unlocked_ioctl = led_ioctl,
}; static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR, //动态设备号
.name = DEVICE_NAME,
.fops = &led_fops,
}; static int __init led_init(void)
{
int rc;
gph0con = (unsigned long *)ioremap(0xE0200C00, 16);
gph0dat = (unsigned long *)ioremap(0xE0200C04, 8); *gph0con &= ~0xffff;
*gph0con |= 0x1111; *gph0dat &= ~0xf; rc = misc_register(&misc); if(rc<0)
{
printk(KERN_ALERT"register %s char dev error\n","leds");
return -1;
}
else
printk(KERN_ALERT" lcd module OK!\n"); return 0;
} static void __exit led_exit(void)
{
unregister_chrdev(LED_MAJOR, "leds");
printk(KERN_ALERT"module exit\n");
} module_init(led_init);
module_exit(led_exit); MODULE_LICENSE("GPL");
MODULE_AUTHOR("cw");
5. 编写led.c的Makefile. 这里将led驱动编译成模块的方式.(注意: 编写Makefile时,行的开头只能用Tab,不能用空格.)
KERNELDIR :=/home/share/210/android4.0/4.0/qt210_ics_kernel3.0.8
PWD :=$(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
obj-m:=led.o
clean:
rm -rf *.o *~core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
6. 编译
编译成功后生成led.ko模块.
7. 将led.ko 拷贝到开发板上,半加载.加载之后会在/dev/目录下生成leds这个设备.
二. Android应用程序
1. 新建一个Android应用程序
2. 打开 src/LedActivity.java, 添加public static native int led_ioctl(int i, int j);
添加一个接口是为了利用java来生成jni的头文件. src/LedActivity.java:
package com.example.led; import android.os.Bundle;
import android.app.Activity;
import android.view.Menu; public class LedActivity extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_led);
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.led, menu);
return true;
} public static native int led_ioctl(int i, int j); }
3. 编译整个android项目,将整个Led项目文件拷贝到ubuntu上.
新建一个jni目录
4. 利用java文件自动生成jni头文件.
javah -classpath bin/classes -d jni com.example.led.LedActivity
5. jni目录下编写led.c 即led测试程序led.c.
Led/jni/led.c:
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <android/log.h> #define LOG_TAG "LED" //android logcat
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__ )
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS_ _) //int main(int argc, char **argv)
jint JNICALL Java_com_example_led_LedActivity_led_1ioctl(JNIEnv *env, jclass thiz, jint led_nu, jint on)
{
int fd; fd = open("/dev/leds", O_RDWR);
if(fd < 0)
printf("Can't open /dev/leds!\n"); ioctl(fd, on, led_nu);
LOGI("led_nu=%d,state=%d\n", led_nu, on);
close(fd); return 0;
}
6. jni目录下编写Android.mk
Led/jni/Android.mk
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS)
LOCAL_MODULE := Led_ctrl
LOCAL_SRC_FILES := led.c
LOCAL_LDLIBS := -llog
LOCAL_C_INCLUDES := $(MY_ANDROID_SOURCE)/frameworks/base/core/jni/android/graphics \
$(MY_ANDROID_SOURCE)/external/skia/include/core \
$(MY_ANDROID_SOURCE)/external/skia/include/images \
$(MY_ANDROID_SOURCE)/frameworks/base/include \
$(MY_ANDROID_SOURCE)/system/core/include
include $(BUILD_SHARED_LIBRARY)
7. Led目录下运行ndk-bluild, 将led.c文件编译成so库文件.
前提是你已经安装了android-ndk 工具(http://blog.csdn.net/colwer/article/details/8944166)
8. 将生成的libLed_ctrl.so拷贝到eclipse下Led应用程序中的libs/armeabi目录(如果没有armeabi目录需手动创建一个)
9. 在应用程序布局文件中加入4个开关按钮,对应四个led开关,也可以再添加一个总开关来同时控制四个led.
res/layout/activity_led.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".LedActivity" > <ToggleButton
android:id="@+id/btn1"
android:layout_width="140dip"
android:layout_height="wrap_content"
android:textOn="led1 on"
android:textOff="led1 off"
android:layout_gravity="center_horizontal"
/>
<ToggleButton
android:id="@+id/btn2"
android:layout_width="140dip"
android:layout_height="wrap_content"
android:textOn="led2 on"
android:textOff="led2 off"
android:layout_gravity="center_horizontal"
/>
<ToggleButton
android:id="@+id/btn3"
android:layout_width="140dip"
android:layout_height="wrap_content"
android:textOn="led3 on"
android:textOff="led3 off"
android:layout_gravity="center_horizontal"
/>
<ToggleButton
android:id="@+id/btn4"
android:layout_width="140dip"
android:layout_height="wrap_content"
android:textOn="led4 on"
android:textOff="led4 off"
android:layout_gravity="center_horizontal"
/> </LinearLayout>
10. 编写java文件.
package com.example.led; import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.ToggleButton; public class LedActivity extends Activity { private static final String TAG = "LED";
private ToggleButton button1;
private ToggleButton button2;
private ToggleButton button3;
private ToggleButton button4; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_led); button1 = (ToggleButton)findViewById(R.id.btn1);
button2 = (ToggleButton)findViewById(R.id.btn2);
button3 = (ToggleButton)findViewById(R.id.btn3);
button4 = (ToggleButton)findViewById(R.id.btn4); button1.setOnClickListener(new Button.OnClickListener()
{
public void onClick(View v)
{
if (button1.isChecked())
led_ioctl(0, 1); //led1 on
else
led_ioctl(0, 0); //led1 off
}
}); button2.setOnClickListener(new Button.OnClickListener()
{
public void onClick(View v)
{
if (button2.isChecked())
led_ioctl(1, 1); //led2 on
else
led_ioctl(1, 0); //led2 off
}
}); button3.setOnClickListener(new Button.OnClickListener()
{
public void onClick(View v)
{
if (button3.isChecked())
led_ioctl(2, 1); //led3 on
else
led_ioctl(2, 0); //led3 off
}
}); button4.setOnClickListener(new Button.OnClickListener()
{
public void onClick(View v)
{
if (button4.isChecked())
led_ioctl(3, 1); //led4 on
else
led_ioctl(3, 0); //led4 off
}
});
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.led, menu);
return true;
} public static native int led_ioctl(int i, int j); static
{
System.loadLibrary("Led_ctrl"); // libs/armeabi/libLed_ctrl.so } }
编译生成Led.apk,并安装到开发板上.
至此,整个工作已经完成,开发板上打开应用程序就可以控制led了.但有几点需要注意
1. 开发板上D5这个灯已经被占用了,所以led1不能控制D5了.
2. 记住运行应用程序前确保内核中led.ko已被加载,并修改 /dev/leds的权限,否则led灯不受控制.
代码下载地址:http://download.csdn.net/detail/colwer/5403281
嵌入式Linux驱动开发日记的更多相关文章
- 嵌入式linux驱动开发之点亮led(驱动编程思想之初体验)
这节我们就开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的.个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的 ...
- 驱动编程思想之初体验 --------------- 嵌入式linux驱动开发之点亮LED
这节我们就开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的.个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的 ...
- 书籍--嵌入式Linux驱动开发
<UNIX环境高级编程>(第2版),史蒂文斯著 <深入理解 Linux 内核>(第三版) ,博韦等著 Linux设备驱动开发详解:基于最新的Linux 4.0内核 宋宝华
- 嵌入式linux驱动开发 笔记
@ 目录 首个驱动hellodrv 1.编写源码 2.编译模块 3.加载驱动 首个驱动hellodrv 3.如果下载不到,就自己编写,并编译驱动. 1.编写源码 2.编译模块 1.先写makefile ...
- linux驱动开发流程
嵌入式linux驱动开发流程嵌入式系统中,操作系统是通过各种驱动程序来驾驭硬件设备的.设备驱动程序是操作系统内核和硬件设备之间的接口,它为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个 ...
- 驱动开发学习笔记. 0.06 嵌入式linux视频开发之预备知识
驱动开发读书笔记. 0.06 嵌入式linux视频开发之预备知识 由于毕业设计选择了嵌入式linux视频开发相关的项目,于是找了相关的资料,下面是一下预备知识 UVC : UVC,全称为:USB v ...
- linux驱动开发重点关注内容--摘自《嵌入式Linux驱动模板精讲与项目实践》
本文摘自本人拙著 <嵌入式Linux驱动模板精讲与项目实践> 初步看起来Linux设备驱动开发涉及内容非常多,而须要实现驱动的设备千差万别.事实上做一段时间驱动之后回首看来主要就是下面几点 ...
- 嵌入式linux应用开发完全手册学习笔记一
2015.3.25星期三 晴 有两个星期没写学习日记了,找个时间把这段时间做的电子词典和ARM小项目总结一下. 下面的知识点总结,U-BOOT:参考PDF文档:嵌入式linux应用开发完全手册 当虚拟 ...
- 嵌入式linux驱动开发之给linux系统添加温度传感器模块
忙了几天,终于可以让ds18b20在自己的开发板的linux系统上跑了!虽然ds18b20不是什么新鲜玩意,但是想想知己可以给linux系统添加模块了还是有点小鸡冻呢! 虽然说现在硬件的资源非常丰富而 ...
随机推荐
- 04Mybatis_搭建Mybatis的开发环境
第一步:导jia包: 1.导入Mybatis的核心jia包:
- C#仿google日历asp.net简单三层版本
网上搜了很多xgcalendar的例子都是Php开发的,而且官方站上的asp.net/MVC版 在vs10 08 都报错. 所以自己重新用三层写了一下希望对大家有帮助 废话不多说了 先看看它都有些什么 ...
- JavaScript技巧[转载]
在这篇文章中将给大家分享12个有关于JavaScript的小技巧.这些小技巧可能在你的实际工作中或许能帮助你解决一些问题. 使用!!操作符转换布尔值 有时候我们需要对一个变量查检其是否存在或者检查值是 ...
- 从angularJS看MVVM
javascript厚积薄发走势异常迅猛,导致现在各种MV*框架百家争雄,MVVM从MVC演变而来,为javascript注入了全新的活力.我工作的业务不会涉及到angularJS[ng]这么重量级的 ...
- Linux下EclipseCDT工程和TFS的持续集成CI实践
在Linux下使用TFS自动构建,需要自动执行连接tfs服务器的操作,命令行文件包TEE-CLC-10.1.0.2011121402.zip,下载地址:http://www.microsoft.com ...
- Android项目实战(十七):QQ空间实现(二)—— 分享功能 / 弹出PopupWindow
这是一张QQ空间说说详情的截图. 分析: .点击右上角三个点的图标,在界面底部弹出一个区域,这个区域有一些按钮提供给我们操作 .当该区域出现的时候,详情界面便灰了,也说成透明度变化了 .当任意选了一个 ...
- java field, property,variable及getField和getDeclaredField的区别
java 里面的field ,property, attribute,variable的区别 field: 就是定义的用于保存数据的字段 property: property是用于描述类中的特征,所以 ...
- 浅谈Java五大设计原则之观察者模式
定义一下观察者模式: 观察者模式又叫 发布-订阅 模式,定义的两个对象之间是一种一对多的强依赖关系,当一个对象的状态发生改变,所有依赖它的对象 将得到通知并自动更新(摘自Hand First). ...
- 新萝卜家园GHOST WIN7系统32,64位极速装机特别版
系统来自:系统妈:http://www.xitongma.com 新萝卜家园GHOST win7系统32位极速装机特别版 V2016年3月 系统概述 新萝卜家园ghost win7系统32位极速装机特 ...
- 【代码笔记】iOS-登陆单例
一,工程图. 二,代码. UserInfo.h #import <Foundation/Foundation.h> @interface UserInfo : NSObject + (id ...