模块描述

将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\n", 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]={'\0'}; 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\n",buf); //打印从设备读到的字符
close(fd); //关闭打开的文件
return 0; }

MY_FIRSH_MODULE的更多相关文章

随机推荐

  1. Entity Framework实例详解

    Entity Framework Code First的默认行为是使用一系列约定将POCO类映射到表.然而,有时候,不能也不想遵循这些约定,那就需要重写它们.重写默认约定有两种方式:Data Anno ...

  2. vim关于 引号和 括号的 高效操作-很好很强大的!

    http://blog.csdn.net/bigshady/article/details/6019963 对括号匹配, 进行跳转, 使用的是%. 匹配的括号, 都会被高亮显示, 但是: 根据光标的 ...

  3. mysql 导入sql文件,source命令

    转自:http://blog.sina.com.cn/s/blog_610997850100mwv8.html 今天碰到个问题要用phpmyadmin导入1G的数据,但是在怎么都导入不了,用命令行就可 ...

  4. centos 安装 mysql5.7.9初始密码问题

    mysql5.7.9在安装完成后会,root用户会产生一个不为空的初始密码,登陆mysql就会产生问题了,有必要修改一下登陆密码: 这是从网上找的一个方法,加以总结得出来的,亲测可以:# /etc/i ...

  5. jdk的安装及配置

    前几天重新了下系统,所以JDK也要重新安装,顺带温故了安装及配置的过程,记录下来.(安装的版本是JDK1.7.0) 后面基本都是点下一步(i第一步选:开发工具),路径我改为E:/java/jdk 1. ...

  6. Java 中浮点数---------BigDecimal和double(初探)

    为什么要使用 bigdecimal? 借用<Effactive Java>这本书中的话,float和double类型的主要设计目标是为了科学计算和工程计算.他们执行二进制浮点运算,这是为了 ...

  7. Nginx-tomcat-redis------负载均衡以及session共享

    测试环境 Nginx 1.10.1 tomcat 7.0.70 Redis-x64-3.2.100 说明 tomcat 8 和 redis 实现session共享 有问题. 寻找源码 发现tomcat ...

  8. Java多线程初学者指南(7):向线程传递数据的三种方法

    在传统的同步开发模式下,当我们调用一个函数时,通过这个函数的参数将数据传入,并通过这个函数的返回值来返回最终的计算结果.但在多线程的异步开发模式下,数据的传递和返回和同步开发模式有很大的区别.由于线程 ...

  9. C#深入浅出 关键字(一)

    1.this this关键字用于指示当前对象“自己”,来看一个例子,了解什么时候需要用this class Star { String name; int age; public void SetIn ...

  10. Swift2.1 语法指南——可空链式调用

    原档:https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programmi ...