做Linux驱动开发经常要使用到内核相关的函数,本篇只要介绍在做驱动开发的过程中用到的内核函数,为以后开发查询提供方便。
本篇覆盖函数如下
1. copy_from_user与copy_to_user函数
copy_from_user:从用户空间拷贝数据到内核空间,失败返回没有被拷贝的字节数,成功返回0,其函数原型如下:
static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n)
{
unsigned long res = n;
kasan_check_write(to, n);
if (access_ok(VERIFY_READ, from, n)) {
check_object_size(to, n, false);
res = __arch_copy_from_user(to, from, n);
}
if (unlikely(res))
memset(to + (n - res), 0, res);
return res;
}
copy_to_user:从内核空间拷贝数据到用户空间,失败返回没有被拷贝的字节数,成功返回0,其函数原型如下:
static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n)
{
kasan_check_read(from, n); // 与copy_from_user一致,先检查内核空间地址的合法性
if (access_ok(VERIFY_WRITE, to, n)) {
check_object_size(from, n, true);
n = __arch_copy_to_user(to, from, n);
}
return n;
}
2. down_interruptible与down函数
down_interruptible函数原型如下:
int down_interruptible(struct semaphore *sem)
该函数的功能就是获得信号量,如果得不到信号量就睡眠,此时没有信号打断,那么进入睡眠。但是在睡眠过程中可能被信号打断,打断之后返回-EINTR,主要用来进程间的互斥同步。
一个进程在调用down_interruptible()之后,如果sem<0,那么就进入到可中断的睡眠状态并调度其它进程运行, 但是一旦该进程收到信号,那么就会从down_interruptible函数中返回。并标记错误号为:-EINTR。一个形象的比喻:小强下午放学回家,回家了就要开始吃饭嘛,这时就会有两种情况:情况一:饭做好了,可以开始吃;情况二:当他到厨房去的时候发现妈妈还在做,妈妈就对他说:“你先去睡会,待会做好了你。”小强就答应去睡会,不过又说了一句:“睡的这段时间要是小红来找我玩,你可以叫醒我。”小强就是down_interruptible,想吃饭就是获取信号量,睡觉对应这里的休眠,而小红来找我玩就是中断休眠。
使用可被中断的信号量版本的意思是,万一出现了semaphore的死锁,还有机会用ctrl+c发出软中断,让等待这个内核驱动返回的用户态进程退出,而不是把整个系统都锁住了。
down函数原型如下:
void down(struct semaphore * sem)
down操作,跟down_interruptible类似,先去获取信号量,如果信号量被占用,先把该进程加入到等待队列。然后查询当前进程是否有信号(软中断)要去处理,如果有的话会返回–EINTR退出;如果没有的话,当前进程进入不可被信号(软中断)唤醒的睡眠,也就是睡眠过程中不响应信号(软中断),直到获取到信号量(flag)退出睡眠,即被 up操作 从等待队列上唤醒。
扩展其他类似函数:
//睡眠的进程能够由于受到致命信号而被唤醒,中断获取信号量的操作
int down_killable(struct semaphore *sem);
//试图获取信号量,若无法获得则直接返回1而不睡眠;返回0则 表示获取到了信号量
int down_trylock(struct semaphore *sem);
//表示睡眠时间是有限制的。假设在jiffies指明的时间到期时仍然无法获得信号量,则将返回错误码
int down_timeout(struct semaphore *sem,long jiffies)
//释放内核信号量锁
void up(struct semaphore *sem)
3. writeX与readX宏函数
writeb(), writew(), writel() 宏函数,其功能往内存映射的 I/O 空间上写数据:
#include
void writeb (unsigned char data , unsigned short addr )
void writew (unsigned char data , unsigned short addr )
void writel (unsigned char data , unsigned short addr )
readb(), readw(), readl() 宏函数,其功能从内存映射的 I/O 空间读取数据:
函数原型如下:
unsigned char readb (unsigned int addr )
unsigned char readw (unsigned int addr )
unsigned char readl (unsigned int addr )