MY_FIRSH_MODULE

模块描述

将30个字节的内存空间模仿成设备文件。每次读写不超过30个字节。

模块加载成功之后,需建立设备文件

mknod /dev/mydev c 231 0

模块代码

#include <linux/types.h>     //dev_t,MAJOR,MINOR,MKDEV
#include <linux/fs.h>        //file_operations,struct file,struct indoe,register
                //unregister_chrdev,register/alloc/unregister_chrdev_regino,
#include <linux/cdev.h>      //cdev_alloc,cdev_init,cdev_add,cdev_del
#include <linux/kernel.h>    //container_of
#include <linux/slab.h>      //kfree,kmalloc
#include <linux/errno.h>     //error code 
#include <linux/module.h>    //MODULE_LICENSE,...
#include <linux/platform_device.h>    //struct platform_device,struct platform_driver
#include <asm/uaccess.h>     //copy_from_user,copy_to_user

#define MYMAJOR 231        //静态分配设备号

MODULE_LICENSE("GPL");
MODULE_AUTHOR("WGY");
MODULE_DESCRIPTION("MY_FIRST_MODULE");


unsigned int count=0;   //记录打开设备的次数
dev_t devn;             //设备号

struct my_cdev
{
	char kerbuf[30];  //分配30个字节的内存空间
	struct cdev  cd;  //如果这里实例化cd为指针,记得使用前为cd分配空间
};



struct my_cdev ex_cdev;   //设备结构

int simple_open(struct inode  * inode,struct file * filp)
{
	if(count>=1)   //设备已被打开
	{
		printk(KERN_ERR "Device is in use.");
		return -EBUSY;
	}
	count++;    //设备初次打开,加一
	return 0;
}

int simple_release(struct inode * inode,struct file * filp)
{
	count--;   //关闭设备,计数减一
	return 0;
}

ssize_t simple_read(struct file * filp,char __user *usrbuf,size_t count,loff_t * f_pos)
{
	if(count>30)   //用户要求读出字符总数超过30个字节
	{
		printk(KERN_WARNING "Over the max length of the kernel array");
		return -1;
	}
	
	//拷贝内核空间的数据到用户空间
	if(copy_to_user(usrbuf,ex_cdev.kerbuf,count))
	{
		return -EFAULT;
	}

	return count;
}

ssize_t simple_write(struct file * filp,const char  __user *usrbuf,size_t count,loff_t * f_pos)
{
	if(count>30)  //用户写入字符总数超过30个字节
	{
		printk(KERN_WARNING "over the max length of the kernel array");
		return -1;
	}

	//拷贝用户空间的数据到内核空间
	if(copy_from_user(ex_cdev.kerbuf,usrbuf,count))
	{
		return -EFAULT;
	}

	return 0;
}


struct file_operations simple_ops=
{
	.owner=THIS_MODULE,
	.read=simple_read,
	.write=simple_write,
	.open=simple_open,
	.release=simple_release,
};

int  __init simple_init_module(void)
{
	int ret,result;
	
	devn=MKDEV(MYMAJOR,0);   //获取设备号

	ret=register_chrdev_region(devn,1,"/dev/mydev");  //起始设备号,设备个数,设备名
	if(ret<0)
	{
		printk(KERN_WARNING "failed to alloc a dev number");
		return ret;
	}


	//直接涉及内核的操作
	cdev_init(&ex_cdev.cd,&simple_ops);  
	ex_cdev.cd.owner=THIS_MODULE;
	result = cdev_add (&ex_cdev.cd, devn, 1);
	if(result)      
	{          
		printk(KERN_NOTICE "Error %d adding DEMO
", result);      
	}
	printk("success ,good!");

	return 0;
	
}

void __exit simple_cleanup_module(void)
{
	cdev_del(&ex_cdev.cd);
	unregister_chrdev_region(devn,1);
	printk("simple_cleanup_module");
}

module_init(simple_init_module);
module_exit(simple_cleanup_module);

 应用

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

int main()
{
	int fd,ret;
	char buf[30]={''};

	fd=open("/dev/mydev",O_RDWR|O_NONBLOCK|O_NOCTTY);
	if(fd<0)
	{
		printf("fail to open..");
		exit(1);
	}
	
	
	ret=write(fd,"hello",5);   //向设备写入5个字符
	if(ret<0)
	{
		printf("fail to write.. ");
		exit(1);
	}

	ret=read(fd,buf,5);     //从设备读入5个字符
	if(ret<0)
	{
		printf("fail to read..");
		exit(1);
	}

	printf("string=%s
",buf);     //打印从设备读到的字符
	close(fd);                 //关闭打开的文件
	return 0;
	
}
学习记录,方便复习
原文地址:https://www.cnblogs.com/jingjingdidunhe/p/4603284.html