要点
默认输出到
/tmp/<program name>.<hostname>.<user name>.log.<severity level>.<date>.<time>.<pid>
FATAL和CHECK失败,会打印堆栈(默认打印到stderr),然后exit(1)
选项
minloglevel=NUM
指定最小级别
命令行
重定向到标准出错
GLOG_logtostderr=1 ./your_application
默认输出到/tmp/<program name>.<hostname>.<user name>.log.<severity level>.<date>.<time>.<pid>
FATAL和CHECK失败,会打印堆栈(默认打印到stderr),然后exit(1)
minloglevel=NUM
指定最小级别
重定向到标准出错
GLOG_logtostderr=1 ./your_application
rpm -ql procps-ng |grep bin
-a
输出进程的命令行参数
-p
输出进程PID
-u
输出进程使用者
-s
Show parent processes of the specified process.
-n
按PID排序
-l
完整显示,默认80列
-h
高亮当前进程及其父进程
-H PID
高亮PID进程及其父进程
显示PID进程的族谱
pstree -apls PID
通过yum provides FILENAME
来查找所属包
glibc-headers(使用C开发库,必须安装的包)
/usr/include/sys
,/usr/include/bits
kernel-headers(被glibc使用)
/usr/include/linux
,/usr/include/asm
查询包信息
rpm -q glibc
列出包文件
rpm -ql glibc
查询文件所属
yum provides /usr/include/sys/types.h
下载包
yum -y install yum-utils
yumdownloader httpd
二进制编码,格式紧凑,编解码快,占用内存小
可读性非常差,不利于调试
protoc [OPTION] PROTO_FILES
输出c++代码
protoc --cpp_out=. base.proto
基本类型(uint32
、string
等)提供了set_
方法
singular(单数
) message字段(自定义消息),提供mutalbe_
方法设置值,没有set_
方法
repeated字段
_size
查询数量add_
添加(返回指针来修改数据)消息类型
CamelCase(with an initial capital)
字段
underscore_separated_names
1 | message SongServerRequest { |
枚举
Use CamelCase (with an initial capital) for enum type names and CAPITALS_WITH_UNDERSCORES for value names
1 | enum Foo { |
service
CamelCase (with an initial capital) for both the service name and any RPC method names
1 | service FooService { |
采用类似于UTF-8编码方式,来编码整型数,该数为uint64
类型,负数采用补码,所以占用8B,对应需要10B(ceil((8 * 8) / 7)
)。
每个字节用7bits来编码数字
单字节的最高位(Most Significant Bit),来表示是否还有后续字节(1表示有,0表示没有)。
多字节数采用小端字节序
1 | 1 => 0000 0001 |
源码(encode.go
):
1 | const maxVarintBytes = 10 // maximum length of a varint |
具体有key(tag+type)
,length
,value(int32, int64, uint32, uint64, sint32, sint64, bool, enum)
使用varint
编码。
1 | int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout); |
0 返回IO就绪的文件描述符总数;
==0 超时返回
<0(-1) 出错(需要注意,该调用为慢速系统调用,当被信号中断时,返回EINTR)
调用epoll_create时,内核除了帮我们在epoll文件系统里建了个file结点,在内核cache里建了个红黑树用于存储以后epoll_ctl传来的fd外,还会再建立一个list链表,用于存储准备就绪的事件,当epoll_wait调用时,仅仅观察这个list链表里有没有数据即可。有数据就返回,没有数据就sleep,等到timeout时间到后即使链表没数据也返回。所以,epoll_wait非常高效。而且,通常情况下即使我们要监控百万计的fd,大多一次也只返回很少量的准备就绪fd而已,所以,epoll_wait仅需要从内核态copy少量的fd到用户态而已。那么,这个准备就绪list链表是怎么维护的呢?当我们执行epoll_ctl时,除了把fd放到epoll文件系统里file对象对应的红黑树上之外,还会给内核中断处理程序注册一个回调函数,告诉内核,如果这个fd的中断到了,就把它放到准备就绪list链表里。所以,当一个fd(例如socket)上有数据到了,内核在把设备(例如网卡)上的数据copy到内核中后就来把fd(socket)插入到准备就绪list链表里了
执行epoll_create
时,创建了红黑树和就绪list链表。
执行epoll_ctl
时,如果增加fd(socket),则检查在红黑树中是否存在,存在立即返回,不存在则添加到红黑树上,然后向内核注册回调函数,用于当中断事件来临时向准备就绪list链表中插入数据。
执行epoll_wait
时立刻返回准备就绪链表里的数据
epoll_event
中的epoll_data_t
用来存储用户自定义数据
当与其绑定的fd
上发生指定的事件时,epoll_wait
返回该event
,用户可以拿到该数据
select
,poll
)?无需每次调用,都将套接字集合从应用层拷贝到内核层。
epoll采用红黑树来管理描述符,epoll_ctl
执行管理操作
当有IO事件返回时,epoll无需遍历整个描述符集合(O(m),m为IO就绪的数量),而select/poll则是O(n),大大的减少了轮询操作
epoll返回event的集合(该event结构包含用户数据),应用层只需根据原有数据来分发事件
内核采用slab算法管理epoll相关数据结构,加速了相关操作时间
ssize_t read(int fildes, void *buf, size_t nbyte);
0,成功读取了n字节
=0,对方断开了连接
<0,发生了错误