Linux内核开发常见的函数

做Linux驱动开发经常要使用到内核相关的函数,本篇只要介绍在做驱动开发的过程中用到的内核函数,为以后开发查询提供方便。

本篇覆盖函数如下

copy_from_user与copy_to_user函数
down_interruptible与down函数
writeX与readX宏函数

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 空间上写数据:

  • writeb() I/O 上写入 8 位数据 (1字节)
  • writew() I/O 上写入 16 位数据 (2字节)
  • wirtel() I/O 上写入 32 位数据 (4字节)
    函数原型如下:
#include <asm/io.h> 

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 空间读取数据:

  • readb 从 I/O 读取 8 位数据 ( 1 字节 )
  • readw 从 I/O 读取 16 位数据 ( 2 字节 )
  • readl 从 I/O 读取 32 位数据 ( 4 字节 )

函数原型如下:

unsigned char readb (unsigned int addr )
unsigned char readw (unsigned int addr )
unsigned char readl (unsigned int addr )
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值