C++线程的使用
C++11之前,C++语言没有对并发编程提供语言级别的支持,这使得我们在编写可移植的并发程序时,存在诸多的不便。现在C++11中增加了线程以及线程先关的类,很方便的支持了并发编程,使得编写的多线程程序的可移植性得到了很大的提高。
C++11中提供的线程类叫做std::thread,基于这个类创建一个新的线程非常的简单,只需要提供线程函数或者函数对象即可,并且可以同时指定线程函数的参数。我们首先来了解一下这个类提供的一些常用API:
1. 构造函数123456789// ①thread() noexcept;// ②thread( thread&& other ) noexcept;// ③template< class Function, class... Args >explicit thread( Function&& f, Args&&... args );// ④thread( const thread& ) = delete;
构造函数1:默认构造函数,构造一个线程对象,在这个线程中不执行任何处理动作
构 ...
处理日期和时间的chrono库
C++11中提供了日期和时间相关的库chrono,通过chrono库可以很方便的处理日期和时间,为程序的开发提供了便利。chrono库主要包含三种类型的库:**时间间隔duration、时钟clocks、时间点time point**。
1. 时间间隔duration1.1 常用类成员duration表示一段时间间隔,用来记录时间长度,可以表示几秒、几分钟、几个小时的时间间隔。duration的原型如下:
12345//定义于头文件 <chrono>template< class Rep, class Period = std::ratio<1>> class duration;
**Rep**:这是一个数值类型,表示时钟数(周期)的类型(默认为整形)。若Rep是浮点数,则duration能使用小数描述时钟周期的数目。
**Period**:表示时钟的周期,原型如下: 12345// 定义于头文件 <ratio>template< std::intmax_t Num, std::intmax_t Denom = ...
Android匿名共享内存ashmem
1. 进程间通信之共享内存Android匿名共享内存—ashmem,其本质是一种共享内存实现方案,而共享内存是操作系统实现进程间通信(IPC)的一种手段。众所周知,binder驱动是Android系统运用最广泛的一种IPC,那么为什么还需要ashmem呢?我么将在文章的最后给出答案,在此之前,我们将其作为一种共享内存机制来说明其实现原理。
先来看一下共享内存的原理。
1.1 什么是虚拟内存虚拟内存—vm,不是一块实际存在的内存,为了环节物理内存不够用的问题,往往从磁盘空间中开辟一块空间作为物理内存的扩展,这块开辟的磁盘空间称之为交换区—swap。
但是我们都知道,CPU是不能直接访问磁盘空间的,所有的数据都必须先从磁盘空间读入物理内存之后才能被CPU访问,所以swap的工作方式并不是简单的当物理内存用完之后直接从交换区读取数据,而是有一个换出(swap out)换入(swap in)的过程。
具体来说,根据局部访问原理,我们总是认为物理内存中存储的总是最常访问的数据,所以当我们要访问数据时,大多数时候可以直接从物理内存中访问到。但是,当访问数据不在物理内存中时,内核需要将数据从磁盘 ...
bazel构建C++工程
1. bazel介绍Bazel是一个开源的构建和测试工具,类似于Make、Maven和Gradel。Bazel支持多种语言的项目,并未多种平台构建输出。Bazel支持跨多个存储库和大量用户的大型代码库。
2. bazel安装bazel安装有两种方法,一种是通过安装,另一个是通过下载安装包本地安装。ubuntu系统建议使用第一种安装方式。
第一步:添加bazel分发url作为包源
123sudo apt install curl gnupgcurl https://bazel.build/bazel-release.pub.gpg | sudo apt-key add -echo "deb [arch=amd64] https://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list
第二步:安装或者更新bazel
1sudo apt update && sudo apt install bazel
如果已经安装 ...
巧妙的kfifo
在编写一个字符驱动的时候想用一个Ring Buffer的结构来做数据的读取/写入,自己去设计了一个RingBuffer的数据结构,然后使用一个read/write的指针来指向读取和写入buffer的地址,由于是ring buffer所以会考虑到写入超过size的时候回到起始地址的操作。
写完之后偶然发现Linux Kernel中有现成的kfifo实现,拜读了一下代码之后,发现自己的代码太low了,原来Linux Kernel的kfifo才是大神级别的代码,简洁且美观,没有一行多余的代码。
下面我们来分析一下Linux Kernel的kfifo是如何实现和工作的。
kfifo概述kfifo是内核里面的一个First In First Out数据结构,它采用唤醒循环队列的数据结构来实现,但是它提供的是一个无边界的字节流,最重要的一点是,它使用并行无锁编程技术,也就是当它用于只有一个入队线程和一个出队线程的场景时,两个线程可以并行操作,不需要加锁就可以保证kfifo的线程安全。
OK,既然那么多特点,先来看数据结构:
1234567struct kfifo { unsig ...
Linux线程池
前言基本上每一种编程语言都会支持多线程,这里我们只讲C/C++,C/C++是真正的native language。
现代操作系统都是支持多线程的,不管是单核还是多核,多线程的编程,也可以非常有效的利用CPU的执行来解决很多复杂的问题,并且在多核的情况下更好的让多核CPU核心共同协调工作。
Posix Threads(pthread): 对不同platform的支持很好,你可以非常稳定可靠的使用,如果想让你的代码可移植性非常强的话,使用pthread是毫无疑问的
std::thread: 是从C++11中引入,在不同的平台上表现各异,比如在一些Android和Win64平台下不支持,或者有性能瓶颈,当然了如果你的代码只是考虑到Linux/gcc平台编译器的话,是个不错的选择,特别是对C++11的类非常友好
boost::thread: 对std::thread是个非常好的替代品,而且API也非常相似,但是boost::thread是一个第三方库,一般都需要移植到你正在使用的平台
但是总的来说还是要以发展的眼光看待std::thread,毕竟C++的所谓现代化API也一直在更新发展 ...
Android智能指针
Android的核心库基本都是由C++代码编写的,这也证明了C++代码的潜力,面向对象的可扩展性很强,而且不失性能的流失,确实是大型项目的首选编程语言。
那么引入“智能”指针的目的是为了解决C++语言中经常性会发生的内存泄漏的问题,因为使用C/C++语言很多地方需要手动去分配内存,在C++语言中指针的使用使得很多时候会在不恰当的时候去释放内存,或者说忘记释放内存,导致内存泄漏,那么这里引入了智能指针可以比较有效的防止类似事情大量的发生,我这里只是保守的说防止大量发生,这是因为即使有了很好的工具,不正确的使用,也是无法防止错误的发生。
其实原理很简单,就是使用强指针(sp)、弱指针(wp)来代替普通的指针,这种指针基于引用计数,来智能的管理对象指针,并不需要开发者做过多的内存管理操作。
1234567891011121314151617181920class Student: public RefBase {public: Student(const char* name) { LOG(INFO) << "Create & ...
dma-buf深入浅出--(1)简介
前言由于最近在开发新平台和新的Android 11的移植工作,需要把以前的一些驱动和方案移植到最新的Android OS上,有遇到一些Android OS间的差异,导致了有一些代码的调整,我这里就遇到了ION接口的改动导致需要做一些代码的调整,具体ION的接口差异可以查看下面的文章:
https://zhangjie201412.github.io/2021/02/16/Android-ION-3-DMA-BUF/
以前对dma-buf有一些认知,既然这还是比较新的一个知识点,那么我们就来系统的学习一下,以便于后面遇到了可以很方便的读懂代码。
dma-buf在Linux驱动中出现最多的就是在多媒体模块方面了,如果你接触过Android的Video、Camera、Display还是GPU,他们使用的buffer都是通过ION分配的,而现在Android的kernel中的ION的实现都是基于dma-buf。
历史dma-buf 最初的原型为 shrbuf,由 Marek Szyprowski (Samsung)于2011年8月2日首次提出,他实现了 “Buffer Sharing” 的 ...
Android ION内存管理(3) -- dma-buf
前面讲了如何在内核空间以及用户空间利用ion的接口分配内存、共享内存、同步内存数据,但是最近在浏览最新的AOSP的系统变更的时候发现接口都发生了改变:
https://source.android.com/devices/architecture/kernel/ion_abi_changes
意思就是在kernel 4.14版本和之后ION的接口有一个重大的重构,使得在使用kernel 4.14和之后的版本之后的一些代码都需要注意很多地方需要修改。特别是Display,Camera,DRM等模块的kernel驱动和硬件抽象层的代码。
下面来看看有哪些改动的地方。
其实在kernel 4.12已经开始重构ion的内核代码了,清除了一些和Android 框架层强耦合的代码,一些ion的ioctl接口被移除了。
移除ION clients和handles在kernel 4.12之前,通过打开dev/ion获取到ion client,然后通过IOC_ION_ALLOC ioctl 来分配一块新的buffer,到用户空间就是返回一个ion handle,这个handle就代表了一块buf ...
Android Input子系统 -- EventHub
前言前面其实也有提到EventHub的构造函数,里面就是创建epoll实例,然后把一些事件触发的文件描述符加入到epoll里面统一管理。
监控/dev/input/目录的iNotify文件mINotifyFd
接收Kernel驱动事件(/dev/input/eventX)的文件描述符
用来唤醒InputReader线程的管道读文件
EventHub是服务于InputReader线程的,前面在InputRead的构造函数里面有创建EventHub的实例。
InputReader线程InputReader线程主要就是查看threadLoop接口中代码的实现,threadLoop返回值是true代表的是会不断的循环,返回false的话就不会继续在调用threadLoop函数。
1234bool InputReaderThread::threadLoop() { mReader->loopOnce(); return true;}
不停的调用InputReader的loopOnce函数
loopOnce函数InputReader.cpp
12345 ...