I.MX6 bq27441 driver hacking
/************************************************************************** I.MX6 bq27441 driver hacking* 声明:* 本文主要是记录对电池计量芯片bq27441芯片驱动注册过程进行代码跟踪。** 2016-2-19 深圳 南山平山村 曾剑锋 ************************************************************************/static int __init bq27x00_battery_init(void) {int ret;ret = bq27x00_battery_i2c_init(); -----------------------+if (ret) |return ret; ||ret = bq27x00_battery_platform_init(); |if (ret) |bq27x00_battery_i2c_exit(); -----------------------*-----+| |return ret; | | } | | module_init(bq27x00_battery_init); | || | static void __exit bq27x00_battery_exit(void) | | { | |bq27x00_battery_platform_exit(); | |bq27x00_battery_i2c_exit(); | | } | | module_exit(bq27x00_battery_exit); | || | MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); | | MODULE_DESCRIPTION("BQ27x00 battery monitor driver"); | | MODULE_LICENSE("GPL"); | || || | static inline int __init bq27x00_battery_i2c_init(void) <-------+ | { |int ret = i2c_add_driver(&bq27x00_battery_driver); -----------+ |if (ret) | |printk(KERN_ERR "Unable to register BQ27x00 i2c driver\n"); | || |return ret; | | } | || | static inline void __exit bq27x00_battery_i2c_exit(void) <-------*--+ { |i2c_del_driver(&bq27x00_battery_driver); | } ||| static const struct i2c_device_id bq27x00_id[] = { <------+ |{ "bq27200", BQ27200 }, | |{ "bq27500", BQ27500 }, | |{ "bq27520", BQ27520 }, | |{ "bq274xx", BQ274XX }, | |{ "bq276xx", BQ276XX }, | |{ "bq2753x", BQ2753X }, | |{}, | | }; | | MODULE_DEVICE_TABLE(i2c, bq27x00_id); | || | static struct i2c_driver bq27x00_battery_driver = { <---|------+.driver = { |.name = "bq27x00-battery", |}, |.probe = bq27x00_battery_probe, -------*-------+.remove = bq27x00_battery_remove, | |.id_table = bq27x00_id, --------+ | }; || static int __init bq27x00_battery_probe(struct i2c_client *client, <-+const struct i2c_device_id *id) {char *name;struct bq27x00_device_info *di;int num;int retval = 0;u8 *regs;/* Get new ID for the new battery device */retval = idr_pre_get(&battery_id, GFP_KERNEL);if (retval == 0)return -ENOMEM;mutex_lock(&battery_mutex);retval = idr_get_new(&battery_id, client, &num);mutex_unlock(&battery_mutex);if (retval < 0)return retval;name = kasprintf(GFP_KERNEL, "%s-%d", id->name, num);if (!name) {dev_err(&client->dev, "failed to allocate device name\n");retval = -ENOMEM;goto batt_failed_1;}di = kzalloc(sizeof(*di), GFP_KERNEL);if (!di) {dev_err(&client->dev, "failed to allocate device info data\n");retval = -ENOMEM;goto batt_failed_2;}di->id = num;di->dev = &client->dev;di->chip = id->driver_data;di->bat.name = name;di->bus.read = &bq27xxx_read_i2c; -------------+di->bus.write = &bq27xxx_write_i2c; -------------*-+di->bus.blk_read = bq27xxx_read_i2c_blk; -------------*-*-+di->bus.blk_write = bq27xxx_write_i2c_blk; -------------*-*-*-+di->dm_regs = NULL; | | | |di->dm_regs_count = 0; | | | || | | |if (di->chip == BQ27200) | | | |regs = bq27200_regs; | | | |else if (di->chip == BQ27500) | | | |regs = bq27500_regs; | | | |else if (di->chip == BQ27520) | | | |regs = bq27520_regs; | | | |else if (di->chip == BQ2753X) | | | |regs = bq2753x_regs; | | | |else if (di->chip == BQ274XX) { | | | |regs = bq274xx_regs; | | | |di->dm_regs = bq274xx_dm_regs; -------------*-*-*-*-+di->dm_regs_count = ARRAY_SIZE(bq274xx_dm_regs); | | | | |} else if (di->chip == BQ276XX) { | | | | |/* commands are same as bq274xx, only DM is different */ | | | | |regs = bq276xx_regs; | | | | |di->dm_regs = bq276xx_dm_regs; | | | | |di->dm_regs_count = ARRAY_SIZE(bq276xx_dm_regs); | | | | |} else { | | | | |dev_err(&client->dev, | | | | |"Unexpected gas gague: %d\n", di->chip); | | | | |regs = bq27520_regs; | | | | |} | | | | || | | | |memcpy(di->regs, regs, NUM_REGS); | | | | || | | | |di->fw_ver = bq27x00_battery_read_fw_version(di); | | | | |dev_info(&client->dev, "Gas Guage fw version is 0x%04x\n", | | | | |di->fw_ver); | | | | || | | | |retval = bq27x00_powersupply_init(di); -------*-*-*-*-*-+if (retval) | | | | | |goto batt_failed_3; | | | | | || | | | | |/* Schedule a polling after about 1 min */ | | | | | |schedule_delayed_work(&di->work, 60 * HZ); | | | | | || | | | | |i2c_set_clientdata(client, di); | | | | | |retval = sysfs_create_group(&client->dev.kobj, | | | | | |&bq27x00_attr_group); | | | | | |if (retval) | | | | | |dev_err(&client->dev, "could not create sysfs files\n"); | | | | | || | | | | |return 0; | | | | | || | | | | | batt_failed_3: | | | | | |kfree(di); | | | | | | batt_failed_2: | | | | | |kfree(name); | | | | | | batt_failed_1: | | | | | |mutex_lock(&battery_mutex); | | | | | |idr_remove(&battery_id, num); | | | | | |mutex_unlock(&battery_mutex); | | | | | || | | | | |return retval; | | | | | | } | | | | | || | | | | | static int bq27xxx_read_i2c(struct bq27x00_device_info *di, <-----+ | | | | |u8 reg, bool single) | | | | | { | | | | |struct i2c_client *client = to_i2c_client(di->dev); | | | | |struct i2c_msg msg[2]; | | | | |unsigned char data[2]; | | | | |int ret; | | | | || | | | |if (!client->adapter) | | | | |return -ENODEV; | | | | || | | | |msg[0].addr = client->addr; | | | | |msg[0].flags = 0; | | | | |msg[0].buf = ® | | | | |msg[0].len = sizeof(reg); | | | | |msg[1].addr = client->addr; | | | | |msg[1].flags = I2C_M_RD; | | | | |msg[1].buf = data; | | | | |if (single) | | | | |msg[1].len = 1; | | | | |else | | | | |msg[1].len = 2; | | | | || | | | |ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); | | | | |if (ret < 0) | | | | |return ret; | | | | || | | | |if (!single) | | | | |ret = get_unaligned_le16(data); | | | | |else | | | | |ret = data[0]; | | | | || | | | |return ret; | | | | | } | | | | || | | | | static int bq27xxx_write_i2c(struct bq27x00_device_info *di, <----+ | | | |u8 reg, int value, bool single) | | | | { | | | |struct i2c_client *client = to_i2c_client(di->dev); | | | |struct i2c_msg msg; | | | |unsigned char data[4]; | | | |int ret; | | | || | | |if (!client->adapter) | | | |return -ENODEV; | | | || | | |data[0] = reg; | | | |if (single) { | | | |data[1] = (unsigned char)value; | | | |msg.len = 2; | | | |} else { | | | |put_unaligned_le16(value, &data[1]); | | | |msg.len = 3; | | | |} | | | || | | |msg.buf = data; | | | |msg.addr = client->addr; | | | |msg.flags = 0; | | | || | | |ret = i2c_transfer(client->adapter, &msg, 1); | | | |if (ret < 0) | | | |return ret; | | | || | | |return 0; | | | | } | | | || | | | static int bq27xxx_read_i2c_blk(struct bq27x00_device_info *di, <-----+ | | |u8 reg, u8 *data, u8 len) | | | { | | |struct i2c_client *client = to_i2c_client(di->dev); | | |struct i2c_msg msg[2]; | | |int ret; | | || | |if (!client->adapter) | | |return -ENODEV; | | || | |msg[0].addr = client->addr; | | |msg[0].flags = 0; | | |msg[0].buf = ® | | |msg[0].len = 1; | | || | |msg[1].addr = client->addr; | | |msg[1].flags = I2C_M_RD; | | |msg[1].buf = data; | | |msg[1].len = len; | | || | |ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); | | |if (ret < 0) | | |return ret; | | || | |return ret; | | | } | | || | | static int bq27xxx_write_i2c_blk(struct bq27x00_device_info *di, <------+ | |u8 reg, u8 *data, u8 sz) | | { | |struct i2c_client *client = to_i2c_client(di->dev); | |struct i2c_msg msg; | |int ret; | |u8 buf[33]; | || |if (!client->adapter) | |return -ENODEV; | || |buf[0] = reg; | |memcpy(&buf[1], data, sz); | || |msg.buf = buf; | |msg.addr = client->addr; | |msg.flags = 0; | |msg.len = sz + 1; | || |ret = i2c_transfer(client->adapter, &msg, 1); | |if (ret < 0) | |return ret; | || |return 0; | | } | || | static struct dm_reg bq274xx_dm_regs[] = { <-----------------+ |{82, 0, 2, 1000}, /* Qmax */ |{82, 5, 1, 0x81}, /* Load Select */ |{82, 10, 2, 1340}, /* Design Capacity */ |{82, 12, 2, 3700}, /* Design Energy */ |{82, 16, 2, 3250}, /* Terminate Voltage */ |{82, 27, 2, 110}, /* Taper rate */ | }; || static int __init bq27x00_powersupply_init( <-------------------+struct bq27x00_device_info *di) {int ret;di->bat.type = POWER_SUPPLY_TYPE_BATTERY;if (di->chip == BQ274XX) {set_properties_array(di, bq274xx_battery_props,ARRAY_SIZE(bq274xx_battery_props));} else if (di->chip == BQ276XX) {set_properties_array(di, bq276xx_battery_props,ARRAY_SIZE(bq276xx_battery_props));} else if (di->chip == BQ27520) {set_properties_array(di, bq27520_battery_props,ARRAY_SIZE(bq27520_battery_props));} else if (di->chip == BQ2753X) {set_properties_array(di, bq2753x_battery_props,ARRAY_SIZE(bq2753x_battery_props));} else {set_properties_array(di, bq27x00_battery_props,ARRAY_SIZE(bq27x00_battery_props));}di->bat.get_property = bq27x00_battery_get_property;di->bat.external_power_changed = bq27x00_external_power_changed;INIT_DELAYED_WORK(&di->work, bq27x00_battery_poll); -------------+mutex_init(&di->lock); ||ret = power_supply_register(di->dev, &di->bat); |if (ret) { |dev_err(di->dev, "failed to register battery: %d\n", ret); |return ret; |} ||dev_info(di->dev, "support ver. %s enabled\n", DRIVER_VERSION); ||bq27x00_update(di); ||return 0; | } || static void bq27x00_battery_poll(struct work_struct *work) <------------+ {struct bq27x00_device_info *di =container_of(work, struct bq27x00_device_info, work.work);if (((di->chip == BQ274XX) || (di->chip == BQ276XX)) &&!rom_mode_gauge_dm_initialized(di)) {rom_mode_gauge_dm_init(di); -------------+} ||bq27x00_update(di); -------------*---+| |if (poll_interval > 0) { | |/* The timer does not have to be accurate. */ | |set_timer_slack(&di->work.timer, poll_interval * HZ / 4); | |schedule_delayed_work(&di->work, poll_interval * HZ); | |} | | } | || | #define INITCOMP_TIMEOUT_MS 10000 | | static void rom_mode_gauge_dm_init(struct bq27x00_device_info *di) <---+ | { |int i; |int timeout = INITCOMP_TIMEOUT_MS; |u8 subclass, offset; |u32 blk_number; |u32 blk_number_prev = 0; |u8 buf[32]; |bool buf_valid = false; |struct dm_reg *dm_reg; ||dev_dbg(di->dev, "%s:\n", __func__); ||while (!rom_mode_gauge_init_completed(di) && timeout > 0) { |msleep(100); |timeout -= 100; |} ||if (timeout <= 0) { |dev_err(di->dev, "%s: INITCOMP not set after %d seconds\n", |__func__, INITCOMP_TIMEOUT_MS/100); |return; |} ||if (!di->dm_regs || !di->dm_regs_count) { |dev_err(di->dev, "%s: Data not available for DM initialization\n", |__func__); |return; |} ||enter_cfg_update_mode(di); ------------+ |for (i = 0; i < di->dm_regs_count; i++) { | |dm_reg = &di->dm_regs[i]; | |subclass = dm_reg->subclass; | |offset = dm_reg->offset; | || |/* | |* Create a composite block number to see if the subsequent | |* register also belongs to the same 32 btye block in the DM | |*/ | |blk_number = subclass << 8; | |blk_number |= offset >> 5; | || |if (blk_number == blk_number_prev) { | |copy_to_dm_buf_big_endian(di, buf, offset, | |dm_reg->len, dm_reg->data); | |} else { | || |if (buf_valid) | |update_dm_block(di, blk_number_prev >> 8, | |(blk_number_prev << 5) & 0xFF , buf); | |else | |buf_valid = true; | || |read_dm_block(di, dm_reg->subclass, dm_reg->offset, | |buf); | |copy_to_dm_buf_big_endian(di, buf, offset, | |dm_reg->len, dm_reg->data); | |} | |blk_number_prev = blk_number; | |} | || |/* Last buffer to be written */ | |if (buf_valid) | |update_dm_block(di, subclass, offset, buf); ------------------*-+ || | |exit_cfg_update_mode(di); --------------*-*-+ | } | | | || | | | #define CFG_UPDATE_POLLING_RETRY_LIMIT 50 | | | | static int enter_cfg_update_mode(struct bq27x00_device_info *di) <----+ | | | { | | |int i = 0; | | |u16 flags; | | || | |dev_dbg(di->dev, "%s:\n", __func__); | | || | |if (!unseal(di, BQ274XX_UNSEAL_KEY)) | | |return 0; | | || | |control_cmd_wr(di, SET_CFGUPDATE_SUBCMD); | | |msleep(5); | | || | |while (i < CFG_UPDATE_POLLING_RETRY_LIMIT) { | | |i++; | | |flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, false); | | |if (flags & (1 << 4)) | | |break; | | |msleep(100); | | |} | | || | |if (i == CFG_UPDATE_POLLING_RETRY_LIMIT) { | | |dev_err(di->dev, "%s: failed %04x\n", __func__, flags); | | |return 0; | | |} | | |+------------------------------------------------+ | |return 1; | | | } | | || | |V | | static int update_dm_block(struct bq27x00_device_info *di, u8 subclass, | |u8 offset, u8 *data) | | { | |u8 buf[32]; | |u8 cksum; | |u8 blk_offset = offset >> 5; | || |dev_dbg(di->dev, "%s: subclass %d offset %d\n", | |__func__, subclass, offset); | || |di->bus.write(di, BLOCK_DATA_CONTROL, 0, true); | |msleep(5); | || |di->bus.write(di, BLOCK_DATA_CLASS, subclass, true); | |msleep(5); | || |di->bus.write(di, DATA_BLOCK, blk_offset, true); | |msleep(5); | || |di->bus.blk_write(di, BLOCK_DATA, data, 32); | |msleep(5); | |print_buf(__func__, data); | || |cksum = checksum(data); | |di->bus.write(di, BLOCK_DATA_CHECKSUM, cksum, true); | |msleep(5); | || |/* Read back and compare to make sure write is successful */ | |di->bus.write(di, DATA_BLOCK, blk_offset, true); | |msleep(5); | |di->bus.blk_read(di, BLOCK_DATA, buf, 32); | |if (memcmp(data, buf, 32)) { | |dev_err(di->dev, "%s: error updating subclass %d offset %d\n", | |__func__, subclass, offset); | |return 0; | |} else { | |return 1; | |} | | } | || | static int exit_cfg_update_mode(struct bq27x00_device_info *di) <-------+ | { |int i = 0; |u16 flags; ||dev_dbg(di->dev, "%s:\n", __func__); ||control_cmd_wr(di, BQ274XX_SOFT_RESET); ||while (i < CFG_UPDATE_POLLING_RETRY_LIMIT) { |i++; |flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, false); |if (!(flags & (1 << 4))) |break; |msleep(100); |} ||if (i == CFG_UPDATE_POLLING_RETRY_LIMIT) { |dev_err(di->dev, "%s: failed %04x\n", __func__, flags); |return 0; |} ||if (seal(di)) |return 1; |else |return 0; | } ||| static void bq27x00_update(struct bq27x00_device_info *di) <------------+ {struct bq27x00_reg_cache cache = {0, };bool is_bq27200 = (di->chip == BQ27200);bool is_bq27500 = (di->chip == BQ27500);bool is_bq274xx = (di->chip == BQ274XX);bool is_bq276xx = (di->chip == BQ276XX);cache.flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, !is_bq27500);if (cache.flags >= 0) {if (is_bq27200 && (cache.flags & BQ27200_FLAG_CI)) {dev_info(di->dev, "battery is not calibrated!ignoring capacity values\n");cache.capacity = -ENODATA;cache.energy = -ENODATA;cache.time_to_empty = -ENODATA;cache.time_to_empty_avg = -ENODATA;cache.time_to_full = -ENODATA;cache.charge_full = -ENODATA;cache.health = -ENODATA;} else {cache.capacity = bq27x00_battery_read_soc(di);if (!(is_bq274xx || is_bq276xx)) {cache.energy = bq27x00_battery_read_energy(di);cache.time_to_empty =bq27x00_battery_read_time(di,BQ27XXX_REG_TTE);cache.time_to_empty_avg =bq27x00_battery_read_time(di,BQ27XXX_REG_TTECP);cache.time_to_full =bq27x00_battery_read_time(di,BQ27XXX_REG_TTF);}cache.charge_full = bq27x00_battery_read_fcc(di);cache.health = bq27x00_battery_read_health(di);}cache.temperature = bq27x00_battery_read_temperature(di);if (!is_bq274xx)cache.cycle_count = bq27x00_battery_read_cyct(di);cache.power_avg =bq27x00_battery_read_pwr_avg(di, BQ27XXX_POWER_AVG);/* We only have to read charge design full once */if (di->charge_design_full <= 0)di->charge_design_full = bq27x00_battery_read_dcap(di);}if (memcmp(&di->cache, &cache, sizeof(cache)) != 0) {di->cache = cache;power_supply_changed(&di->bat);}di->last_update = jiffies; }
相关文章:
PHP5.5的一点变化
之前一直使用eAccelerator,参考:PHP安装eAccelerator 注意PHP5.5以后暂时不能使用eAccelerator 原因:其中一个我知道的是eAccelerator中使用了: php_register_info_logo(EACCELERATOR_VERSION_GUID, "text/plain", (un…

虚拟机的操作系统的安装
虚拟机的操作系统的安装启动虚拟机进入下一步,按Enter键开始安装。按F8许可协议选则C创建分区再按C,将未划分的分区划分按ENTER继续,选择NTFS文件系统格式化磁盘分区写上姓名和单位,单击下一步直接点击关闭<?xml:namespace pr…
2020,国产AI开源框架“亮剑”TensorFlow、PyTorch
「AI技术生态论」 人物访谈栏目是CSDN发起的百万人学AI倡议下的重要组成部分。通过对AI生态专家、创业者、行业KOL的访谈,反映其对于行业的思考、未来趋势的判断、技术的实践,以及成长的经历。 2020年,CSDN将对1000人物进行访谈,形…

Centos下部署Solr 搜索引擎
一、环境准备:系统环境:centos 6.5tomcat 7.0.47jdk-7u9solr-4.7.0首先将软件包上传到/tmp目录下1、 jdk安装[rootsvn-server /]# cd /tmp/ [rootsvn-server /]#tar zxvf jdk-7u9-linux-x64.tar.gz[rootsvn-server /]#mv jdk1.7.0_09 /u…

Redis源码分析-TCMalloc
redis很多地方都在调用zmalloc函数 zmalloc在这里定义zmalloc.c void *zmalloc(size_t size) {void *ptr malloc(sizePREFIX_SIZE);if (!ptr) zmalloc_oom_handler(size); #ifdef HAVE_MALLOC_SIZEupdate_zmalloc_stat_alloc(zmalloc_size(ptr));return ptr; #else*((size_t…
让AI训练AI,阿里和浙大的“AI训练师助手”是这样炼成的
不久前,人力资源社会保障部发布了一种炙手可热的新职业:AI训练师。没想到,浙江大学与阿里安全的人工智能训练师马上创造出一个 “AI训练师助手”,高效打造AI深度模型,应对海量应用场景的增加,让AI训练模型面…

用 Navicat for Oracle 管理 Oracle10g/11g 数据库
Navicat for xxx 是一个优秀的数据库管理客户端,有 MySQL、Oracle 等版本。建议大家最好用 Enterprise 版本,功能全面一些,但较之于免费的 Lite 版,企业版可是要花银子买的。 安装 Navicat for Oracle 后,首先需要建一…

借一个同事的经历,谈一谈程序员的成长
一个很久之前的同事,今天找我,想让我帮他推荐下,去我们公司来工作,因为认识很久,就和他说了说公司的现状,也询问了一下他的状况,寒暄几句,让他下周等面试。 这位同事是之前一起做游戏…

select,epoll,poll比较
select,poll,epoll简介 select select本质上是通过设置或者检查存放fd标志位的数据结构来进行下一步处理。这样所带来的缺点是: 1 单个进程可监视的fd数量被限制 2 需要维护一个用来存放大量fd的数据结构,这样会使得用户空间和内…
华为开发者大会HDC.Cloud技术探秘:云搜索服务技术实践
搜索是一个古老的技术,从互联网发展的第一天开始,搜索技术就绽放出了惊人的社会和经济价值。随着信息社会快速发展,数据呈爆炸式增长,搜索技术通过数据收集与处理,满足信息共享与快速检索的需求。基于搜索技术…

从今天开始,自己做SEO。
1.购买了一点黑链。开始优化之路。 2.更改了关键词,描述。 3.整理了友情链接。 4.购买了VPS服务器:点击查看 转载于:https://www.cnblogs.com/zq535228/archive/2010/06/09/1754986.html

Elasticsearch2.2.0配置文件说明
为什么80%的码农都做不了架构师?>>> 官方配置文档 https://www.elastic.co/guide/en/elasticsearch/reference/current/setup.html 配置详解 # ---------------------------------- Cluster (集群配置)----------------------…

各种类型的字节数
int类型比较特殊,具体的字节数同机器字长和编译器有关。如果要保证移植性,尽量用__int16 __int32 __int64吧,或者自己typedef int INT32一下。 C、C标准中只规定了某种类型的最小字节数(防止溢出) 64位指的是cpu通用寄…
154 万 AI 开发者用数据告诉你,中国 AI 如何才能弯道超车?| 中国 AI 应用开发者报告...
曾经,软件吞噬世界。现在,AI 吞噬软件。作者 | 屠敏数据 | 杨阳、刘学涛可视化&策划 | 唐小引出品 | CSDN(ID:CSDNnews)从三年前年薪 25 万只是白菜价,到去年华为以年薪最高达 201 万招揽顶尖应届毕业生…

中国移动用户能不能用WCDMA网?(世界杯与通信2)
到南非有移动的用户也有联通的用户,联通的网络快这是肯定的,不过联通的通话价格也比移动的高,就有人希望拿着移动的号去南非,最好也能享受WCDMA的网络速度,这样就是两全其美了,对于这个问题,在国…

平安陆金所-点金计划,简直是骗子行为。
陆金所点金计划,让人防不胜防。平安保险,骗子中的教练。 转载于:https://www.cnblogs.com/hthf/p/5205921.html
深度分析define预处理指令
#define语句 预处理 宏替换 --以上出自《C语言入门经典(第四版)》 #和## --出自《C语言程序设计:现代方法(第2版)》 #undef取消定义 --以上出自《21天学通C语言(第6版)》

建立YUM服务器CENTOS
1 ,YUM Client:要保证安装有如下软件包:yum-3.2.19-18.el5.centosyum-metadata-parser-1.1.2-2.el52 ,YUM Server:要保证安装有如下软件包:yum-3.2.19-18.el5.centosyum-metadata-parser-1.1.2-2.el5yum-fastestmirror…
数据库设计的10个最佳实践
作者 | Emily Williamson译者 | 孙薇,责编 | 屠敏出品 | CSDN(ID:CSDNnews)以下为译文:数据库是应用及计算机的核心元素,负责存储运行软件应用所需的一切重要数据。为了保障应用正常运行,总有一…

十进制转化为十六进制分割高低位
2019独角兽企业重金招聘Python工程师标准>>> 将十进制1000,转化为十六进制,则为0x03E8,如果得到高低位,high0x03,low0xE8 BYTE high;BYTE low;int temp_data1nWeightValue;highBYTE(temp_data1 >>8);int temp_data2nWeightV…
Nginx内存池--pool代码抽取(链表套路)
ngx_palloc.c文件 ngx_palloc_large_hm是自己写的代码没有nginx原版的ngx_palloc_large写的好,细节要品味才会发现nginx的美 nginx链表的套路,正好是两种插入“从前插”和“从后插”,有些许差别 #include <stdio.h> #include <std…

阿里再次主办大数据世界杯, KDD Cup2020正式开赛
记者从国际计算机科学顶会ACM SIGKDD官网获悉,KDD Cup 2020今日正式开赛,本届比赛由阿里巴巴达摩院主办。随即,阿里公布了认知智能、曝光偏差两大赛题方向,并向全球参赛者开放最大规模的商品多模态数据集。阿里也是两次举办该赛事…

grep 正则表达式
grep 正则表达式来源:http://blog.rednet.cn/user1/213546/archives/2007/35795.html以下为整理的grep 正则表达式的大部分功能,详细参见man grep: 要用好grep这个工具,其实就是要写好正则表达式,所以这里不对grep的所有功能进行实例讲解,只列…

Mybatis缓存机制理解及配置
2019独角兽企业重金招聘Python工程师标准>>> 1. Ehcache EHCache是来自sourceforge(http://ehcache.sourceforge.net/)的开源项目,也是纯Java实现的简单、快速的Cache组件。EHCache支持内存和磁盘的缓存,支持LRU、…

浅谈无缓存I/O操作和标准I/O文件操作区别 (转载)
首先,先稍微了解系统调用的概念: 系统调用,英文名system call,每个操作系统都在内核里有一些内建的函数库,这些函数可以用来完成一些系统系统调用把应用程序的请求传给内核,调用相应的的内核函数完成所需的…

Android之ListActivity(一):布局与数据绑定
Android中的列表,当然也可以用ListView来完成所需要的功能,用法是一样的。 废话不说,来关键的。 LiveActivity本身继承了关于List操作的众多接口,我们可以方便的重写这些操作中需要的方法来实现自己需要的功能。 如果要用ListActi…
用于单图像超分辨率的对偶回归网络,达到最新SOTA | CVPR 2020
作者 | Yong Guo, Jian Chen等译者 | 刘畅出品 | AI科技大本营(ID:rgznai100)通过学习从低分辨率(LR)图像到高分辨率(HR)图像之间的非线性映射函数,深度神经网络在图像超分辨率(SR&a…

老生常谈,joomla wordpress drupal,你该选择哪个CMS?
本人从事Joomla建站多年,给客户建站都是用Joomla,所以我会极力推荐你选择Joomla? No No No,这样未免太Hard sale了。 虽然这是一个会经常被提到的问题,网上也有不少优秀的答案,但我还是想把自己的想法跟大家…
利用TCMalloc替换Nginx和Redis默认glibc库的malloc内存分配
TCMalloc的全称为Thread-Caching Malloc,是谷歌开发的开源工具google-perftools中的一个成员。与标准的glibc库的Malloc相比,TCMalloc库在内存分配效率和速度上要高很多,这在很大程度上提高了服务器在高并发情况下的性能,从而降低…

Silverlight Analytics Framework(开源分析框架)
Silverlight Analytics Framework是由微软官方推出的WPF/Silverlight扩展Web分析框架.该框架与10余家第三方分析服务结合,使应用可以跟踪程序如何使用的详细情况,为用户提供诸如可用性和视频质量等细节分析。用户可以了解到这些应用软件的使用细节&#…