C语言
文章平均质量分 67
土豆西瓜大芝麻
这个作者很懒,什么都没留下…
展开
-
解决CMake时的Find_Package失败问题
今天在编译组内代码时遇到了Find_package问题,具体来说就是找不到redis的库及相关头文件。针对上述问题,我们查找并安装了class_loader的开发库,上述问题就解决了。也就是继续执行cmake,又出现了问题,找不到hiredis库使用前面的方法,发现安装hiredis的开发库之后,仍然报错。然后使用whereis查找hiredis对应的头文件和库。分别在/usr/include/hiredis下面和/usr/lib/x86_64-linux-gnu下面。然后重新执行cmake,成功。原创 2023-01-03 14:55:58 · 12538 阅读 · 0 评论 -
Linux内核模块使用浮点float double运算的方法
最近我们有一个需求,需要把用户态的浮点数运算全部放到内核态运行,以提高运行速度,移植的过程中发现问题没有这么简单,然后我们抽丝剥茧,揭开 Linux 对浮点float double处理的原理。转载 2022-12-09 06:21:07 · 4361 阅读 · 0 评论 -
linux 内核中 memcpy 和 memmove 函数的区别和实现
memcpy 和memmove都是把 src 指向的对象中的 size 个字符拷贝到 dest 所指向的对象中,返回指向结果对象的指针。但这两个函数在处理内存区域重叠的方式不同。转载 2022-11-25 11:07:55 · 1088 阅读 · 0 评论 -
使用互斥锁mutex进行进程间同步的说明和示例
进程间同步可以使用互斥量mutex(互斥锁)、信号量和文件锁。这里面的重要函数是pthread_mutex_init(),它负责进行互斥锁的初始化,只有初始化之后才能使用它进行加锁、解锁。这里需要说明的是,mutex不仅可以用于进程间的同步,还可以用于线程间的同步,默认情况下是线程间同步。如果要用于进程间同步,则需要在pthread_mutex_init初始化之前,修改其属性为进程间共享。pthread_mutexattr_t mattr 类型就是用于定义mutex锁的属性的。转载 2022-11-24 17:32:04 · 1590 阅读 · 1 评论 -
年月日时分秒的正则表达式
日期和时间的正则表达式,可以判断非法日期和时间。原创 2022-11-17 21:13:11 · 2310 阅读 · 0 评论 -
System V的共享内存shm的释放问题
这样,System V中的共享内存的对象如果没有被显示地删除的话,及时所有访问共享内存的进程都已经终止了,该共享内存区域的对象仍然会在内核中出现,也就是System V的共享内存对象的生命周期是和系统内核的生命周期一致的。但是这里面有个麻烦的地方是,写进程每几秒钟就会申请一个新的20M的共享内存(因为有些原因,不能使用同一个共享内存),为了防止共享内存消耗过大,它维护了一个长度20的vector,当超出时就删掉共享缓冲区,调用的shmDel操作。读进程也会从相应的新的共享内存中读取新的数据。原创 2022-11-08 22:09:40 · 415 阅读 · 0 评论 -
Hook技术
linux上基于C和C++的hook尝试原创 2022-09-06 16:38:39 · 3737 阅读 · 0 评论 -
fork出来的父子进程对信号的处理
在terminal中运行的父子进程在收到ctrl+c时如何响应。原创 2022-09-05 23:15:21 · 1737 阅读 · 0 评论 -
addr2line定位段错误
addr2line 动态库转载 2022-08-28 01:05:24 · 2284 阅读 · 0 评论 -
C实现的UDP压力测试工具
UDP压力测试工具转载 2022-08-16 16:01:17 · 755 阅读 · 0 评论 -
基于inotify实现落盘文件的跨进程实时读写交互
基于inotify实现落盘文件的跨进程实时读写交互原创 2022-08-08 15:46:13 · 478 阅读 · 2 评论 -
基于Inotify封装的C++事件类
C++实现的文件粒度的事件类封装。原创 2022-08-08 14:34:37 · 828 阅读 · 0 评论 -
格式化输出当前时间
近期在测试跨进程数据共享时需要测试延时情况,在不适用日志系统的情况下,我们要对别多个进程在数据读写的时刻的差值,为此需要记录各操作对应的时刻,使用uint64_4打印timestamp是一种可行的方式,但是看着还是别扭,于是采用亲和人眼的年月日时分秒的方式。这段代码比较简单,做成一个函数后面使用吧,也供有需要的人使用。编译g++ test.cpp -o test即可。...原创 2022-08-05 11:28:45 · 352 阅读 · 0 评论 -
高性能c++ string split实现
原文链接https//blog.csdn.net/Sweet_Oranges/article/details/107509383。测试分别执行100000次,split耗时257329us,boostsplit耗时679503us。测试得知比boostsplit方法大概快2倍。类似于string_view。转载 2022-07-20 23:58:19 · 665 阅读 · 0 评论 -
C++中float和double的比较
前面的例子中x==0.1导致了x变量提升到double(因为右边的0.1是double类型,所以x要提升到double),double位数比float要多,这时候就需要二进制补全(x进行了补全,只是把后面缺的近30位补成了0,而不是把x这个0.1重新按照double进行组织,也就是补全后的x虽然小数部分达到了52位,但是后面的29位都是0)。由于float的位数(23)要小于double(52)的位数,在x变量提升到double后,编译器会将多余的尾补全尾0。x==0.1f返回了true。...原创 2022-07-20 22:46:25 · 3110 阅读 · 0 评论 -
C++的UDP收包recvfrom一直失败,返回-1,错误码10022
记录一个使用socket库中遇到的问题,最近项目中遇到使用本地udp通信的情况,在编写程序过程中,发现调用recvfrom一直失败,返回-1,错误码10022(错误码很重要)。排查了半个下午,终于发现原来是bind函数的问题。由于在文件开头使用了 using namespace std 导致默认的bind变成了 functional中的那个,而不是socket的bind,导致绑定一直没有成功。当然,也可能是套接字端口被占用,recvfrom直接返回-1(但运行不报错),错误码是10044和10022(放在不转载 2022-06-20 14:03:50 · 4707 阅读 · 0 评论 -
std::thread线程命名
也可以参考我另外一篇文章,另外一篇更详细些。为线程设置名字的最大的好处是在程序出错时,它会出现在 GDB 的出错信息里,可以更快地定位问题。有两种方法可以给线程设置名字:一种在线程的调用函数内部设置,还有一种是在外部对指定线程变量做设置。原创 2022-06-02 15:52:14 · 3163 阅读 · 1 评论 -
在C++中创建线程时为线程设置名字
在进行多线程调试时,不知道哪个线程起来没起来,如果不设置独立的名字,则没法区分。因此考虑给每个线程设置一个名字,这样就可以方便直观查看了。第一个参数是操作类型,指定PR_SET_NAME,即设置进程名第二个参数是进程名字符串,长度至多16字节prctl 缺点prctl()只能设置/获取当前线程的名字注意:只能设置本线程的名称,传入参数线程名超出长度,会自动截断由于prctl的缺点,所以pthread_setname_np()和pthread_getname_np应运而生,能设置指定线程的名称。注意原创 2022-06-01 22:38:26 · 5716 阅读 · 0 评论 -
宋宝华:Linux为什么一定要copy_from_user
这个问题,我认为需要从2个层面回答第一个层次是为什么要拷贝,可不可以不拷贝? 第二个层次是为什么要用copy_from_user而不是直接memcpy为什么要拷贝拷贝这个事情是必须的,这个事情甚至都跟Linux都没有什么关系。比如Linux有个kobject结构体,kobject结构体里面有个name指针:struct kobject { const char *name; struct list_head entry; struct kobject *paren转载 2022-03-22 15:09:45 · 903 阅读 · 3 评论 -
讲的最清楚的正则表达式
什么是正则表达式?正则表达式(Regular Expression 或 Regex),是用于定义某种特定搜索模式的字符组合。正则表达式可用于匹配、查找和替换文本中的字符,进行输入数据的验证,查找英文单词的拼写错误等。调试工具下面列出了几款优秀的在线调试工具,如果你想创建或者调试正则表达式可能会需要。个人比较偏好Regex101,regex101 支持在正则表达式的不同 flavor 之间切换、解释你的正则表达式、显示匹配信息、提供常用语法参考等功能,非常强大。当然除了Regex101和Regex转载 2022-03-22 14:41:43 · 405 阅读 · 0 评论 -
C语言函数参数是如何传递的?
前言我们可能听过C语言中的传值和传指针,在其他语言中,也有传引用一说,那么他们到底有什么区别呢?如果你还不能准确地分辨,就该好好了解一下了。传值我们在初学C语言的时候就被老师教过,下面的方式是无法交换a和b的值的:#include<stdio.h>void swap(int a,int b){ int temp = a; a = b; b = temp; printf("swap a = %d,b = %d\n",a,b);}int main(void){转载 2022-03-14 16:16:15 · 2147 阅读 · 0 评论 -
确认主机是大端机还是小端机
何为大端、小端大端还是小端不好理解和记忆是因为当初翻译是有问题的。翻译成“高尾端”和“低尾端”会更好理解。如果把一个数看成一个字符串,比如11223344看成"11223344",末尾是个'\0','11'到'44'各占用一个存储单元,那么它的尾端很显然是44,如果44放在后面(按照数组的表示,数组开头地址最小,后面的地址可以用首地址+i来表示,后面的地址高于或者大于前面的地址)则表示高尾端;如果44放在了前面,则表示低尾端。如下图: 如果用c...原创 2021-12-21 20:22:55 · 1103 阅读 · 0 评论 -
C++类对象构造函数出错malloc: memory corruption
问题1问题概述:编译插件代码,cmake和make均成功,但是执行sudo make install时报错cannot find -lclass_loader,在CMakeLists.txt中添加find_package(class_loader),cmake时提示可以找到class_loader,但是make install 还是报错。解决方案:修改系统时间 sudo date -s “YYYY/MM/DD HH:mm:ss”。问题2问题概述:pm_test中起线程执行pm原创 2021-12-06 19:47:40 · 1584 阅读 · 0 评论 -
IP地址转换为整数
IP地址转换为整数:比如"192.168.1.254",以点为分割,将192 168 1 254保存在一个int a[4]数组里,然后通过unsigned int nResult = (a[3] << 24) + (a[2] << 16) + (a[1] << 8) + a[0]得到一个无符号32位整数。整数转换为IP地址:把这个整数转换成一个无符号32位二进制数。从左到右,每八位进行一下分割,得到4段8位的二进制数,把这些二进制数转换...原创 2021-11-10 16:56:46 · 2524 阅读 · 0 评论 -
C++文件中调用c文件中的函数报错collect2: error: ld return xxx undefined reference
今天我们在封装传感器插件的时候,出现一个问题。将包使用cmake的方式编译生成.so文件的时候出错,collect2: error: ld return xxx undefined reference,表示某个函数A没有定义。实际上该函数A是在一个a.c中定义和实现的,同时在a.h对函数A进行了声明。函数A是在b.cpp中调用的,同时在b.h中include了a.h。 针对这个问题,有两种解决方式:1. 将a.c改成a.cpp首先尝试将a.c改成了a...原创 2021-11-10 16:24:42 · 1636 阅读 · 0 评论 -
安装自定义模块到系统中并在独立工程中使用find_package找到
因为项目目前采用的程序和库的构建方式是把所有的库和可执行程序都安装到/opt/xxx/1.0.1/bin 或者/opt/xxx/1.0.1/lib 以及/opt/xxx/1.0.1/include目录下。但这种写死的方式肯定是不太合适的,因此有必要掌握常用的其他安装方式,比如说我们安装了OpenCV等常用库,它们会安装到何处,怎么使用它们。 基于Cmake编译的C++工程常见的一种第三方库文件的使用方式是find_package()函数,在使用时还是挺方便的。但是如何构建自...原创 2021-11-02 21:06:24 · 2894 阅读 · 0 评论 -
C++ 变量的定义与声明的区别
变量的定义变量的定义用于为变量分配存储空间,还可以为变量指定初始值。在一个程序中,变量有且仅有一个定义。变量的声明用于向程序表明变量的类型和名字。程序中变量可以声明多次,但只能定义一次。变量的声明有两种情况一种是分配内存空间的(声明)。例如:int a在声明的时候就已经分配了内存空间。 另一种是不需要分配内存空间的(声明)。例如:extern int a其中变量a是在别的文件中定义的。第一种是"定义性声明",或者称为”定义",第二种是"引用性声明"。...转载 2021-10-29 17:09:34 · 513 阅读 · 0 评论 -
C++中的头文件和源文件
一、C++编译模式通常,在一个C++程序中,只包含两类文件——.cpp文件和.h文件。其中,.cpp文件被称作C++源文件,里面放的都是C++的源代码;而.h文件则被称作C++头文件,里面放的也是C++的源代码。C+ +语言支持“分别编译”(separate compilation)。也就是说,一个程序所有的内容,可以分成不同的部分分别放在不同的.cpp文件里。.cpp文件里的东西都是相对独立的,在编译(compile)时不需要与其他文件互通,只需要在编译成目标文件后再...原创 2021-10-29 11:50:19 · 2526 阅读 · 0 评论 -
查看linux下程序或者动态库到底依赖哪些so动态库以及对应的版本
基本上每一个linux 程序都至少会有一个动态库,查看某个程序使用了那些动态库,使用ldd命令查看#ldd/bin/lslinux-vdso.so.1=>(0x00007fff597ff000)libselinux.so.1=>/lib64/libselinux.so.1(0x00000036c2e00000)librt.so.1=>/lib64/librt.so.1(0x00000036c2200000)libcap.so.2=>...原创 2021-10-29 00:30:05 · 13244 阅读 · 0 评论 -
linux c 的void *指针的加减算术运算的说明
Pointer (computer programming)Pointer arithmetic cannot be performed on void pointers because the void type has no size, and thus the pointed address can not be added to, although gcc and other compilers will perform byte arithmetic on void* as a non-sta原创 2021-10-27 10:22:14 · 1549 阅读 · 0 评论 -
什么是makefile
1什么是Makefile在之前学习C程序的编译过程中,我们知道编译一个程序还比较简单, 如果要编译多个文件,或者不同文件夹中的文件,需要生成不同的库文件,以及确定这些文件的编译先后顺序,往往所需要的命令行特别多,而且比较复杂,甚至对于以后项目的维护也比较麻烦。 再想想如果我们需要编译Linux内核这样好几W个文件的项目难道需要我们一个命令的输入吗 ? 那估计是一场噩梦。 那么这个时候如果我们能够把所有的编译规则全部规范到文件中,然后通过解析该文件去执行对应的编译...转载 2021-10-19 16:30:10 · 14017 阅读 · 0 评论 -
Makefile入门
0. 前言粉丝留言,想知道如何使用Makefile给多个文件和多级目录建立一个工程,必须安排!关于Makefile的入门参考文章,可以先看这篇文章:《Makefile入门教程》为了让大家有个更加直观的感受,一口君将之前写的一个小项目,本篇在该项目基础上进行修改。该项目详细设计和代码,见下文:《从0写一个《电话号码管理系统》的C入门项目【适合初学者】》一、文件好了,开始吧!我们将该项目的所有功能函数放到以该函数名命名的c文件,同时放到对应名称的子目录中。比如函数allf转载 2021-10-19 16:25:25 · 193 阅读 · 0 评论 -
对Vector内的结构体对象按照结构体内某成员进行排序
首先定义一个结构体:struct stu{ float y; int age; string name;};然后定义一个比较函数,并返回布尔值。bool comp(const struct stu & a, const struct stu & b){ return a.age < b.age;}这个是从小到大的排序。vector<stu> vl;for (s...原创 2021-10-15 09:31:21 · 1075 阅读 · 0 评论 -
linux c 使用fifo管道进行多线程间通信
创建有名管道,如果管道存在则直接使用//创建有名管道,如果管道存在则直接使用 int n = mkfifo("./myfifo",0664); if( n < 0 && errno!=EEXIST) { perror("mkfifo"); return -1; }负责管道写数据线程void *thread_fun_write(void *p){ char *buf = "12345"; i...原创 2021-10-13 15:12:34 · 2083 阅读 · 0 评论 -
C++11允许定义结构体时给成员赋初始值
在C++11之前,我们定义结构体时,只是声明了一个机构体的构成,并不能给其中的成员赋初始值。在使用的时候,先生成一个结构体对象,然后才能对其成员逐个赋值,这种方式肯定是我们不喜欢的。 在C++11之前,创建结构体只是开辟了一块内存空间,而不赋初始值,赋初始值有的编译器不支持的! 从C++11之后,编译器就支持在结构体的定义时进行成员初始化。#include <iostream>using namespace std;...原创 2021-10-13 10:08:16 · 5185 阅读 · 0 评论 -
Linux内核中的list_head双向链表详解
做内核驱动开发经常会使用linux内核最经典的双向链表 list_head, 以及它的拓展接口(或者宏定义): list_add , list_add_tail, list_del , list_entry ,list_for_each , list_for_each_entry ...... 每次看到这些接口,感觉都很像,今天专门研究了一下内核,对它们做一些总结,希望为后续开发提供方便。首先找到list_head 结构体定义,kernel/inclue...转载 2021-10-09 11:26:25 · 1965 阅读 · 2 评论 -
2021-09-29
alarm也称为闹钟函数,alarm()用来设置信号SIGALRM在经过参数seconds指定的秒数后将SIGALRM信号传送给目前的进程。如果参数seconds为0,则之前设置的闹钟会被取消,并将剩下的时间返回。要注意的是,一个进程只能有一个闹钟时间,如果在调用alarm之前已设置过闹钟时间,则任何以前的闹钟时间都被新值所代替。所需头文件 #include<unistd.h>函数原型 unsigned int alarm(unsigned int seconds)...原创 2021-09-29 11:22:37 · 112 阅读 · 0 评论 -
linux C++ 简单的线程池
线程池中维护了一个存放线程的数组以及一个任务队列。在创建线程池(构造函数中)时创建若干个线程,起始时由于任务队列中没有任务,创建的每一个线程都处于阻塞状态。使用pthread_create函数创建线程时把所有的线程与同一个函数关联在一起,也就是产生如下的代码:pthread_t p[5]; //线程池中有5个线程for(int i = 0; i < 5; ++i){ pthread_create(&p[i], NULL, func, NULL);}...转载 2021-09-14 17:12:26 · 197 阅读 · 0 评论 -
C++调用python脚本
环境:Windows10;python3.7.4;visual studio 2019;安装python,opencv(如果用到的话),以及将二者目录添加到vs中的包含目录和库目录就不再说了。教程一大堆,自己配置好。以下步骤都建立在这些环境配置成功之后。重要:将Python安装目录下的include和libs文件夹引入到项目中将libs目录下的python37.lib复制一份为python37_d.lib一、Python脚本这个python脚本和C++编译成功后生成的.ex转载 2021-06-24 10:28:51 · 1821 阅读 · 0 评论 -
将python工程生成cmake包并使用find_package验证
这一段我们在借鉴ros的genmsg包的实现来创建我们的数据定义到.h文件的自动生成机制。但是genmsg是ros中基于python写的包,还依赖gencpp等包。鉴于此,我们分成几步来做这件事。(1)将ros中的genmsg包及其依赖的包都抽出来,变成一个与ros环境无关的工程gendo,然后在该工程中进行msg文件到.h文件的测试。但是没有使用catkin_make和cmake,而是用的python脚本。(2)在gendo中编写一个cpp和.h文件,里面定义一个函数。在该函数中创建一个pytho原创 2021-06-23 11:32:56 · 1885 阅读 · 0 评论