class.c 添加中文注释(2)
/* Class Device Stuff */ int class_device_create_file(struct class_device * class_dev,
const struct class_device_attribute * attr)
{
int error = -EINVAL; /* [cgw]: class_dev指针不为空 */
if (class_dev)
/* [cgw]: 为class_dev->kobj对象创建一个属性文件 */
error = sysfs_create_file(&class_dev->kobj, &attr->attr);
return error;
} void class_device_remove_file(struct class_device * class_dev,
const struct class_device_attribute * attr)
{
/* [cgw]: class_dev指针不为空 */
if (class_dev)
/* [cgw]: 删除class_dev->kobj对象对应的一个属性文件 */
sysfs_remove_file(&class_dev->kobj, &attr->attr);
} int class_device_create_bin_file(struct class_device *class_dev,
struct bin_attribute *attr)
{
int error = -EINVAL; /* [cgw]: class_dev指针不为空 */
if (class_dev)
/* [cgw]: 为class_dev->kobj对象创建一个BIN文件 */
error = sysfs_create_bin_file(&class_dev->kobj, attr);
return error;
} void class_device_remove_bin_file(struct class_device *class_dev,
struct bin_attribute *attr)
{
/* [cgw]: class_dev指针不为空 */
if (class_dev)
/* [cgw]: 删除class_dev->kobj对象对应的一个BIN文件 */
sysfs_remove_bin_file(&class_dev->kobj, attr);
} static ssize_t
class_device_attr_show(struct kobject * kobj, struct attribute * attr,
char * buf)
{
/* [cgw]: 找出包含这个attr的struct class_device_attribute *指针 */
struct class_device_attribute * class_dev_attr = to_class_dev_attr(attr);
/* [cgw]: 找出包含这个kobj的struct class_device *指针
*/
struct class_device * cd = to_class_dev(kobj);
ssize_t ret = ; /* [cgw]: class_dev_attr->show指针不为空 */
if (class_dev_attr->show)
/* [cgw]: 调用class_dev_attr->show方法 */
ret = class_dev_attr->show(cd, buf);
return ret;
} static ssize_t
class_device_attr_store(struct kobject * kobj, struct attribute * attr,
const char * buf, size_t count)
{
/* [cgw]: 找出包含这个attr的struct class_device_attribute *指针 */
struct class_device_attribute * class_dev_attr = to_class_dev_attr(attr);
/* [cgw]: 找出包含这个kobj的struct class_device *指针
*/
struct class_device * cd = to_class_dev(kobj);
ssize_t ret = ; /* [cgw]: class_dev_attr->store指针不为空 */
if (class_dev_attr->store)
/* [cgw]: 调用class_dev_attr->store方法 */
ret = class_dev_attr->store(cd, buf, count);
return ret;
} static struct sysfs_ops class_dev_sysfs_ops = {
.show = class_device_attr_show,
.store = class_device_attr_store,
}; static void class_dev_release(struct kobject * kobj)
{
/* [cgw]: 找出包含这个kobj的struct class_device *指针 */
struct class_device *cd = to_class_dev(kobj);
/* [cgw]: cls指向class_device的成员class */
struct class * cls = cd->class; pr_debug("device class '%s': release.\n", cd->class_id); /* [cgw]: 释放这个class_device的class_device_attribute内存空间
* 并把class_device_attribute指针置为空
*/
kfree(cd->devt_attr);
cd->devt_attr = NULL; /* [cgw]: 调用class_device->release 方法,
* 释放这个已分配的struct class_device *的内存空间
*/
if (cd->release)
cd->release(cd);
else if (cls->release)
/* [cgw]: 调用class_device->class->release 方法
* 释放这个已分配的struct class *的内存空间
*/
cls->release(cd);
else {
printk(KERN_ERR "Class Device '%s' does not have a release() function, "
"it is broken and must be fixed.\n",
cd->class_id);
WARN_ON();
}
} static struct kobj_type ktype_class_device = {
.sysfs_ops = &class_dev_sysfs_ops,
.release = class_dev_release,
}; static int class_uevent_filter(struct kset *kset, struct kobject *kobj)
{
/* [cgw]: 找到kobj所属的类型ktype */
struct kobj_type *ktype = get_ktype(kobj); /* [cgw]: 这个kobj的类型ktype属于ktype_class_device */
if (ktype == &ktype_class_device) {
/* [cgw]: 找到包含这个kobj 的class_dev指针
*/
struct class_device *class_dev = to_class_dev(kobj);
/* [cgw]: class_dev->class指针不为空 */
if (class_dev->class)
return ;
}
return ;
} static const char *class_uevent_name(struct kset *kset, struct kobject *kobj)
{
/* [cgw]: 找到包含这个kobj 的class_dev指针
*/
struct class_device *class_dev = to_class_dev(kobj); /* [cgw]: 返回class_dev下class的名字 */
return class_dev->class->name;
} #ifdef CONFIG_SYSFS_DEPRECATED
char *make_class_name(const char *name, struct kobject *kobj)
{
char *class_name;
int size;
/* [cgw]: 找出这个kobj的名字
* 计算两个字符串的总长度并+2,
*/
size = strlen(name) + strlen(kobject_name(kobj)) + ;
/* [cgw]: 分配一个size字节的内存空间 */
class_name = kmalloc(size, GFP_KERNEL);
/* [cgw]: 分配失败 */
if (!class_name)
return NULL;
/* [cgw] : 把名字name填装到class_name */
strcpy(class_name, name);
/* [cgw] : 在名字name末尾添加":" */
strcat(class_name, ":");
/* [cgw] : 合并字符串,name+":"+kobj->k_name */
strcat(class_name, kobject_name(kobj));
return class_name;
} static int make_deprecated_class_device_links(struct class_device *class_dev)
{
char *class_name;
int error; /* [cgw]: class_dev->dev指针为空 */
if (!class_dev->dev)
return ;
/* [cgw]: 合并class_dev->class->name和class_dev->kobj->k_name
*/
class_name = make_class_name(class_dev->class->name, &class_dev->kobj);
/* [cgw]: 合并成功 */
if (class_name)
/* [cgw]: 在class_dev->dev->kobj对象目录下创建一个链表
* 设置这个链表的名字为class_name
*/
error = sysfs_create_link(&class_dev->dev->kobj,
&class_dev->kobj, class_name);
else
error = -ENOMEM;
/* [cgw]: 释放class_name内存空间,class_name在这里只做临时作用 */
kfree(class_name);
return error;
} static void remove_deprecated_class_device_links(struct class_device *class_dev)
{
char *class_name; /* [cgw]: class_dev->dev指针为空 */
if (!class_dev->dev)
return; /* [cgw]: 合并class_dev->class->name和class_dev->kobj->k_name
*/
class_name = make_class_name(class_dev->class->name, &class_dev->kobj);
if (class_name)
/* [cgw] : 从class_dev->dev->kobj对象目录下删除一个名字为
* class_name的链表
*/
sysfs_remove_link(&class_dev->dev->kobj, class_name);
/* [cgw] : 释放class_name的内存空间 */
kfree(class_name);
}
#else
static inline int make_deprecated_class_device_links(struct class_device *cd)
{ return ; }
static void remove_deprecated_class_device_links(struct class_device *cd)
{ }
#endif static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp,
int num_envp, char *buffer, int buffer_size)
{
/* [cgw]: 找出包含这个kobj的class_device结构体指针 */
struct class_device *class_dev = to_class_dev(kobj);
struct device *dev = class_dev->dev;
int i = ;
int length = ;
int retval = ; pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id); /* [cgw]: 主设备号不为0 */
if (MAJOR(class_dev->devt)) {
/* [cgw]: 格式化"MAJOR= MAJOR(class_dev->devt)"填装到buffer中
* 并把buffer指针储存在envp数组
*/
add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"MAJOR=%u", MAJOR(class_dev->devt)); /* [cgw]: 格式化"MAJOR= MINOR(class_dev->devt)"填装到buffer中
* 并把buffer指针储存在envp数组
*/
add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"MINOR=%u", MINOR(class_dev->devt));
} /* [cgw]: dev指针不为空 */
if (dev) {
/* [cgw]: 获得dev->kobj所在的路径 */
const char *path = kobject_get_path(&, GFP_KERNEL);
/* [cgw]: 获取成功 */
if (path) {
/* [cgw]: 格式化"PHYSDEVPATH=path"填装到buffer中
* 并把buffer指针储存在环境变量envp数组,i+1
*/
add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"PHYSDEVPATH=%s", path);
/* [cgw]: 释放path的内存空间 */
kfree(path);
} /* [cgw]: dev->bus指针不为空 */
if (dev->bus)
/* [cgw]: 格式化"PHYSDEVBUS=dev->bus->name"填装到buffer中
* 并把buffer指针储存在环境变量envp数组,i+1
*/
add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"PHYSDEVBUS=%s", dev->bus->name); /* [cgw]: dev->driver指针不为空 */
if (dev->driver)
/* [cgw]: 格式化"PHYSDEVDRIVER=dev->driver->name"填装到buffer中
* 并把buffer指针储存在环境变量envp数组,i+1
*/
add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"PHYSDEVDRIVER=%s", dev->driver->name);
} /* terminate, set to next free slot, shrink available space */
/* [cgw]: 清空下一个环境变量,envp[i]是一个指针,把这个指针置0 */
envp[i] = NULL;
/* [cgw]: 重置envp的指针,指向下一个环境变量envp[i] */
envp = &envp[i];
/* [cgw]: 计算环境变量数组剩下的可用大小 */
num_envp -= i;
/* [cgw]: 重置buffer指针,指向buffer + length */
buffer = &buffer[length];
/* [cgw]: 计算环境变量buffer剩下的可用大小 */
buffer_size -= length; /* [cgw]: class_dev->uevent指针不为空 */
if (class_dev->uevent) {
/* have the class device specific function add its stuff */
/* [cgw]: 调用class_dev->uevent方法 */
retval = class_dev->uevent(class_dev, envp, num_envp,
buffer, buffer_size);
if (retval)
pr_debug("class_dev->uevent() returned %d\n", retval);
} else if (class_dev->class->uevent) {
/* have the class specific function add its stuff */
/* [cgw]: 调用class_dev->class->uevent方法 */
retval = class_dev->class->uevent(class_dev, envp, num_envp,
buffer, buffer_size);
if (retval)
pr_debug("class->uevent() returned %d\n", retval);
} return retval;
} static struct kset_uevent_ops class_uevent_ops = {
.filter = class_uevent_filter,
.name = class_uevent_name,
.uevent = class_uevent,
}; static decl_subsys(class_obj, &ktype_class_device, &class_uevent_ops); static int class_device_add_attrs(struct class_device * cd)
{
int i;
int error = ;
struct class * cls = cd->class; /* [cgw]: cls->class_dev_attrs指针不为空,即分配了class device 的属性 */
if (cls->class_dev_attrs) {
/* [cgw]: 历遍class_dev_attrs[]数组,如果该属性名字不为空,则
* 对应地创建一个属性文件
*/
for (i = ; attr_name(cls->class_dev_attrs[i]); i++) {
/* [cgw]: 创建一个class device属性文件 */
error = class_device_create_file(cd,
&cls->class_dev_attrs[i]);
if (error)
goto Err;
}
}
Done:
return error;
Err:
/* [cgw]: 删除class device的所有属性文件 */
while (--i >= )
class_device_remove_file(cd,&cls->class_dev_attrs[i]);
goto Done;
} static void class_device_remove_attrs(struct class_device * cd)
{
int i;
struct class * cls = cd->class; /* [cgw]: cls->class_dev_attrs指针不为空,即此前已经添加了这个属性列表 */
if (cls->class_dev_attrs) {
/* [cgw]: 历遍class_dev_attrs[]数组,如果该属性名字不为空,则
* 对应地删除一个属性文件
*/
for (i = ; attr_name(cls->class_dev_attrs[i]); i++)
/* [cgw]: 删除一个属性文件 */
class_device_remove_file(cd,&cls->class_dev_attrs[i]);
}
} static int class_device_add_groups(struct class_device * cd)
{
int i;
int error = ; /* [cgw]: cd->groups指针不为空 */
if (cd->groups) {
/* [cgw]: 历遍groups[],对应每个groups创建一个属性组 */
for (i = ; cd->groups[i]; i++) {
/* [cgw]: 创建一个属性组 */
error = sysfs_create_group(&cd->kobj, cd->groups[i]);
/* [cgw]: 创建失败 */
if (error) {
/* [cgw]: 删除所有属性组 */
while (--i >= )
/* [cgw]: 删除一个属性组 */
sysfs_remove_group(&cd->kobj, cd->groups[i]);
goto out;
}
}
}
out:
return error;
} static void class_device_remove_groups(struct class_device * cd)
{
int i;
/* [cgw]: cd->groups指针不为空 */
if (cd->groups) {
/* [cgw]: 历遍groups[],删除所有属性组 */
for (i = ; cd->groups[i]; i++) {
/* [cgw]: 删除一个属性组 */
sysfs_remove_group(&cd->kobj, cd->groups[i]);
}
}
} static ssize_t show_dev(struct class_device *class_dev, char *buf)
{
/* [cgw]: 格式化class_dev->devt的主和次设备号为字符串,
* 填装到buf中
*/
return print_dev_t(buf, class_dev->devt);
} static ssize_t store_uevent(struct class_device *class_dev,
const char *buf, size_t count)
{
/* [cgw]: 对class_dev->kobj产生一个KOBJ_ADD事件通知用户空间 */
kobject_uevent(&class_dev->kobj, KOBJ_ADD);
return count;
} void class_device_initialize(struct class_device *class_dev)
{
/* [cgw]: 分配class_dev->kobj.kset,指向&class_obj_subsys */
kobj_set_kset_s(class_dev, class_obj_subsys);
/* [cgw]: 初始化class_dev->kobj */
kobject_init(&class_dev->kobj);
/* [cgw]: 初始化class_dev->node链表 */
INIT_LIST_HEAD(&class_dev->node);
} int class_device_add(struct class_device *class_dev)
{
struct class *parent_class = NULL;
struct class_device *parent_class_dev = NULL;
struct class_interface *class_intf;
int error = -EINVAL; /* [cgw]: class_dev->kobj引用计数+1
* 并根据kobj找到包含这个kobj的结构体指针class_dev
*/
class_dev = class_device_get(class_dev);
/* [cgw]: class_dev指针为空 */
if (!class_dev)
return -EINVAL; /* [cgw]: class_dev->class_id长度为0 */
if (!strlen(class_dev->class_id))
goto out1; /* [cgw]: class->kobj引用计数+1
* 并根据kobj找到包含这个kobj的结构体指针class
*/
parent_class = class_get(class_dev->class);
/* [cgw]: parent_class指针为空 */
if (!parent_class)
goto out1; /* [cgw]: 找出class_dev的父节点,并且class_dev->parent->kobj
* 引用计数+1
*/
parent_class_dev = class_device_get(class_dev->parent); pr_debug("CLASS: registering class device: ID = '%s'\n",
class_dev->class_id); /* first, register with generic layer. */
/* [cgw]: 以class_dev->class_id作为class_dev->kobj的名字 */
error = kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id);
/* [cgw]: 设置class_dev->kobj的名字失败 */
if (error)
goto out2; /* [cgw]: parent_class_dev指针不为空 */
if (parent_class_dev)
/* [cgw]: 设置class_dev的kobj的父节点为class_dev父节点的kobj */
class_dev->kobj.parent = &parent_class_dev->kobj;
else
/* [cgw]: 设置class_dev的kobj的父节点为class->subsys.kobj
* 设置class_dev的kobj的在最顶层,父节点就是kset.kobj
*/
class_dev->kobj.parent = &parent_class->subsys.kobj; /* [cgw]: 添加kobj到层,实际上是把kobj添加到kset集合
* entry插入到kobj->kset->list链表中, 为这个kobj创建目录,
* 即加入到sysfs目录,并为这个kobj添加属性
*/
error = kobject_add(&class_dev->kobj);
/* [cgw]: 添加失败 */
if (error)
goto out2; /* add the needed attributes to this device */
/* [cgw]: 在class_dev->kobj目录下创建一个名为subsystem
* 的链表,指向parent_class->subsys.kobj
*/
error = sysfs_create_link(&class_dev->kobj,
&parent_class->subsys.kobj, "subsystem");
/* [cgw]: 创建失败 */
if (error)
goto out3;
/* [cgw]: 设置class_dev的属性名为uevent */
class_dev->uevent_attr.attr.name = "uevent";
/* [cgw]: 权限为S_IWUSR */
class_dev->uevent_attr.attr.mode = S_IWUSR;
/* [cgw]: 设置拥有这个class_dev->uevent_attr属性的模块 */
class_dev->uevent_attr.attr.owner = parent_class->owner;
/* [cgw]: 分配class_dev->uevent_attr.store的方法 */
class_dev->uevent_attr.store = store_uevent;
/* [cgw]: 为class_dev->kobj创建一个属性为class_dev->uevent_attr的
* 属性文件
*/
error = class_device_create_file(class_dev, &class_dev->uevent_attr);
/* [cgw]: 创建失败 */
if (error)
goto out3;
/* [cgw]: 主设备号不为0 */
if (MAJOR(class_dev->devt)) {
struct class_device_attribute *attr;
/* [cgw]: 分配一块sizeof(*attr)字节大小的内存空间 */
attr = kzalloc(sizeof(*attr), GFP_KERNEL);
/* [cgw]: 分配失败 */
if (!attr) {
error = -ENOMEM;
goto out4;
}
/* [cgw]: attr的属性名为dev */
attr->attr.name = "dev";
/* [cgw]: attr的权限为S_IRUGO */
attr->attr.mode = S_IRUGO;
/* [cgw]: 设置拥有这个attr->attr属性的模块 */
attr->attr.owner = parent_class->owner;
/* [cgw]: 分配attr->show的方法 */
attr->show = show_dev;
/* [cgw]: 为class_dev->kobj对象创建一个attr属性文件 */
error = class_device_create_file(class_dev, attr);
/* [cgw]: 创建失败 */
if (error) {
/* [cgw]: 释放attr的内存空间 */
kfree(attr);
goto out4;
}
/* [cgw]: class_dev->devt_attr指向attr */
class_dev->devt_attr = attr;
} /* [cgw]: 为class_dev->kobj添加属性文件列表,属性文件
* 来自于class_dev->class->class_dev_attrs[]
*/
error = class_device_add_attrs(class_dev);
/* [cgw]: 添加失败 */
if (error)
goto out5; /* [cgw]: class_dev->dev指针不为空 */
if (class_dev->dev) {
/* [cgw]: 在class_dev->kobj目录下创建一个名为device的链表
* 指向class_dev->dev->kobj
*/
error = sysfs_create_link(&class_dev->kobj,
&class_dev->dev->kobj, "device");
/* [cgw]: 创建失败 */
if (error)
goto out6;
} /* [cgw]: 添加属性组 */
error = class_device_add_groups(class_dev);
/* [cgw]: 添加失败 */
if (error)
goto out7; /* [cgw]: 合并class_dev->class->name和class_dev->kobj->k_name
* class_dev->dev->kobj对象目录下创建一个链表
*/
error = make_deprecated_class_device_links(class_dev);
/* [cgw]: 创建失败 */
if (error)
goto out8; /* [cgw]: 通知用户空间,产生一个KOBJ_ADD事件 */
kobject_uevent(&class_dev->kobj, KOBJ_ADD); /* notify any interfaces this device is now here */
/* [cgw]: 获得信号量 */
down(&parent_class->sem);
/* [cgw]: 插入一个新节点class_dev->node到parent_class->children节点前 */
list_add_tail(&class_dev->node, &parent_class->children);
/* [cgw]: 从parent_class->interfaces的下一节点起,历遍这个链表,直到又回到
* 头节点(环形链表)
*/
list_for_each_entry(class_intf, &parent_class->interfaces, node) {
/* [cgw]: 这个节点的class_intf->add的指针不为空 */
if (class_intf->add)
/* [cgw]: 调用class_intf->add方法 */
class_intf->add(class_dev, class_intf);
}
/* [cgw]: 释放信号量 */
up(&parent_class->sem); goto out1; out8:
/* [cgw]: 删除属性组 */
class_device_remove_groups(class_dev);
out7:
/* [cgw]: class_dev->dev指针不为空 */
if (class_dev->dev)
/* [cgw]: 删除class_dev->kobj目录下,名为device的链表 */
sysfs_remove_link(&class_dev->kobj, "device");
out6:
/* [cgw]: 删除class_dev所有属性文件 */
class_device_remove_attrs(class_dev);
out5:
/* [cgw]: class_dev->devt_attr指针不为空,即已经分配了class_dev->devt_attr属性 */
if (class_dev->devt_attr)
/* [cgw]: 删除class_dev->kobj对象对应的一个class_dev->devt_attr属性文件 */
class_device_remove_file(class_dev, class_dev->devt_attr);
out4:
/* [cgw]: 删除class_dev->kobj对象对应的一个class_dev->uevent_attr属性文件 */
class_device_remove_file(class_dev, &class_dev->uevent_attr);
out3:
/* [cgw]: 删除class_dev->kobj,从sysfs中删除对应class_dev->kobj的
* 条目
*/
kobject_del(&class_dev->kobj);
out2:
/* [cgw]: parent_class_dev指针不为空(class_dev->parent) */
if(parent_class_dev)
/* [cgw]: parent_class_dev->kobj引用计数-1 */
class_device_put(parent_class_dev);
/* [cgw]: parent_class->subsys.kset.kobj引用计数-1 */
class_put(parent_class);
out1:
/* [cgw]: class_dev->kobj引用计数-1 */
class_device_put(class_dev);
return error;
}
class.c 添加中文注释(2)的更多相关文章
- Python中添加中文注释报错SyntaxError: Non-UTF-8 code starting with '\xc1'
问题:在文本编辑器中编辑Python文件时添加中文注释,运行python文件时报错.SyntaxError: Non-UTF-8 code starting with '\xc1' 解决方法:在文本开 ...
- char_dev.c 添加中文注释
char_dev.c里的中文注释,仅代表个人理解,仅供参考.如有错误之处,请指出,谢谢! /* * linux/fs/char_dev.c * * Copyright (C) 1991, 1992 L ...
- 在mapper.xml映射文件中添加中文注释报错
问题描述: 在写mapper.xml文件时,想给操作数据库语句添加一些中文注释,添加后运行报如下错误: 思考 可能是写了中文注释,编译器在解析xml文件时,未能成功转码,从而导致乱码.但是文件开头也采 ...
- class.c 添加中文注释(1)
注释仅代表个人理解,仅供参考. /* * class.c - basic device class management * * Copyright (c) 2002-3 Patrick Mochel ...
- class.c 添加中文注释(3)
int class_device_register(struct class_device *class_dev) { /* [cgw]: 初始化一个struct class_device */ cl ...
- sass中文注释的解决方法和一些简单用法
最近用sass来编写项目中的css,发现不能添加中文注释,报错如下 于是查阅了一下发现需要在scss文件顶部加上@charset "utf-8"即可解决. 在此顺便记录一些sass ...
- 关于 Keil uVision2 中文注释会显示不完整,字体不正常的问题
在Keil中添加中文注释经常出现这样情况: ,注释文字不正常! 解决方案:Edit---->Option----->选择color&fonts选项卡中的Editor c Files ...
- Eclipse MyBatis generator 1.3.7插件的核心包(中文注释)
一.最近刚搭建一个项目框架,使用springboot + mybatis,但是在使用Eclipse开发时发现开发mybatis的Dao.mapper.xml和entity时特别不方便,手工去写肯定是不 ...
- mysql数据库导出模型到powerdesigner,PDM图形窗口中显示数据列的中文注释
1,mysql数据库导出模型到powerdesigner 2,CRL+Shift+X 3,复制以下内容,执行 '******************************************** ...
随机推荐
- Circuit Breaker Pattern(断路器模式)
Handle faults that may take a variable amount of time to rectify when connecting to a remote service ...
- 创建ASP.NET Core MVC应用程序(5)-添加查询功能 & 新字段
创建ASP.NET Core MVC应用程序(5)-添加查询功能 & 新字段 添加查询功能 本文将实现通过Name查询用户信息. 首先更新GetAll方法以启用查询: public async ...
- 自己实现简单的AOP(三) 实现增强四项基本功能
前面的两篇随笔,都是只是个铺垫,真正实现增强四项基本功能的重头戏,在本篇随笔中, 本文将通过AOP实现如下的四个基本功能: /// <para>1.自动管理数据库连接[可选]</pa ...
- 【C#】DataRowState演变备忘
环境:.net 2.0 DataRow的行状态一段时间不用就会吃不准,记录一下,备查. DataRowState 演变表 行属于如下状态时进行右边操作→ 后的状态演变 添加到表 dt.Rows.Add ...
- MongoDb gridfs-ngnix文件存储方案
在各类系统应用服务端开发中,我们经常会遇到文件存储的问题. 常见的磁盘文件系统,DBMS传统文件流存储.今天我们看一下基于NoSQL数据库MongoDb的存储方案.笔者环境 以CentOS ...
- CSS笔记之伪类与伪元素
伪类分为两种:UI伪类 与 结构化伪类 UI伪类:a:link{} a:hover{} a:active{} a:visited{} input[type='text']:focus{} ...
- 【单页应用巨坑之History】细数History带给单页应用的噩梦
前言 在我们日常的网页浏览中,我们非常喜欢做一个操作:点击浏览器的前进后退在Ajax技术出现后,有些时候前进后退就会给开发者带来困扰,甚至一些开发者试图去干掉History随着Html5的发展,移动端 ...
- ArcGIS工具之ET GeoWizards、GeoTools、GeoTools
简介 ET GeoWizards是ET SpatialTechniques一套基于ArcGIS的工具集,从2002年开始,其设计的初衷: (1)让ArcView用户拥有ArcEditor甚至ArcIn ...
- Docker dockerfile创建Eclipse镜像初试
抽空初步阅读了Docker技术入门与实战 [Kindle电子书] http://www.cnblogs.com/2018/p/4600116.html 现在想首先在开发环境下引入统一的环境,由于开发中 ...
- Android动画例子。
例子一: 补间动画效果,从右进,从左出. ImageSwitcher mImageSwitcher = new ImageSwitcher(this); mImageSwitcher.setFacto ...