首页
chatGPT
关于
友链
其它
统计
更多
壁纸
留言
Search
1
cgroup--(4)cgroup v1和cgroup v2的详细介绍
6,378 阅读
2
修改Linux Kernel defconfig的标准方法
6,375 阅读
3
Android系统之VINTF(1)manifests&compatibility matrices
5,953 阅读
4
使用git生成patch和应用patch
3,440 阅读
5
c语言的__attribute__
3,165 阅读
默认分类
文章收集
学习总结
算法
环境配置
知识点
入门系列
vim
shell
Git
Make
Android
Linux
Linux命令
内存管理
Linux驱动
Language
C++
C
工具
软件工具
Bug
COMPANY
登录
Search
标签搜索
shell
Linux
c
uboot
Vim
vintf
Linux驱动
Android
device_tree
git
DEBUG
arm64
链表
数据结构
IDR
内核
ELF
gcc
ARM
网址
adtxl
累计撰写
365
篇文章
累计收到
14
条评论
首页
栏目
默认分类
文章收集
学习总结
算法
环境配置
知识点
入门系列
vim
shell
Git
Make
Android
Linux
Linux命令
内存管理
Linux驱动
Language
C++
C
工具
软件工具
Bug
COMPANY
页面
chatGPT
关于
友链
其它
统计
壁纸
留言
搜索到
7
篇与
的结果
2022-11-09
使用AddressSanitzier后0xbebebebe值是什么意思
暂无简介
2022年11月09日
405 阅读
0 评论
0 点赞
2021-06-07
OpenGrok使用说明
OpenGrok一个快速、便于使用的源代码搜索与对照引擎。它帮助你搜索,对照,定位你的源代码树。它能够明白各种程序文件格式和版本控制历史记录。
2021年06月07日
1,438 阅读
0 评论
0 点赞
2021-01-19
dtb文件的反汇编
在使用设备树时我们将*.dts文件利用dtc编译器编译为*.dtb文件。在已知*.dtb文件的情况下我们有两种方法可以得到dts源码:1. 使用fdtdump工具进行反汇编使用命令:root#fdtdump *.dtb > temp.dts反汇编生成的内容保存在temp.dts2. 使用dtc编译器进行反汇编dtc -h 可以查看dtc命令的帮助使用命令:root# dtc -I dtb -O dts -o temp1.dts s5pv210-smdkv210.dtb
2021年01月19日
1,015 阅读
0 评论
0 点赞
2021-01-18
Git常用命令助记
1. git的全局配置文件#查看当前的配置信息: $git config --list #编辑配置文件: $git config -e [--global] #配置提交代码时的账户信息: $git config [--global] user.name "[name]" $git config [--global] user.email "[email address]"2. 增加/删除文件#添加指定文件到暂存区 $git add [file1] [file2] ... #添加指定目录到暂存区,包括子目录 $git add [dir] #添加当前目录的所有文件到暂存区 $git add . #添加每个变化前,都会要求确认# 对于同一个文件的多处变化,可以实现分次提交 $git add -p #删除工作区文件,并且将这次删除放入暂存区 $git rm [file1] [file2] ... #停止追踪指定文件,但该文件会保留在工作区 $git rm --cached [file] #改名文件,并且将这个改名放入暂存区 $git mv [file-original] [file-renamed]3. 代码提交#提交暂存区到仓库区 $git commit -m [message] #提交暂存区的指定文件到仓库区 $git commit [file1] [file2] ... -m [message] #提交工作区自上次commit之后的变化,直接到仓库区 $git commit -a #提交时显示所有diff信息 $git commit -v #使用一次新的commit,替代上一次提交 $git commit --amend -m [message] #重做上一次commit,并包括指定文件的新变化 $git commit --amend [file1] [file2] ...4. 分支操作#列出所有本地分支 $git branch #列出所有远程分支 $git branch -r #列出所有本地分支和远程分支 $git branch -a #新建一个分支,但依然停留在当前分支 $git branch [branch-name] #新建一个分支,并切换到该分支 $git checkout -b [branch] #新建一个分支,指向指定commit $git branch [branch] [commit] #新建一个分支,与指定的远程分支建立追踪关系 $git branch --track [branch] [remote-branch] #切换到指定分支,并更新工作区 $git checkout [branch-name] #切换到上一个分支 $git checkout - #建立追踪关系,在现有分支与指定的远程分支之间 $git branch --set-upstream [branch] [remote-branch] #合并指定分支到当前分支 $git merge [branch] #选择一个commit,合并进当前分支 $git cherry-pick [commit] #删除分支 $git branch -d [branch-name]5. 查看提交变更#显示有变更的文件 $git status #显示当前分支的版本历史 $git log #显示commit历史,以及每次commit发生变更的文件 $git log --stat #显示指定文件相关的每一次diff $git log -p [file] #显示过去5次提交 $git log -5 --pretty --oneline #显示指定文件是什么人在什么时间修改过 $git blame [file] #显示暂存区和工作区的差异 $git diff #显示暂存区和上一个commit的差异 $git diff --cached [file] #显示某次提交的元数据和内容变化 $git show [commit] #显示某次提交发生变化的文件 $git show --name-only [commit]
2021年01月18日
734 阅读
0 评论
0 点赞
2020-10-12
C库函数--memset()函数
描述在定义变量时一定要进行初始化,尤其是数组和结构体这种占用内存大的数据结构。在使用数组的时候经常因为没有初始化而产生“烫烫烫烫烫烫”这样的野值,俗称“乱码”。每种类型的变量都有各自的初始化方法,memset() 函数可以说是初始化内存的“万能函数”,通常为新申请的内存进行初始化工作。它是直接操作内存空间,mem即“内存”(memory)的意思。原型该函数的原型为:# include <string.h> void *memset(void *str, int c, size_t n);参数:str -- 指向要填充的内存块。c -- 要被设置的值。该值以 int 形式传递,但是函数在填充内存块时是使用该值的无符号字符形式。n -- 要被设置为该值的字符数。函数的功能是:将指针变量 s 所指向的前 n 字节的内存单元用一个“整数” c 替换,注意 c 是 int 型。str 是 void* 型的指针变量,所以它可以为任何类型的数据进行初始化。返回值:该值返回一个指向存储区 str 的指针。memset() 的作用是在一段内存块中填充某个给定的值。因为它只能填充一个值,所以该函数的初始化为原始初始化,无法将变量初始化为程序中需要的数据。用memset初始化完后,后面程序中再向该内存空间中存放需要的数据。memset 一般使用“0”初始化内存单元,而且通常是给数组或结构体进行初始化。一般的变量如 char、int、float、double 等类型的变量直接初始化即可,没有必要用 memset。如果用 memset 的话反而显得麻烦。当然,数组也可以直接进行初始化,但 memset 是对较大的数组或结构体进行清零初始化的最快方法,因为它是直接对内存进行操作的。这时有人会问:“字符串数组不是最好用'\0'进行初始化吗?那么可以用 memset 给字符串数组进行初始化吗?也就是说参数 c 可以赋值为'\0'吗?”可以的。虽然参数 c 要求是一个整数,但是整型和字符型是互通的。但是赋值为 '\0' 和 0 是等价的,因为字符 '\0' 在内存中就是 0。所以在 memset 中初始化为 0 也具有结束标志符 '\0' 的作用,所以通常我们就写“0”。memset 函数的第三个参数 n 的值一般用 sizeof() 获取,这样比较专业。注意,如果是对指针变量所指向的内存单元进行清零初始化,那么一定要先对这个指针变量进行初始化,即一定要先让它指向某个有效的地址。而且用memset给指针变量如p所指向的内存单元进行初始化时,n 千万别写成 sizeof(p),这是新手经常会犯的错误。因为 p 是指针变量,不管 p 指向什么类型的变量,sizeof(p) 的值都是 4。注意,C语言中的指针和数组名不完全等价,不能将它们混为一谈。下面写一个程序:# include <stdio.h> # include <string.h> int main(void) { int i; //循环变量 char str[10]; char *p = str; memset(str, 0, sizeof(str)); //只能写sizeof(str), 不能写sizeof(p) for (i=0; i<10; ++i) { printf("%d\x20", str[i]); } printf("\n"); return 0; }根据memset函数的不同,输出结果也不同,分为以下几种情况:memset(p, 0, sizeof(p)); //地址的大小都是4字节 0 0 0 0 -52 -52 -52 -52 -52 -52 memset(p, 0, sizeof(*p)); //*p表示的是一个字符变量, 只有一字节 0 -52 -52 -52 -52 -52 -52 -52 -52 -52 memset(p, 0, sizeof(str)); 0 0 0 0 0 0 0 0 0 0 memset(str, 0, sizeof(str)); 0 0 0 0 0 0 0 0 0 0 memset(p, 0, 10); //直接写10也行, 但不专业 0 0 0 0 0 0 0 0 0 0
2020年10月12日
40 阅读
0 评论
0 点赞
2020-09-24
c语言的左移和右移
https://www.cnblogs.com/lyggqm/p/7826938.html
2020年09月24日
851 阅读
0 评论
0 点赞
2020-09-15
c语言的__attribute__
[TOC]转载:https://blog.csdn.net/qlexcel/article/details/92656797https://www.cnblogs.com/embedded-linux/p/5801999.html一、介绍GNU C 的一大特色就是\_\_attribute\_\_ 机制。\_\_attribute\_\_ 可以设置函数属性(Function Attribute )、变量属性(Variable Attribute )和类型属性(Type Attribute )。\_\_attribute\_\_ 书写特征是:\_\_attribute\_\_ 前后都有两个下划线,并切后面会紧跟一对原括弧,\_\_attribute\_\_ 参数。\_\_attribute\_\_ 语法格式为:\_\_attribute\_\_ ((attribute-list))\_\_attribute\_\_ 也可以对结构体(struct )或共用体(union )进行属性设置。大致有六个参数值可以被设定,即:aligned, packed, transparent_union, unused, deprecated 和 may_alias 。\_\_attribute\_\_ 参数时,你也可以在参数的前后都加上“\_\_” (两个下划线),例如,使用\_\_aligned\_\_而不是aligned ,这样,你就可以在相应的头文件里使用它而不用关心头文件里是否有重名的宏定义。二、__attribute__参数介绍1.aligned该属性设定一个指定大小的对齐格式(以字节 为单位),例如:struct S { short b[3]; } __attribute__ ((aligned (8))); typedef int int32_t __attribute__ ((aligned (8)));该声明将强制编译器确保(尽它所能)变量类 型为struct S 或者int32_t 的变量在分配空间时采用8 字节对齐方式。如上所述,你可以手动指定对齐的格式,同 样,你也可以使用默认的对齐方式。如果aligned 后面不紧跟一个指定的数字值,那么编译器将依据你的目标机器情况使用最大最有益的对齐方式。例如:struct S { short b[3]; } __attribute__ ((aligned));这里,如果sizeof (short )的大小为2 (byte ),那么,S 的大小就为6 。取一个2 的次方值,使得该值大于等于6 ,则该值为8 ,所以编译器将设置S 类型的对齐方式为8 字节。ligned 属性使被设置的对象占用更多的空间,相反的,使用packed 可以减小对象占用的空间。需要注意的是,attribute 属性的效力与你的连接器也有关,如果你的连接器最大只支持16 字节对齐,那么你此时定义32 字节对齐也是无济于事的。2.packed使用该属性对struct 或者union 类型进行定义,设定其类型的每一个变量的内存约束。当用在enum 类型 定义时,暗示了应该使用最小完整的类型(it indicates that the smallest integral type should be used)。下面的例子中,packed_struct 类型的变量数组中的值将会紧紧的靠在一起,但内部的成员变量s 不会被“pack” ,如果希望内部的成员变量也被packed 的话,unpacked-struct 也需要使用packed 进行相应的约束。struct unpacked_struct { char c; int i; }; struct packed_struct { char c; int i; struct unpacked_struct s; }__attribute__ ((__packed__));下面的例子中使用\_\_attribute\_\_ 属性定义了一些结构体及其变量,并给出了输出结果和对结果的分析。struct p { int a; char b; short c; }__attribute__((aligned(4))) pp; struct m { char a; int b; short c; }__attribute__((aligned(4))) mm; struct o { int a; char b; short c; }oo; struct x { int a; char b; struct p px; short c; }__attribute__((aligned(8))) xx; int main() { printf("sizeof(int)=%d,sizeof(short)=%d.sizeof(char)=%d\n",sizeof(int),sizeof(short),sizeof(char)); printf("pp=%d,mm=%d \n", sizeof(pp),sizeof(mm)); printf("oo=%d,xx=%d \n", sizeof(oo),sizeof(xx)); return 0; }输出结 果:sizeof(int)=4,sizeof(short)=2.sizeof(char)=1pp=8,mm=12oo=8,xx=24分析:sizeof(pp):sizeof(a)+sizeof(b)+sizeof(c)=4+1+1=6\<8 所以sizeof(pp)=8sizeof(mm):sizeof(a)+sizeof(b)+sizeof(c)=1+4+2=7但是 a 后面需要用 3 个字节填充,但是 b 是 4 个字节,所以 a 占用 4 字节, b 占用 4 个字节,而 c 又要占用 4 个字节。所以 sizeof(mm)=12sizeof(oo):sizeof(a)+sizeof(b)+sizeof(c)=4+1+2=7因为默 认是以4 字节对齐,所以sizeof(oo)=8sizeof(xx):sizeof(a)+ sizeof(b)=4+1=5sizeof(pp)=8; 即xx 是采用8 字节对齐的,所以要在a ,b 后面添3 个空余字节,然后才能存储px ,4+1+ (3 )+8+1=17因为xx 采用的对齐是8 字节对齐,所以xx 的大小必定是8 的整数倍,即xx 的大小是一个比17 大又是8 的倍数的一个最小值,由此得到17\<24 ,所以sizeof(xx)=243.函数属性(Function Attribute)函数属性可以帮助开发者把一些特性添加到函数声明中,从而可以使编译器在错误检查方面的功能更强大。\_\_attribute\_\_机制也很容易同非GNU应用程序做到兼容之功效。GNU CC需要使用 –Wall编译器来击活该功能,这是控制警告信息的一个很好的方式。下面介绍几个常见的属性参数。\_\_attribute\_\_ format该\_\_attribute\_\_属性可以给被声明的函数加上类似printf或者scanf的特征,它可以使编译器检查函数声明和函数实际调用参数之间的格式化字符串是否匹配。该功能十分有用,尤其是处理一些很难发现的bug。format的语法格式为:format (archetype, string-index, first-to-check)format属性告诉编译器,按照printf, scanf, strftime或strfmon的参数表格式规则对该函数的参数进行检查。“archetype”指定是哪种风格;“string-index”指定传入函数的第几个参数是格式化字符串;“first-to-check”指定从函数的第几个参数开始按上述规则进行检查。具体使用格式如下:\_\_attribute\_\_((format(printf,m,n)))\_\_attribute\_\_((format(scanf,m,n)))其中参数m与n的含义为:m:第几个参数为格式化字符串(format string);n:参数集合中的第一个,即参数“…”里的第一个参数在函数参数总数排在第几,注意,有时函数参数里还有“隐身”的呢,后面会提到;在使用上,\_\_attribute\_\_((format(printf,m,n)))是常用的,而另一种却很少见到。下面举例说明,其中myprint为自己定义的一个带有可变参数的函数,其功能类似于printf://m=1;n=2 extern void myprint(const char *format,...) \_\_attribute\_\_((format(printf,1,2))); //m=2;n=3 extern void myprint(int l,const char *format,...) \_\_attribute\_\_((format(printf,2,3)));需要特别注意的是,如果myprint是一个函数的成员函数,那么m和n的值可有点“悬乎”了,例如://m=3;n=4 extern void myprint(int l,const char *format,...) \_\_attribute\_\_((format(printf,3,4)));其原因是,类成员函数的第一个参数实际上一个“隐身”的“this”指针。(有点C++基础的都知道点this指针,不知道你在这里还知道吗?)这里给出测试用例:attribute.c,代码如下:1: 2:extern void myprint(const char *format,...) __attribute__((format(printf,1,2))); 3: 4:void test() 5:{ 6: myprint("i=%d\n",6); 7: myprint("i=%s\n",6); 8: myprint("i=%s\n","abc"); 9: myprint("%s,%d,%d\n",1,2); 10:}运行$gcc –Wall –c attribute.c attribute后,输出结果为:attribute.c: In function 'test':attribute.c: 7: warning: format argument is not a pointer (arg 2)attribute.c: 9: warning: format argument is not a pointer (arg 2)attribute.c: 9: warning: too few arguments for format如果在attribute.c中的函数声明去掉\_\_attribute\_\_((format(printf,1,2))),再重新编译,既运行$gcc –Wall –c attribute.c attribute后,则并不会输出任何警告信息。注意,默认情况下,编译器是能识别类似printf的“标准”库函数。\_\_attribute\_\_ noreturn该属性通知编译器函数从不返回值,当遇到类似函数需要返回值而却不可能运行到返回值处就已经退出来的情况,该属性可以避免出现错误信息。C库函数中的abort()和exit()的声明格式就采用了这种格式,如下所示:extern void exit(int) \_\_attribute\_\_((noreturn));extern void abort(void) \_\_attribute\_\_((noreturn)); 为了方便理解,大家可以参考如下的例子://name: noreturn.c ;测试__attribute__((noreturn)) extern void myexit(); int test(int n) { if ( n > 0 ) { myexit(); /* 程序不可能到达这里*/ } else return 0; }编译显示的输出信息为:gcc –Wall –c noreturn.cnoreturn.c: In function 'test':noreturn.c: 12: warning: control reaches end of non-void function警告信息也很好理解,因为你定义了一个有返回值的函数test却有可能没有返回值,程序当然不知道怎么办了!加上\_\_attribute\_\_((noreturn))则可以很好的处理类似这种问题。把extern void myexit();修改为:extern void myexit() \_\_attribute\_\_((noreturn));之后,编译不会再出现警告信息。\_\_attribute\_\_ const该属性只能用于带有数值类型参数的函数上。当重复调用带有数值参数的函数时,由于返回值是相同的,所以此时编译器可以进行优化处理,除第一次需要运算外, 其它只需要返回第一次的结果就可以了,进而可以提高效率。该属性主要适用于没有静态状态(static state)和副作用的一些函数,并且返回值仅仅依赖输入的参数。为了说明问题,下面举个非常“糟糕”的例子,该例子将重复调用一个带有相同参数值的函数,具体如下:extern int square(int n) __attribute__ ((const)); ... for (i = 0; i < 100; i++ ) { total += square (5) + i; }通过添加\_\_attribute\_\_((const))声明,编译器只调用了函数一次,以后只是直接得到了相同的一个返回值。事实上,const参数不能用在带有指针类型参数的函数中,因为该属性不但影响函数的参数值,同样也影响到了参数指向的数据,它可能会对代码本身产生严重甚至是不可恢复的严重后果。并且,带有该属性的函数不能有任何副作用或者是静态的状态,所以,类似getchar()或time()的函数是不适合使用该属性的。关于linux内核中的"\_\_attribute\_\_ ((packed))"引用:\_\_attribute\_\_ ((packed)) 的作用就是告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐。#define __u8 unsigned char #define __u16 unsigned short /* __attribute__ ((packed)) 的位置约束是放于声明的尾部“;”之前 */ struct str_struct{ __u8 a; __u8 b; __u8 c; __u16 d; } __attribute__ ((packed)); /* 当用到typedef时,要特别注意__attribute__ ((packed))放置的位置,相当于: * typedef struct str_stuct str; * 而struct str_struct 就是上面的那个结构。 */ typedef struct { __u8 a; __u8 b; __u8 c; __u16 d; } __attribute__ ((packed)) str; /* 在下面这个typedef结构中,__attribute__ ((packed))放在结构名str_temp之后,其作用是被忽略的,注意与结构str的区别。*/ typedef struct { __u8 a; __u8 b; __u8 c; __u16 d; }str_temp __attribute__ ((packed)); typedef struct { __u8 a; __u8 b; __u8 c; __u16 d; }str_nopacked; int main(void) { printf("sizeof str = %d\n", sizeof(str)); printf("sizeof str_struct = %d\n", sizeof(struct str_struct)); printf("sizeof str_temp = %d\n", sizeof(str_temp)); printf("sizeof str_nopacked = %d\n", sizeof(str_nopacked)); return 0; }编译运行:引用:[root@localhost root]# ./packedtest sizeof str = 5sizeof str_struct = 5sizeof str_temp = 6sizeof str_nopacked = 6packed属性:使用该属性可以使得变量或者结构体成员使用最小的对齐方式,即对变量是一字节对齐,对域(field)是位对齐。4.at绝对定位,可以把变量或函数绝对定位到Flash中,或者定位到RAM。1)、定位到flash中,一般用于固化的信息,如出厂设置的参数,上位机配置的参数,ID卡的ID号,flash标记等等const u16 gFlashDefValue[512] __attribute__((at(0x0800F000))) = {0x1111,0x1111,0x1111,0x0111,0x0111,0x0111};//定位在flash中,其他flash补充为00 const u16 gflashdata__attribute__((at(0x0800F000))) = 0xFFFF;2)、定位到RAM中,一般用于数据量比较大的缓存,如串口的接收缓存,再就是某个位置的特定变量u8 USART2_RX_BUF[USART2_REC_LEN] __attribute__ ((at(0X20001000)));//接收缓冲,最大USART_REC_LEN个字节,起始地址为0X20001000.注意:1)、绝对定位不能在函数中定义,局部变量是定义在栈区的,栈区由MDK自动分配、释放,不能定义为绝对地址,只能放在函数外定义。2)、定义的长度不能超过栈或Flash的大小,否则,造成栈、Flash溢出。5.section提到section,就得说RO RI ZI了,在ARM编译器编译之后,代码被划分为不同的段,RO Section(ReadOnly)中存放代码段和常量,RW Section(ReadWrite)中存放可读写静态变量和全局变量,ZI Section(ZeroInit)是存放在RW段中初始化为0的变量。于是本文的大体意思就清晰了,\_\_attribute\_\_((section("section_name"))),其作用是将作用的函数或数据放入指定名为"section_name"对应的段中。1)、编译时为变量指定段:__attribute__((section("name"))) RealView Compilation Tools for µVision Compiler Reference Guide Version 4.0 Home > Compiler-specific Features > Variable attributes > __attribute__((section("name"))) 4.5.6. __attribute__((section("name"))) Normally, the ARM compiler places the objects it generates in sections like data and bss. However, you might require additional data sections or you might want a variable to appear in a special section, for example, to map to special hardware. The section attribute specifies that a variable must be placed in a particular data section. If you use the section attribute, read-only variables are placed in RO data sections, read-write variables are placed in RW data sections unless you use the zero_init attribute. In this case, the variable is placed in a ZI section. Note This variable attribute is a GNU compiler extension supported by the ARM compiler. Example /* in RO section */ const int descriptor[3] __attribute__ ((section ("descr"))) = { 1,2,3 }; /* in RW section */ long long rw[10] __attribute__ ((section ("RW"))); /* in ZI section * long long altstack[10] __attribute__ ((section ("STACK"), zero_init));/2)、编译时为函数指定段__attribute__((section("name"))) RealView Compilation Tools for µVision Compiler Reference Guide Version 4.0 Home > Compiler-specific Features > Function attributes > __attribute__((section("name"))) 4.3.13. __attribute__((section("name"))) The section function attribute enables you to place code in different sections of the image. Note This function attribute is a GNU compiler extension that is supported by the ARM compiler. Example In the following example, Function_Attributes_section_0 is placed into the RO section new_section rather than .text. void Function_Attributes_section_0 (void) __attribute__ ((section ("new_section"))); void Function_Attributes_section_0 (void) { static int aStatic =0; aStatic++; } In the following example, section function attribute overrides the #pragma arm section setting. #pragma arm section code="foo" int f2() { return 1; } // into the 'foo' area __attribute__ ((section ("bar"))) int f3() { return 1; } // into the 'bar' area int f4() { return 1; } // into the 'foo' area #pragma arm section6.多个属性组合使用u8 FileAddr[100] __attribute__ ((section ("FILE_RAM"), zero_init,aligned(4)));
2020年09月15日
3,165 阅读
0 评论
0 点赞