1、__FILE__ __FUNCTION__ __LINE__
他们是C语言中非常有用的全局变量,用于代码定位。
__FILE__代码当前所在的文件名。字符串
__FUNCTION__:当前所处的函数名。字符串
__LINE__当前所处的 行号。整型
实验:
结果:
2、%p
用法:
char * ptr;
printf("%p",ptr);
用于显示指针的地址。当程序所处的cpu位数16、32、64位时,可以统一使用该语句显示指针的地址,不受长度的影响。
3、snprintf sprintf
void f(const char *p)
{
char buf[11]={0};
sprintf(buf,"%10s",p); // very dangerous
printf("%sn",buf);
}
这里使用sprintf会导致缓冲区溢出,不安全(%10s,10个长度也是没用的)。应该使用安全的snprintf或sprintf_s(微软建议)代替。
4、GFP_KERNEL
在linux/gfp.h中定义的一个宏,是分配内核空间的内存时的一个标志位。
这个标志位分配内存的一个选项,GFP_KERNEL是内核内存分配时最常用的,无内存可用时可引起休眠。
5、assert函数 :assert(expression);
assert断言,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行。
缺点:
1)频繁的调用会极大的影响程序的性能,增加额外的开销。
2)同时检验多个条件时,如果断言失败,无法直观的判断是哪个条件失败。
6、perror函数
#include <stdio.h> // void perror(const char *msg);
#include <string.h> // char *strerror(int errnum);
#include <errno.h> //errno
errno是错误代码,在errno.h头文件中
void perror(const char *s)
perror是错误输出函数,在标准输出设备上输出一个错误信息。参数s一般是参数错误的函数
例如perror("fun"),其输出为:fun:后面跟着错误信息(加上一个换行符)
char *strerror(int errnum); 通过参数errnum(也就是errno),返回错误信息
结果:
7、.mk文件
.mk文件是makefile文件,通过include包含到Makefile文件当中!
8、中断同步机制
spin_lock和spin_unlock: spin_lock用于阻止在不同CPU上的执行单元对共享资源的同时访问以及不同进程上下文互相抢占导致的对共享资源的非同步访问,如果只有一个中断处理句柄访问该共享资源,那么在中断处理句柄中仅需要来保护对共享资源的访问就可以了。 如果被保护的共享资源只在一个软中断(tasklet和timer除外)上下文访问,那么这个共享资源需要用spin_lock和spin_unlock来保护,因为同样的软中断可以同时在不同的CPU上运行。
spin_lock_irq和spin_unlock_irq:获锁成功,失效了本地硬中断,失效硬中断隐式地也失效了软中断。执行完毕后,开启中断。因为在执行中断处理句柄期间,不可能被同一CPU上的软中断或进程打断。但是如果有不同的中断处理句柄访问该共享资源,那么需要在中断处理句柄中使用它们,来保护对共享资源的访问。
在使用spin_lock_irq和spin_unlock_irq的情况下,完全可以用spin_lock_irqsave和spin_unlock_irqrestore取代。
如果可以确信在对共享资源访问前中断是使能的,那么使用spin_lock_irq更好一些。 spin_lock_irqsave需要保存标志寄存器flag。spin_lock_irqsave(lock,flag);
spin_lock_irq(lock);
如果你不能确定是否中断使能,那么使用spin_lock_irqsave和spin_unlock_irqrestore更好,因为它将恢复访问共享资源前的中断标志而不是直接使能中断。
spin_lock_irqsave和spin_unlock_irqrestore: 获锁成功,失效了本地硬中断,失效硬中断隐式地也失效了软中断。执行完毕后,恢复访问共享资源前的中断标志。
当然,有些情况下需要在访问共享资源时必须中断失效,而访问完后必须中断使能,这样的情形使用spin_lock_irq和spin_unlock_irq最好。
spin_lock_bh和spin_unlock_bh: 适用于当在进程上下文访问共享资源时,可能被软中断打断,从而可能进入软中断上下文来对被保护的共享资源访问。
只失效本地软中断。对共享资源的访问必须使用它。 比spin_lock_irq和spin_unlock_irq、spin_lock_irqsave和spin_unlock_irqrestore都快。
需要特别提醒读者,,而中断失效和软中断失效却是为了阻止在同一CPU上软中断或中断对共享资源的非同步访问。
9有static的结构体
struct S4{
char a;
long b;
static long c; //静态
};
结构体的sizeof一定要考虑字节对齐的问题。
静态变量存放在全局数据区内,而sizeof计算栈中分配的空间的大小,故不计算在内,S4的大小为4+4=8。
sizeof计算字符串大小时,包括'\0'
strlen计算字符串大小时,不包括'\0'
如:char a[]="123"
sizeof(a)=4 strlen=3
char a[10]="123"
sizeof(a)=10 strlen=3
10、、#pragma pack
· 使用伪指令#pragma pack (n),C编译器将按照n个字节对齐。
· 使用伪指令#pragma pack (),取消自定义字节对齐方式。
#pragma pack(8)
struct s1{
short a;
long b;
};
struct s2{
char c;
struct s1 d;
long long e;
};
#pragma pack()
问
1.sizeof(s2) = ?
答案: 24
11、换行符(\n) 与 回车符(\r)
换行(\n)就是光标下移一行却不会移到这一行的开头;
回车(\r)就是回到当前行的开头却不向下移一行.
12. 函数指针调用的形式
结果:
结果可以看出b(2);和(*b)(2);这两种形式都可以对函数指针进行调用。
13. __setup的用途
(kernel\include\linux\init.h)
struct obs_kernel_param {
const char *str;
int (*setup_func)(char *);
int early;
};
#define __setup_param(str, unique_id, fn, early) \
static const char __setup_str_##unique_id[] __initconst \
__aligned(1) = str; \
static struct obs_kernel_param __setup_##unique_id \
__used __section(.init.setup) \
__attribute__((aligned((sizeof(long))))) \
= { __setup_str_##unique_id, fn, early }
#define __setup(str, fn) \
__setup_param(str, fn, fn, 0)
/* NOTE: fn is as per module_param, not __setup! Emits warning if fn
* returns non-zero. */
#define early_param(str, fn) \
__setup_param(str, fn, fn, 1)
可以看出,__setup的功能就是给一个obs_kernel_param结构赋值,obs_kernel_param结构是第一个成员域为字符串,第二个成员域为函数指针,参数通过第一个成员传递。第三个成员变量表示是否是early_param。
__setup用于在内核启动时将对应str的内核参数传递到__setup中的函数中,从而完成相应的功能。checksetup完成上述过程。例如,__setup("console=",console_setup);比较"console="字符串后,将内核启动项中=后面的部分赋值给console_setup完成console的配置。
static int __init checksetup(char *line)
{
struct kernel_param *p;
p = &__setup_start;
do {
int n = strlen(p->str);
if (!strncmp(line,p->str,n)) {
if (p->setup_func(line+n))
return 1;
}
p++;
} while (p < &__setup_end);
return 0;
}
在较新的内核中,checksetup函数已经不用,现在使用obsolete_checksetup。
early_parm 和__setup宏近相差一个标志位。