字符设备(1)读写

/*
struct cdev {
	struct kobject kobj;
	struct module *owner; //一般初始化为THIS_MODULE
	const struct file_operations *ops; //文件操作结构体
	struct list_head list;
	dev_t dev; //设备号
	unsigned int count; //添加的设备个数
};
*/
/*
简单的内核内存读写,不关联设备
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>

#include <linux/cdev.h>  //for cdev 
#include <linux/fs.h> //for open..

#include <asm/uaccess.h> //for copy_from_user ...
#include <linux/errno.h>  //for -EFAULT

#define P_DEBUG(fmt, args...) printk("<kernel>[%s]"fmt, __FUNCTION__, ##args)

static dev_t devno; //设备号
static int major = 0; //主
static int minor = 0; //次

struct cdev test_cdev; //设备

//设备驱动的操作方法
static int test_open(struct inode *,struct file *);
static int test_close(struct inode *,struct file *);
static ssize_t test_read(struct file *, char __user *, size_t , loff_t *);
static ssize_t test_write(struct file *, const char __user *, size_t, loff_t *);

struct file_operations test_fops = {
	.open = test_open,
	.release = test_close,
	.read = test_read,
	.write = test_write,
};
//打开设备
static int test_open(struct inode *inode,struct file *filp)
{
	P_DEBUG("dev open!\n");	
	return 0;
}
//释放设备
static int test_close(struct inode *inode,struct file *filp)
{
	P_DEBUG("dev close!\n");
	return 0;
}
//从设备读取
static ssize_t test_read(struct file *filp, char __user *buf, size_t count, loff_t *offset)
{
	int ret;
	//在这里先不从设备读取,只是从内核复制"test"到用户态buf
	if (copy_to_user(buf,"test",count)) {//安全性检查
		return -EFAULT;
	}
	else {
		ret = count;
		P_DEBUG("buf is [%s]\n", buf);
	}
	return ret; 
} 

//写入设备
static ssize_t test_write(struct file *filp, const char __user *buf, size_t count, loff_t *offset)
{
	int ret;
	char kbuf[10] = {0};
 	//在这里先不写到设备,只是从用户态读取数据到内核kbuf
	if (copy_from_user(kbuf,buf,count)) {
		return -EFAULT;
	}
	else {
		ret = count;	
 		P_DEBUG("kbuf is [%s]\n", kbuf); 
	}
 	return ret;
 }

static int __init test_init(void)
{
	int ret;
	//1.申请字符设备号
	if (major) {
		devno = MKDEV(major,minor);
		ret = register_chrdev_region(devno,1,"test_dev");
	}
	else {//动态分配
		ret = alloc_chrdev_region(&devno,minor,1,"test_dev");
		major = MAJOR(devno);
		minor = MINOR(devno);
	}	
	
	if (ret < 0) {
		P_DEBUG("register chrdev devno err!\n");
		goto err_regDevno;
	}
	
	printk("major[%d] minor[%d]\n",major,minor);

	//2.注册设备到字符设备数据库并初始化
	cdev_init(&test_cdev,&test_fops);//初始化cdev结构体
	test_cdev.owner = THIS_MODULE;
	ret = cdev_add(&test_cdev,devno,1);//将设备加到字符设备数据库

	if (ret < 0) {
		P_DEBUG("add cdev error!\n");
		goto err_addCdev;
	}
	
	return 0;
err_addCdev:
	unregister_chrdev_region(devno,1);	
err_regDevno:
	return ret;
}

static int __exit test_exit(void)
{
	cdev_del(&test_cdev);//3.从字符设备数据库删除cdev
	unregister_chrdev_region(devno,1);//4.释放设备号

	return 0;
}

module_init(test_init);
module_exit(test_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("LL");
MODULE_VERSION("1.1");

测试

#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>

int main(void)
{
	int fd,num;
        char *buf  = "test_date"; //测试数据
	char buff[10];
	
	fd = open("/dev/test",O_RDWR);//打开文件
	if (fd < 0) {
		perror("open");
		return -1;
	}
	
	//read(fd, buff, 5);//第一次从设备读
	//printf("<app>[%s]\n", buff);
	write(fd, buf, 8);//写到设备 
	//重置偏移量
	lseek(fd,0,SEEK_SET);
	read(fd, buff, 5);//再次从设备读 
	printf("<app>[%s]\n", buff);

	close(fd);		
	return 0;
}

结果




http://blog.csdn.net/blue0432/article/details/7882451


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值