Linux驱动——用户空间读取内核空间的数据

个人声明:转发请注明出处,个人原创,实属不易。本人水平有限,文章若有不妥之处,还请留言批评指正,不胜感激。
本文参考博客并做了一些延伸。

前言

(废话再说一遍)Linux系统下一切皆文件,所以我们对外围设备的操作也就是对Linux系统中/dev/下设备文件的open、read、write和close。但是,为什么操作这些文件的open、read、write和close就可以对外围设备进行操作呢???

  1. 用户空间与内核空间的通信
    本文主要介绍copy_to_user和copy_from_user,这两种通信方式都是单工的,copy_to_user只能从内核空间发送数据到用户空间,而copy_from_user只能从用户空间发送数据到内核空间。

  2. 用户空间的open、read、write和close与内核驱动中files_operations结构体内的操作集的关系
    用户空间对/dev/下文件进行open、read、write和close操作,就会调用内核驱动中files_operations结构体里面对应的open、read、write和release函数接口。

  3. 测试代码
    内核驱动files_operations结构体的操作集函数

static int ap3216c_open(struct inode *nd, struct file *filp)
{
	int ret = 0;
	unsigned char val=0;
	filp->private_data = &ap3216cdev;
	printk("%s:%s %d \r\n",__FILE__,__func__,__LINE__);
	/* 初始化AP3216C */
	ap3216c_write_reg(&ap3216cdev,AP3216C_SYSTEMCONG,0x4);	/* 复位 */
	mdelay(50);
	ap3216c_write_reg(&ap3216cdev,AP3216C_SYSTEMCONG,0x3);	/* 复位 */

	val = ap3216c_read_reg(&ap3216cdev,AP3216C_SYSTEMCONG);
	printk("AP3216C_SYSTEMCONG reg = %#x\r\n",val);
	return ret;
}
static int aps216c_release(struct inode *nd, struct file *filp)
{
	int ret = 0;
	printk("%s:%s %d \r\n",__FILE__,__func__,__LINE__);
	return ret;
}
/* fpos */
static struct file_operations ap3216c_fops = {
	.owner = THIS_MODULE,
	.open = ap3216c_open,
	.read = ap3216c_read,
	.write = ap3216c_write,
	.release = aps216c_release,
};

用户空间的APP测试程序(部分)

/* open ap3216c driver */
fd = open(filename,O_RDWR);
printf("ap3216c is open!\r\n");
if(fd<0)
{
    printf("file %s open failed!\r\n",filename);
    return -1;
}

while(i<5)
{
    ret = read(fd,data,sizeof(data));
    if(ret==0)
    {
        ir = data[0];
        ps = data[1];
        als = data[2];
        printf("AP3216C ir = %d, ps = %d, als = %d\r\n",ir,ps,als);
    }
    usleep(2000000);     /* 2000ms */
    i++;
}
printf("ap3216c read!\r\n");
if(ret<0)
{
    printf("read data  failed!\r\n");
    close(fd);
    return -1;
}

ret = close(fd); /* close file */
if(fd<0)
{
    printf("file %s close failed!\r\n",filename);
    return -1;
}
printf("ap3216c is closed!\r\n");

在这里插入图片描述
4. 测试结果

/home/***/Linux/IMX6ULL/linux_drivers/7_i2c/ap3216c.c:ap3216c_open 154
AP3216C_SYSTEMCONG reg = 0x3
ap3216c is open!
/home/***/Linux/IMX6ULL/linux_drivers/7_i2c/ap3216c.c:ap3216c_read 140
AP3216C ir = 0, ps = 0, als = 0
/home/***/Linux/IMX6ULL/linux_drivers/7_i2c/ap3216c.c:ap3216c_read 140
AP3216C ir = 11, ps = 161, als = 177
/home/***/Linux/IMX6ULL/linux_drivers/7_i2c/ap3216c.c:ap3216c_read 140
AP3216C ir = 35, ps = 159, als = 181
/home/***/Linux/IMX6ULL/linux_drivers/7_i2c/ap3216c.c:ap3216c_read 140
AP3216C ir = 0, ps = 158, als = 181
/home/***/Linux/IMX6ULL/linux_drivers/7_i2c/ap3216c.c:ap3216c_read 140
AP3216C ir = 18, ps = 138, als = 187
/home/***/Linux/IMX6ULL/linux_drivers/7_i2c/ap3216c.c:aps216c_release 167
ap3216c is closed!

总结

用户空间read读取一次ap3216c的数据,就会内核驱动中file_operations结构体里面的read函数接口,所以终端先打印输出printk语句,最终内核驱动把获取到的数据通过copy_to_user发送给用户空间,至此用户空间就完成了对外围设备数据的读取操作。同样地,当应用层调用open函数、write函数和close函数都会调用内核ap3216c驱动中file_operations结构体对应的open函数、write函数和release函数。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值