linux驱动16:read和write

概述:

一、

ssize_t (*read) (struct file *filp, char __user *buff, size_t count, loff_t *offp);
ssize_t (*write) (struct file *filp, const char __user *buff, size_t count, loff_t *offp);

read:拷贝数据到应用程序空间

write:从应用程序空间拷贝数据

read和write方法的buff参数为用户空间的指针

二、

unsigned long copy_to_user(void __user *to, const void *from, unsigned long n);
unsigned long copy_from_user(void *to, const void __user *from, unsigned long n);

定义在#include <linux/uaccess.h>
copy_to_user:拷贝数据到应用程序空间 

copy_from_user:从应用程序空间拷贝数据

这两个函数的作用并不限于在内核空间和用户空间之间拷贝数据,还检查用户空间的指针是否有效。如果指针无效,就不会进行拷贝;如果在拷贝过程中遇到无效地址,则仅仅复制部分数据,返回值为还需要拷贝的内存数量值。出错通常返回-EFAULT。

如果并不需要检查用户空间指针,可以调用:__copy_to_user、__copy_from_user

三、

图1 read使用参数

read和write出错返回负值,错误码定义在<linux/errno.h>中定义,如:-EINTR(系统调用被中断)、-EFAULT(无效地址)等等。

 例程:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>

#define MAX_BUF_LEN 256

static int major = 277;
static int minor = 0;
static dev_t devnum1;
static struct cdev cdev1;
static char helloBuf[MAX_BUF_LEN];

int hello_open(struct inode *pinode, struct file *pfile)
{
	printk("hello_open, minor:%d, major:%d\n", iminor(pinode), imajor(pinode));
	return 0;
}

int hello_release(struct inode *pinode, struct file *pfile)
{
	printk("hello_release, minor:%d, major:%d\n", iminor(pinode), imajor(pinode));	
	return 0;
}

ssize_t hello_read(struct file *filep, char __user *buf, size_t size, loff_t *pos)
{
	int copySize;

	if (size > MAX_BUF_LEN)
	{
		copySize = MAX_BUF_LEN;
	}
	else
	{
		copySize = size;
	}

	memcpy(helloBuf, "hello", 5);
	if(copy_to_user(buf, helloBuf, copySize))
	{
		return -EFAULT;
	}

	return copySize;
}

ssize_t hello_write(struct file *filep, const char __user *buf, size_t size, loff_t *pos)
{
	int copySize;

	if(size > MAX_BUF_LEN)
	{
		copySize = MAX_BUF_LEN;
	}
	else
	{
		copySize = size;
	}
	
	memset(helloBuf, 0, MAX_BUF_LEN);
	if(copy_from_user(helloBuf, buf, copySize))
	{
		return -EFAULT;
	}
	
	printk("%s\n",helloBuf);
	return copySize;
}

static struct file_operations hello_ops = {
	.open = hello_open,
	.release = hello_release,
	.read = hello_read,
	.write = hello_write,
};

static int hello_init(void)
{
	printk("hello_init\n");
	devnum1 = MKDEV(major,minor);
	printk("major:%d, minor:%d\n", MAJOR(devnum1), MINOR(devnum1));
	if (register_chrdev_region(devnum1, 1, "hello1"))//分配设备号
	{
		printk("register_chrdev_region failed\n");
		return -1;
	}

	cdev_init(&cdev1, &hello_ops);//初始化cdev,绑定fops
	if (cdev_add(&cdev1, devnum1, 1) < 0)//添加设备到内核
	{
		printk("cdev_add failed\n");
		unregister_chrdev_region(devnum1, 1);
		return -1;
	}

	return 0;
}

static void hello_exit(void)
{
	printk("hello_exit\n");
	cdev_del(&cdev1);
	unregister_chrdev_region(devnum1, 1);
}

MODULE_LICENSE("GPL");
module_init(hello_init);
module_exit(hello_exit);

mknod /dev/hello0 c 277 0

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char * argv [ ])
{
	int fd = open("/dev/hello0", O_RDWR, 666);
	if (fd < 0)
	{
		perror("open faied");
		return -1;
	}

	printf("open successed: %d\n", fd);

	char readBuf[256] = {0};
	read(fd, readBuf, sizeof(readBuf));
	printf("buf:%s\n", readBuf);

	char writeBuf[] = "halo";
	write(fd, writeBuf, strlen(writeBuf));
	
	sleep(2);
	close(fd);
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值