libuv学习

libuv 是重写了下libev,封装了windows和unix的差异性。
libuv的特点
非阻塞TCP套接字 socket?
非阻塞命名管道
UDP
定时器
子进程 fork?
通过 uv_getaddrinfo实现异步DNS
异步文件系统API uv_fs_*
高分辨率时间 uv_hrtime
正在运行程序路径查找 uv_exepath
线程池调度 uv_queue_work
TTY控制的ANSI转义代码 uv_tty_t
文件系统事件支持 inotify ReadDirectoryChangesW kqueue 马上回支持 uv_fs_event_t
进程间的IPC与套接字共享 uv_write2

事件驱动的风格:程序关注/发送事件,在事件来临时给出反应。
系统编程中,一般都是在处理I/O,而IO的主要障碍是网络读取,在读取的时候是阻塞掉的。标准的解决方案是使用多线程,每一个阻塞的IO操作被分配到一个线程。当线程block,处理器调度处理其他线程。
libuv使用了另一个方案,异步。操作系统提供了socket的事件,即使用socket,监听socket事件即可。

libuv简单使用 创建一个loop,关闭loop。
#include <stdio.h>
#include <stdlib.h>
#include <uv.h>

int main()
{
uv_loop_t *loop = malloc(sizeof(uv_loop_t));
uv_loop_init(loop);

printf("hello, libuv");

uv_run(loop, UV_RUN_DEFAULT);

uv_loop_close(loop);
free(loop);

return 0;
}

如果只需要一个loop的话,调用uv_default_loop就可以了。
tips:Nodejs中使用了这个loop作为主loop。
uv_loop_t *loop = uv_default_loop();

uv_run(loop, UV_RUN_DEFAULT);

uv_loop_close(loop);

Error
初始化或同步函数,会在执行失败是返回一个负数,可以通过uv_strerror、uv_err_name获得这个错误的名字和含义
I/O函数的回调函数会被传递一个nread参数,如果nread小于0,也代表出现了错误。

Handle & Request
libuv的工作建立在事件的监听上,通常通过handle来实现,handle中uv_TYPE_t中的type指定了handle监听的事件。
在uv.h中可以找到handle和request的定义
/* Handle types. */
typedef struct uv_loop_s uv_loop_t;
typedef struct uv_handle_s uv_handle_t;
typedef struct uv_stream_s uv_stream_t;
typedef struct uv_tcp_s uv_tcp_t;
typedef struct uv_udp_s uv_udp_t;
typedef struct uv_pipe_s uv_pipe_t;
typedef struct uv_tty_s uv_tty_t;
typedef struct uv_poll_s uv_poll_t;
typedef struct uv_timer_s uv_timer_t;
typedef struct uv_prepare_s uv_prepare_t;
typedef struct uv_check_s uv_check_t;
typedef struct uv_idle_s uv_idle_t;
typedef struct uv_async_s uv_async_t;
typedef struct uv_process_s uv_process_t;
typedef struct uv_fs_event_s uv_fs_event_t;
typedef struct uv_fs_poll_s uv_fs_poll_t;
typedef struct uv_signal_s uv_signal_t;

/* Request types. */
typedef struct uv_req_s uv_req_t;
typedef struct uv_getaddrinfo_s uv_getaddrinfo_t;
typedef struct uv_getnameinfo_s uv_getnameinfo_t;
typedef struct uv_shutdown_s uv_shutdown_t;
typedef struct uv_write_s uv_write_t;
typedef struct uv_connect_s uv_connect_t;
typedef struct uv_udp_send_s uv_udp_send_t;
typedef struct uv_fs_s uv_fs_t;
typedef struct uv_work_s uv_work_t;

/* None of the above. */
typedef struct uv_cpu_info_s uv_cpu_info_t;
typedef struct uv_interface_address_s uv_interface_address_t;
typedef struct uv_dirent_s uv_dirent_t;

handle是持久化的对象。在异步操作中,相应的handle有许多关联的request。
request是短暂性的,通常只维持一个回调的时间,一般对应handle的一个IO操作。request用来在初始函数和回调函数中传递上下文。
例如uv_udp_t代表了一个udp的socket,每一个socket的写入完成后,都有一个uv_udp_send_t被传递。

handle的设置
uv_TYPE_init(uv_loop_t*, uv_TYPE_t);

一个idle handle的使用例子 观察下它的生命周期
#include <stdio.h>
#include <uv.h>

int counter = 0;

void wait_for(uv_idle_t * handle)
{
counter++;

if (counter > 10e6)
{
uv_idle_stop(handle);
}
}

int main()
{
uv_idle_t idler;

uv_idle_init(uv_default_loop(), &idler);
uv_idle_start(&idler, wait_for);

printf("Idle......");

uv_run(uv_default_loop(), UV_RUN_DEFAULT);

uv_loop_close(uv_default_loop());

return 0;
}

参数传递
handle和request都有一个data域,用来传递信息。uv_loop_t也有一个相似的data域。

文件系统
简单的文件读写是通过uv_fs_*函数族和与之相关的uv_fs_t结构体完成的。
系统的文件操作是阻塞的,所以libuv在线程池中调用这些函数,最后通知loop。

如果没有指定回调函数,文件操作是同步的,return libuv error code。
异步在传入回调函数时调用,return 0。

获得文件描述符
int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int mode, uv_fs_cb cb);
关闭文件描述符
int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb)
回调函数
void callback(uv_fs_t* req);
还有uv_fs_read uv_fs_write uv_fs_t构成了基本的文件操作

流操作使用uv_stream_t,比基本操作方便不少
uv_read_start uv_read_stop uv_write
流操作可以很好的配合pipe使用
pipe相关函数
uv_pipe_init uv_pipe_open uv_close

文件事件
uv_fs_event_t uv_fs_event_init uv_fs_event_start

网络
uv_ip4_addr ip为 0.0.0.0表示绑定所有接口 255.255.255.255是一个广播地址,意味着数据将往所有的子网接口发送,端口号0表示由操作系统随机分配一个端口
tcp
TCP是面向连接的字节流协议,因此基于libuv的stream实现
uv_tcp_t
服务器端创建流程
uv_tcp_init 建立tcp句柄
uv_tcp_bind 绑定
uv_listen 建立监听,当有新的连接到来时,激活调用回调函数
uv_accept 接收链接
使用stream处理数据以及与客户端通信

客户端
客户端比较简单,只需要调用uv_tcp_connect

udp
UDP是不可靠连接,libuv基于uv_udp_t和uv_udp_send_t
udp的流程与tcp类似

libuv提供了一个异步的DNS解决方案,提供了自己的getaddrinfo
配置好主机参数addrinfo后使用uv_getaddrinfo即可

调用uv_interface_addresses获得系统的网络信息

未完待续。

来源:http://luohaha.github.io/Chinese-uvbook/source/introduction.html

使用gyp

GYP(Generate You Project),生成IDE项目的工具,使用Python脚本写成,配置文件为JSON格式。

使用gyp需要两个环境,python和gyp。gyp可以直接在这里下载

git clone https://chromium.googlesource.com/external/gyp

一般下载到build/gyp

使用python将我们的gyp文件加载并运行起来

args中可以添加工程的配置文件,大概格式如下:

target_name:工程名

type: 工程类型

dependencies: 依赖文件夹

sources: 源文件

conditions:条件判断

msvs-settings:msvs额外设置

 

Linux服务器-windows远程开发

最近项目需要在Linux环境下,本人的本是windows,怎么办么?

答:申请一台服务器,linux环境,用ssh工具就可以开发了

不过服务器上只能用vim开发,开发起来惨不忍睹,怎么办?

答:远程开发

远程开发的原理很简单,就是把服务器上的文件夹映射到windows上,就可以像windows本地开发一样了。

首先在Linux服务器上安装samba,装好后给自己配置一个samba用户,具体方法请自行百度,参考链接:http://blog.csdn.net/i_chips/article/details/19191957。

window端打开计算机,有一个映射网络驱动器选项

samba_3

打开后有两个选项

samba_4

第一个是盘符,默认就行,红框所选的地方 写上要映射的服务器文件夹地址。

填好之前在samba上配置的账号/密码,就可以用了。

替代微软Visio的开源免费软件DIA Diagram Editor

DDIA Diagram Editor,功能强大和跨平台特性,原生支持简体中文界面。与Visio相比,DIA Diagram Editor安装包仅不足20MB,可以放在网盘或U盘中随身携带。初用者可能觉得Dia用法比较繁琐而麻烦,但是无法否认,它仍然是综合性能最佳的免费替代方案。

DIA Diagram Editor支持导出的流程图格式如下:EPS、SVG、DXF(Autocad格式)、CGM、WMF、PNG、JPEG、VDX(Microsoft Visio格式)。

dia_screenshot

项目地址:http://sourceforge.net/projects/dia-installer/

 

使用CMake(windows vs2015)

学习使用CMake,简单记录一下学到的东西:

CMake使用自己的语法对工程进行配置,方便在各个平台编译。

windows上,安装了CMake后,有gui界面,操作起来很方便。

1.打开gui,选择源码目录(对应${PROJECT_SOURCE_DIR})

2.选择生成目录,最好是${PROJECT_SOURCE_DIR}/build,防止生成文件跟源码搞到一起。

点击configure,偶尔需要两次。configure完工后,去build目录下已经可以看到VS工程文件,打开就可以慢慢调了。

 

CMake要求不多,编译目录下需要有CMakeList.txt,CMake根据CMakeList酌句执行。

这里贴一个用到的CMakeList.txt,并简单注释(目前理解还不够,仅仅是配置对应了vs的哪一项)

下面是一篇极好的CMake学习文档,CMake practice

 

Sqlite常规操作 add update select

用到了数据库,花了好长时间才搞定,把遇到的问题记录一下,sqlite语法:

select,最简单的语句

select * from table where condition

add

add中有两个需求

1.没有表的时候创建表

create table if not exists

2.如果存在则更新,不存在就插入

insert or replace into table ()values()

这里需要配合 primary key,用unique会报错

3.update

update table set x = x where condition

 

多次遇到 near syntax error,这些肯定是语法拼写错误,请仔细检查。

 

小米Note(MIUI V7)查看程序访问网络流量排行

小米Note(MIUI V7) 连接上WIFI后,显示网络下载一直很高,不清楚是哪个应用在访问网络,网上搜索了一下,找到如何查看网络流量的方法。

  • 桌面上点击“安全中心”

desktop

  • 选择“流量剩...”这个水滴状的按钮

safe_center

  • 选择“流量排行”

flow_list

  • 点击右上角的切换图标来显示WIFI跟3G,4G上网排行

select_network

  • 详细的流量访问,排行信息

net_app_lists

常用数学符号希腊字母表

 

希腊字母表
序号
大写
小写
英文注音
国际音标注音
中文读音
意义
1
Α
α
alpha
a:lf
阿尔法
角度;系数
2
Β
β
beta
bet
贝塔
磁通系数;角度;系数
3
Γ
γ
gamma
ga:m
伽马
电导系数(小写)
4
Δ
δ
delta
delt
德尔塔
变动;密度;屈光度
5
Ε
ε
epsilon
epsilon
艾普西龙
对数之基数
6
Ζ
ζ
zeta
zat
截塔
系数;方位角;阻抗;相对粘度;原子序数
7
Η
η
eta
eit
艾塔
磁滞系数;效率(小写)
8
Θ
θ
thet
θit
西塔
温度;相位角
9
Ι
ι
iot
aiot
约塔
微小,一点儿
10
Κ
κ
kappa
kap
卡帕
介质常数
11
Λ
λ
lambda
lambd
兰布达
波长(小写);体积
12
Μ
μ
mu
mju
磁导系数微(千分之一)放大因数(小写)
13
Ν
ν
nu
nju
磁阻系数
14
Ξ
ξ
xi
ksi
克西
数学上的随机变量
15
Ο
ο
omicron
omikron
奥密克戎
16
Π
π
pi
pai
圆周率=圆周÷直径=3.14159 26535 89793
17
Ρ
ρ
rho
rou
电阻系数(小写)
18
Σ
σ
sigma
sigma
西格马
总和(大写),表面密度;跨导(小写)
19
Τ
τ
tau
tau
时间常数
20
Υ
υ
upsilon
jupsilon
伊普西龙
位移
21
Φ
φ
phi
fai
佛爱
磁通;角
22
Χ
χ
chi
phai
西
23
Ψ
ψ
psi
psai
普西
角速;介质电通量(静电力线);角
24
Ω
ω
omega
o`miga
欧米伽
欧姆(大写);角速(小写);角

Source Insight添加.cc文件

在导入代码时, 发现Souce Insight只导入了.h文件,.cc文件没有导入. Source Insight对C++项目的导入,其文件过滤没有包含*.cc文件, 需要自己手动设置导入:

  1. options->document options->在document type中选择C++ Source->在右边的File Filter里加上*.cc文件
  2. 重新添加项目文件: project->Add and Remove Project files

具体操作如图所示

1.选择“Document Options”
Source_Insight_Document_Options

2.选择 “Document Type”Source_Insight_Document_Type

3.选择“C++”

Source_Insight_Document_Type_Sel

4.增加 “*.CC”

Source_Insight_C_Plus_Add_CC

小米音箱连接到Intel Wireless Bluetooth 7260 音质非常差的解决

最近买了个小米音箱,如下图所示。连接到手机,连接到 DELL笔记本的蓝牙上面都是正常的,但是一旦连接到 Intel Wireless Bluetooth 7260 上面,立即就会音质非常差了。纠结了好久终于找到原因。
T1gCJgB_dT1RXrhCrK!430x430

 

首先看看音质非常差的原因,按照下图操作

20150315131426

可以看到下图的显示,此时,音频处于单声道的8000采样,这个音频质量太差,没办法听音乐的,失真严重。而且没办法选择。

20150315131743

怎么处理呢?如下操作

20150315132238

然后

20150315132535

关闭语音服务,连接音乐服务。

20150315132839

点击后的结果如下所示即可

20150315133032

此时再次观察合成器的属性

20150315131426

观察高级属性

20150315133227

此时大家听音乐的时候,就会效果非常好了。

总结一下原因:

Intel的蓝牙,默认连接了小米的语音电话功能,这个功能按理说在蓝牙通信的时候,音箱应该声明自身没有电话通信功能的,可是小米的音箱错误的声明自己支持语音通话,造成了蓝牙协议栈把音箱当成了电话,导致默认音频异常。