1.配置C++的平台学习环境
2.OpenHarmony 3GPP协议开发深度剖析——一文读懂RIL
3..cp是什么意思?
4.linuxä¸cpå½ä»¤å¦ä½ç¨ Cè¯è¨å®ç°
5.源码详解系列(八)--全面讲解HikariCP的使用和源码
配置C++的学习环境
配置C++的学习环境是学习C++语言的基础,主要涉及文本编辑器与C++编译器的源码安装与使用。首先,平台确保您的源码电脑上安装了文本编辑器和C++编译器。文本编辑器用于创建源文件,平台源文件保存程序源代码,源码kd底背离划线公式源码扩展名通常为.cpp、平台.cp或.c。源码编译器用于将源代码转化为可执行程序,平台最常用的源码免费编译器是GNU的C/C++编译器。根据操作系统不同,平台安装方法也有所差异: 对于使用Linux或UNIX系统的源码用户,可以使用命令行检查是平台否已安装GCC。若未安装,源码请按照gcc.gnu.org/install/上的平台说明安装。 Mac OS X用户可通过苹果官网下载并安装Xcode开发环境,Xcode内含GNU编译器。 在Windows系统下,安装MinGW是一个便捷方式。访问mingw-w.org下载最新版本的MinGW安装程序,并确保安装gcc-core、gcc-g++、源码空间 外包binutils和MinGW runtime。添加MinGW的bin子目录到PATH环境变量中,以便在命令行中通过名称直接指定工具。 接下来,介绍使用Visual Studio编译C++程序的步骤。首先下载并安装Visual Studio,打开Visual Studio Community,创建一个Win Console Application项目,设置项目名称为MyFirstProgram,添加一个名为main.cpp的C++文件,拷贝代码并运行项目。完成这些操作后,可以使用g++命令进行编译链接。 程序g++是将gcc默认语言设为C++的一个特殊版本,用于编译链接C++程序。通过g++编译程序的常用命令包括:编译并生成默认名称的可执行文件:`g++ helloworld.cpp`。
编译并指定输出文件名:`g++ helloworld.cpp -o helloworld`。
指定使用C++标准编译:`g++ main.cpp -std=c++`。
通过这些步骤,可以有效地配置学习环境并开始使用C++编程。OpenHarmony 3GPP协议开发深度剖析——一文读懂RIL
市场上针对终端操作系统3GPP协议开发的easywechat接入源码相关资料较为稀缺,即便在Android领域,相关学习文档也较为有限,更不用说专门的协议开发书籍了。这可能与市场需求有关,目前市场上从事前后端软件开发的人员最多,包括我自己。
鉴于我在某手机协议开发团队工作过一段时间,对协议的AP侧和CP侧开发都有所涉猎,因此我尝试基于OpenAtom OpenHarmony(以下简称“OpenHarmony”)源码编写一些内容,旨在帮助大家了解协议开发领域,尽可能将3gpp协议内容与OpenHarmony电话子系统模块相结合进行讲解。据我所知,目前终端协议开发人才非常紧缺。首先声明,我不是协议专家,且已离开该领域五六年,如有错误,欢迎指正。
谈到终端协议开发,我首先想到的就是RIL。
CP:Communication Processor(通信处理器),录制屏幕源码通常理解为modem侧,也可以理解为底层协议,这部分由各个modem芯片厂商完成(如海思、高通)。
AP:Application Processor(应用处理器),通常指手机终端,通常理解为上层协议,主要由操作系统Telephony服务进行处理。
RIL:Radio Interface Layer(无线电接口层),通常理解为硬件抽象层,即AP侧将通信请求传给CP侧的中间层。
AT指令:AT指令是应用于终端设备与PC应用之间连接与通信的指令。
常规的Modem开发与调试可以使用AT指令进行操作,而各家的Modem芯片的AT指令都会有各自的差异。因此,手机终端厂商为了能在各种不同型号的产品中集成不同modem芯片,需要进行解耦设计来屏蔽各家AT指令的差异。
于是,OpenHarmony采用RIL对Modem进行HAL(硬件抽象),作为系统与Modem之间的通信桥梁,为AP侧提供控制Modem的tinymce 网页源码接口,各Modem厂商则负责提供对应于AT命令的Vender RIL(这些一般为封装好的so库),从而实现操作系统与Modem间的解耦。
框架层:Telephony Service,电话子系统核心服务模块,主要功能是初始化RIL管理、SIM卡和搜网模块。对应OpenHarmony的源码仓库OpenHarmony/telephony_core_service。这个模块也是非常重要的一个模块,后期单独再做详细解读。
硬件抽象层:即我们要讲的RIL,对应OpenHarmony的源码仓库OpenHarmony/telephony_ril_adapter。RIL Adapter模块主要包括厂商库加载,业务接口实现以及事件调度管理。主要用于屏蔽不同modem厂商硬件差异,为上层提供统一的接口,通过注册HDF服务与上层接口通讯。
芯片层:Modem芯片相关代码,即CP侧,这些代码各个Modem厂商是不开放的,不出现在OpenHarmony中。
硬件抽象层又被划分为hril_hdf层、hril层和venderlib层。
hril_hdf层:HDF服务,基于OpenHarmony HDF框架,提供hril层与Telephony Service层进行通讯。
hril层:hril层的各个业务模块接口实现,比如通话、短彩信、数据业务等。
vendorlib层:各Modem厂商提供的对应于AT命令库,各个厂商可以出于代码闭源政策,在这里以so库形式提供。目前源码仓中已经提供了一套提供代码的AT命令操作,至于这个是针对哪个型号modem芯片的,我后续了解清楚再补充。
下面是ril_adapter仓的源码结构:
本文解读RIL层很小一部分代码,RIL是如何通过HDF与Telephony连接上的,以后更加完整的逻辑梳理会配上时序图讲解,会更加清晰。首先,我们要对OpenHarmony的HDF(Hardware Driver Foundation)驱动框架做一定了解,最好是动手写一个Demo案例,具体的可以单独去官网查阅HDF资料。
首先,找到hril_hdf.c文件的代码,它承担的是驱动业务部分,源码中是不带中文注释的,为了梳理清楚流程,我给源码关键部分加上了中文注释。
上述代码中配置了对应该驱动的moduleName为"hril_hdf",因此我们需要去找到对应驱动的配置文件,以HiDV开发板为例,它的驱动配置在vendor_hisilicon/HiDV/hdf_config/uhdf/device_info.hcs代码中可以找到,如下:
这里可以发现该驱动对应的服务名称为cellular_radio1,那么telephony_core_service通过HDF与RIL进行通信肯定会调用到该服务名称,因此无查找telephony_core_service的相关代码,可以很快定位到telephony_core_service/services/tel_ril/src/tel_ril_manager.cpp该代码,该代码中有一个关键类TelRilManager,它用来负责管理tel_ril。
看tel_ril_manager.cpp中的一个关键函数ConnectRilAdapterService,它就是用来通过HDF框架获取RIL_ADAPTER的服务,之前定义过RIL_ADAPTER_SERVICE_NAME常量为"cellular_radio1",它就是在vendor_hisilicon/XXXX/hdf_config/uhdf/device_info.hcs中配置的hril_hdf驱动对应的服务名称。
.cp是什么意思?
“。cp”是一种文件格式后缀,英文全称是“C++ source file”,意思是C++源代码文件。当我们用C++语言编写程序时,我们通常需要使用一个文本编辑器编写程序代码,并将程序代码保存为.cp文件格式。cp文件包含了程序的源代码,可以用编译器将其转换为可执行的程序。
.cp文件是用来编写和存储C++程序的源代码文件。通常情况下,程序员会使用一个文本编辑器(如Notepad++、Sublime Text等)来编写程序代码,并将其存储为.cp文件格式。这样做的好处是可以将代码进行版本控制,以便记录程序的历史修改记录,并保留之前版本的代码,方便以后的追溯和比对。
如果想要打开并编辑.cp文件,我们需要一个文本编辑器。常见的文本编辑器有Notepad++、Sublime Text等。在打开.cp文件时,最好使用专业的编程工具进行编辑,比如Visual Studio。这些工具可以自动识别和高亮显示C++语言的关键字,提高编程效率和体验。另外,如果想要运行.cp文件,需要使用C++编译器将源代码转换为可执行文件,然后在计算机上运行即可。
linuxä¸cpå½ä»¤å¦ä½ç¨ Cè¯è¨å®ç°
1ï¼é¦å éè¦äºè§£cpçåçã2ï¼å¯ä»¥åècpçæºç å»äºè§£å ¶åç
3ï¼cpå½ä»¤çæºç å¯ä»¥å¨linuxå æ ¸ä¸æ¾å°ã
4ï¼æè ä¸è½½busyboxå ¶ä¸ä¹ä¼æcpçæºç
åªæäºè§£å ¶åçä¹åæè½è°å¦ä½å®ç°ãåè代ç å¦ä¸ï¼
#include <stdio.h>#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#define BUF_SIZE
#define PATH_LEN
void my_err(char *err_string, int line )
{
fprintf(stderr,"line:%d ",line);
perror(err_string);
exit(1);
}
void copy_data(const int frd,const int fwd)
{
int read_len = 0, write_len = 0;
unsigned char buf[BUF_SIZE], *p_buf;
while ( (read_len = read(frd,buf,BUF_SIZE)) ) {
if (-1 == read_len) {
my_err("Read error", __LINE__);
}
else if (read_len > 0) { //æ读åé¨ååå ¥ç®æ æ件
p_buf = buf;
while ( (write_len = write(fwd,p_buf,read_len)) ) {
if(write_len == read_len) {
break;
}
else if (write_len > 0) { //åªåå ¥é¨å
p_buf += write_len;
read_len -= write_len;
}
else if(-1 == write_len) {
my_err("Write error", __LINE__);
}
}
if (-1 == write_len) break;
}
}
}
int main(int argc, char **argv)
{
int frd, fwd; //读åæ件æ述符
int len = 0;
char *pSrc, *pDes; //åå«æåæºæ件路å¾åç®æ æ件路å¾
struct stat src_st,des_st;
if (argc < 3) {
printf("ç¨æ³ ./MyCp <æºæ件路å¾> <ç®æ æ件路å¾>\n");
my_err("arguments error ", __LINE__);
}
frd = open(argv[1],O_RDONLY);
if (frd == -1) {
my_err("Can not opne file", __LINE__);
}
if (fstat(frd,&src_st) == -1) {
my_err("stat error",__LINE__);
}
/*æ£æ¥æºæ件路å¾æ¯å¦æ¯ç®å½*/
if (S_ISDIR(src_st.st_mode)) {
my_err("ç¥è¿ç®å½",__LINE__);
}
pDes = argv[2];
stat(argv[2],&des_st);
if (S_ISDIR(des_st.st_mode)) { //ç®æ è·¯å¾æ¯ç®å½ï¼å使ç¨æºæ件çæ件å
len = strlen(argv[1]);
pSrc = argv[1] + (len-1); //æåæåä¸ä¸ªå符
/*å æ¾åºæºæ件çæ件å*/
while (pSrc >= argv[1] && *pSrc != '/') {
pSrc--;
}
pSrc++;//æåæºæ件å
len = strlen(argv[2]);
// . 表示å¤å¶å°å½åå·¥ä½ç®å½
if (1 == len && '.' == *(argv[2])) {
len = 0; //没æç³è¯·ç©ºé´ï¼åé¢å°±ä¸ç¨éæ¾
pDes = pSrc;
}
else { //å¤å¶å°æç®å½ä¸ï¼ä½¿ç¨æºæ件å
pDes = (char *)malloc(sizeof(char)*PATH_LEN);
if (NULL == pDes) {
my_err("malloc error ", __LINE__);
}
strcpy(pDes,argv[2]);
if ( *(pDes+(len-1)) != '/' ) { //ç®å½ç¼ºå°æåç'/'ï¼åè¡¥ä¸â/â
strcat(pDes,"/");
}
strcat(pDes+len,pSrc);
}
}
/* æå¼ç®æ æä»¶ï¼ ä½¿æéä¸æºæ件ç¸å*/
fwd = open(pDes,O_WRONLY | O_CREAT | O_TRUNC,src_st.st_mode);
if (fwd == -1) {
my_err("Can not creat file", __LINE__);
}
copy_data(frd,fwd);
//puts("end of copy");
if (len > 0 && pDes != NULL)
free(pDes);
close(frd);
close(fwd);
return 0;
}
源码详解系列(八)--全面讲解HikariCP的使用和源码
源码详解系列(八):HikariCP深度剖析
HikariCP是一个高效数据库连接池,它的核心在于通过“池”复用连接,减少创建和关闭连接的开销。本文将全面介绍HikariCP的使用方法和源码细节。使用场景与内容
本文将涉及HikariCP的以下内容:如何获取连接对象并进行基本操作
项目环境设置,包括JDK、Maven版本和依赖库
如何配置HikariCP,包括依赖引入和配置文件编写
初始化连接池,以及通过JMX进行管理
源码分析,重点讲解ConcurrentBag和HikariPool类,以及其创新的“标记模型”
HikariDataSource的两个HikariPool的用意和加载配置
核心原理
HikariCP的性能优势主要源于其“标记模型”,通过减少锁的使用,提高并发性能。它使用CopyOnWriteArrayList来保证读操作的效率,结合CAS机制实现无锁的借出和归还操作。源码亮点
源码简洁且易读,特别是ConcurrentBag类,它是HikariCP的核心组件。类结构与DBCP2类似,包含一个通用的资源池,可以应用于其他需要池化管理的场景。总结
通过本文,读者可以深入了解HikariCP的工作原理,掌握其配置和使用技巧,以及源码实现。希望本文对数据库连接池有深入理解的开发者有所帮助。参考资料:
HikariCP官方GitHub地址