muduo库学习笔记
前言
注:个人水平有限,不能保证此文完全正确,如果错误,请不吝指出。
此文在观看《大并发服务器开发》视频时所做。
因此本文所讲基于muduo库0.9.1-beta版本,需要依赖cmake及boost.
sudo apt-get install cmake libboost-dev libboost-test-dev .
更新时间:<2018-03-12>
原创时间: <2018-03-12>
epoll/poll/select
面向对象编程与基于对象编程
std::boost::function
std::bootst::bind
muduo::base中类关系及作用
copyable.h 一个空类,用来标识子类是值语义。
Types.h 提供字符串类的声明,及两个类型转换函数模板。
- implicit_cast (隐式转换),使代码阅读时更明晰。
- down_cast (向下转型),基类指针转换为派生类指针,前提是基类指针指向派生类对象。
Timestamp.h/cc 提供封装好的时间类。
- 继承copyable,值语义。
- 继承boot::less_than_comparable\,less_than_comparable:要求提供<,可自动实现>,<=,>=
- BOOST_STATIC_ASSERT(sizeof(Timestamp) == sizeof(int64_t)); 编译期间的assert,在编译时就可以报错。
- 打印64位整数使用 PRld64, printf(“%” PRld64 “\n”, value_64); 可以做到跨平台(32和64位)。
Atomic.h 提供原子操作模板类。延伸阅读:无锁队列的实现
- 提供了AtomicInt32(用来标识线程数使用)和AtomicInt64(目前还未看出作用) 两个类。
- volatile关键字:确保本条指令不会因编译器的优化而省略,且要求每次直接读值。当要求使用volatile声明的变量的值时,系统总是重新从它所在的内存读取数据,而不是使用保存在寄存器中的备份。
Exception.h/cc 提供异常类
- backtrace 栈回溯,保存各个栈帧的地址。
- backtrace——symbols,根据地址,转成相应的函数符号。
- c++会在编译时会对函数做名字改编(name mangling)。
- abi::__cxa_demangle 对c++的程序做名字还原。
Thread.h/cc 线程类
Linux中进程与线程
- Linux中每个进程有一个pid,类型是pid_t,由getpid()取得。
- Linux下每个POSIX**线**程也有一个id,类型是pthread_t,由pthread_self()取得
- POSIX**线程id由线程库维护,其id空间是各个进程独立的。(即不同的进程中的线**程可能有相同的id)。
- Linux中的POSIX线程库实现的线程其实也是一个进程(LWP),只是该进程与主进程(启动线程的进程)共享一些资源而已,比如代码段,数据段等。
- 有时候我们可能需要知道线程的真实pid。比如进程P1要向进程P2中的某个线程发送信号时,既不能使用P2的pid,更不能使用线程的pthread_id,而只能使用该线程的真实pid,称为tid。
- 有一个函数gettid()可以得到tid,但glibc并没有实现该函数,只能通过 Linux的系统调用syscall来获取。
return syscall(SYS_gettid)
- 普通成员函数,隐含的第一个参数是 Thread*(this),调用是时候遵循 thiscall约定,某一个寄存器会保护this指针,不能直接作为pthread_create的入口函数。需要定义一个static的静态成员函数,传递this指针来调用。
- static AtomicInt32 numCreated_; //用来记录创建的线程数,原子操作类型,在Thread类的构造中加1,析构上减1.
- __thread 关键字可以定义每个线程各个的变量。只能用来修饰基本类型(内置类型(与C兼容的原始类型)或无构造函数的类(结构体)),POD类型。
- 将真实线程tid缓存起来,可以减少系统调用次数。
- namespace detail 内部使用的命名空间,对外不可见
- boost::is_same 用来判定两种类型是否是同一种类型
- pthread_atfork (void (*prepare)(void), void(*parent)(void), void(*child)(void));
- 调用fork时,内部创建子进程前在父进程中调用prepare
- 内部创建子进程成功后,父进程会调用parent
- 子进程会调用child
- fork 可能是在主线程中调用,也可能是在子线程中调用
- fork得到一个新进程,新进程只有一个执行序列,只有一个线程(调用fork的线程被继承下来)
- 实际上,对于编写多线程程序来说,我们最好不要再调用fork
- 不要编写多进程多线程程序,要么用多进程要么用多线程
Mutex.h 提供锁
- MutexLocal类
- 继承自boot::noncopyable,不可拷贝的,对象语义
- MutexLockGuard类(更常用)
- 使用RAII技法(通过生存期来管理资源,在构造函数中申请资源,在析构函数中释放资源)封装的MutexLocal类
- MutexLocal类
Condition.h/cc 条件变量类(Condition类)