目录
一.Address_space
二.Dup系统调用
三.Proc应用
一.Address_space
内核空间到用户空间
__user 这个特性,即__attribute__((noderef, address_space(1))),是用来修饰一个变量的,这个变量必须是非解除参考(__attribute__((noderef))——no dereference)的,即这个变量地址必须是有效的,而且变量所在的地址空间必须是1(__attribute__((address_space(1)))),即用户程序空间的。这里Sparse工具把程序空间分成了3个部分,0表示normal space,即普通地址空间,对内核代码来说,当然就是内核空间地址了。1表示用户地址空间,这个不用多讲,还有一个2,表示是设备地址映射空间,例如硬件设备的寄存器在内核里所映射的地址空间。
# define __kernel /* default address space */
根据定义,就是检查是否处于内核空间。其为默认的地址空间,即0,我想定义成__attribute__((noderef, address_space(0)))也是没有问题的。
# define __user __attribute__((noderef, address_space(1)))
调用Copy_to_user copy_from_user 需要添加__user的原因就是将用户空间上的数据拷贝到内核空间上
# define __iomem __attribute__((noderef, address_space(2)))
写过内核驱动的都一定用过ioremap,事实上也与设备地址映射空间有关。
static inline void __iomem *ioremap(phys_addr_t offset, unsigned long size)
{
return (void __iomem*) (unsigned long)offset;
}
在进行映射时,就是将物理地址对应到IO内存地址,这样就能直接操作IO内存地址,
从而操作对应的寄存器。
比如__raw_writel,__raw_readl 就是将数据读写到对应的IO内存地址上,例如
static inline void __raw_writel(u32 b, volatile void __iomem *addr)
{
*(volatile u32 __force *) addr = b;
}
在简略说说其他的定义
__safe特性声明该变量为安全变量,这是为了避免在内核函数未对传入的参数进行校验就使用的情况下,会导致编译器对其报错或输出告警信息。 通过该特性说明该变量不可能为空。
__force特性声明该变量是可以强制类型转换的。
__nocast声明该变量参数类型与实际参数类型要一致才可以。
__acquires为函数属性定义的修饰,表示函数内,该参数的引用计数值从1变为0。
__releases与__acquires相反,这一对修饰符用于Sparse在静态代码检测时,检查调用的次数和匹配请求,经常用于检测lock的获取和释放。
__acquire表示增加变量x的计数,增加量为1。
__release表示减少变量x的计数,减少量为1。这一对与上面的那一对是一样,只是这一对用在函数的执行过程中,都用于检查代码中出现不平衡的状况。
__cond_lock用于表示条件锁,当c这个值不为0时,计数值加1,并返回1。
__chk_user_ptr和__chk_io_ptr在这里只声明函数,没有函数体,目的就是在编译过程中Sparse能够捕捉到编译错误,检查参数的类型。
二.Dup系统调用
在fcntl.c中有dup2,事实上,许多函数的系统调用都在include/asm-generic/unistd.h中有对应的编号.
Dup2用于文件流的重定向操作,
SYSCALL_DEFINE2(dup2, unsigned int, oldfd, unsigned int, newfd)
{
Return sys_dup3;
}
实际上调用的是dup3,即
SYSCALL_DEFINE3(dup3, unsigned int, oldfd, unsigned int, newfd, int, flags)
而sys_dup3的主要操作就是根据fdtable将当前进程的所指向的fdtable进行expand操作。对于文件的结构不太清晰,待进一步的学习。
三. Proc应用
对于proc文件系统,一直没有用到,写驱动时用的都是sys,前段时间看了input子系统下proc的创建,随意记录一些。
创建proc目录,proc_mkdir
struct proc_dir_entry *proc_bus_input_dir;
proc_bus_input_dir=proc_mkdir(”/bus/input”,NULL); //文件操作方法为NULL
创建proc目录下的文件 proc_create
Proc_create(“devices”,0,proc_bus_input_dir,&input_device_fileops);
//proc_bus_input_dir为创建的文件所在的目录,“device”为proc文件名字,input_device_fileops为操作该文件的相应方法。文件相关的操作方法就不提了,具体的可以看input目录下input.c文件
删除文件和目录
Remove_proc_entry(“device”,proc_bus_input_dir);
Remove_proc_entry(“bus/input”,NULL);