/*Linux字符设备驱动源代码scdd.c*/

#include <linux/init.h>   /*模块头文件*/

#include <linux/module.h>

#include <linux/types.h>  /*dev_t头文件*/

#include <linux/kdev_t.h> /*MAJOR和MINOR宏头文件*/

#include <linux/fs.h>     /*register_chrdev_region等函数

file_operations结构体*/

#include <linux/cdev.h>   /*struct cdev结构体*/

#include <asm/uaccess.h>  /*copy_to_user函数*/

#define DEVICE_NAME "scdd"  /*定义设备名*/

#define DEVICE_MAJOR 250

struct cdev my_cdev;

int scdd_open(struct inode *inode,structfile *filp)

{

return0;

}

int scdd_close(struct inode *inode,structfile *filp)

{

return0;

}

ssize_t scdd_read(struct file *filp,char__user *buff,size_t size,loff_t *offp)

{

intleft;

chardata=1;

for(left=size;left>0;left--)

{

/*拷贝数据到用户空间*/

copy_to_user(buff,&data,1);

buff++;

}

returnsize;

}

ssize_t scdd_write(struct file *filp,char__user *buff,size_t size,loff_t *offp)

{

return0;

}

/*file_operations结构体*/

struct file_operations scdd_fops={

.owner=THIS_MODULE,

.read=scdd_read,

.write=scdd_write,

.open=scdd_open,

.release=scdd_close,

};

static int __init scdd_init(void)

{     /*模块初始化函数*/

intsmajor;

smajor=DEVICE_MAJOR;

dev_tdev_n=MKDEV(smajor,0);

/*申请设备号*/

if(!register_chrdev_region(dev_n,1,DEVICE_NAME))

{     /*静态申请*/

printk("registersuccess\n");

}else

{

gotoregister_error;

}

/*else

{     /*动态申请*/

/*alloc_chrdev_region(&dev_n,0,1,DEVICE_NAME);

smajor=MAJOR(dev_n);

}*/

/*初始化cdev结构体*/

cdev_init(&my_cdev,&scdd_fops);

my_cdev.owner=THIS_MODULE;

my_cdev.ops=&scdd_fops;

/*注册字符设备*/

cdev_add(&my_cdev,dev_n,1);

return0;

register_error:

unregister_chrdev_region(MKDEV(DEVICE_MAJOR,0),1);

return0;

}

static void __exit scdd_exit(void)

{     /*模块卸载函数*/

cdev_del(&my_cdev);

unregister_chrdev_region(MKDEV(DEVICE_MAJOR,0),1);

}

module_init(scdd_init);

module_exit(scdd_exit);

MODULE_LICENSE("Dual BSD/GPL");

这个程序只是简单演示字符注册的一个完整过程,并不带有复杂的操作,调用read时向用户空间写全1

要点:

1.设备号,主设备号用来标识设备所对应的驱动程序,同一个驱动程序可以对应多个设备,次设备号就是用来区分采用同一个驱动程序的不同设备文件。

内核中采用dev_t来描述设备号,其实dev_t实质为unsigned int类型,其中高12位为主设备号,低20位为次设备号,其定义在linux/types.h中

从dev_t中分解出主设备号和次设备号

MAJOR(dev_t dev)

MINOR(dev_t dev)

将主设备号和次设备号转换成dev_t类型

MKDEV(intmajor,int minor)

2.申请设备号

静态申请,函数定义在linux/fs.h中

int register_chrdev_region(dev_t from,unsigned count,const char *name)

from是申请设备号起始值,from次设备号经常被置成0,count是所请求连续设备号个数,name是该设备号范围关联的名称,它将出现在/proc/device和sysfs中。

分配成功返回0,错误情况下,将返回一个负的错误码,并且不能使用所请求的设备号。

动态申请

int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name)

申请的设备号将保存在dev中,baseminor为所申请的第一个次设备号

无论哪种方式申请设备号,不使用时要释放设备号

void unregister_chrdev_region(dev_t first,unsigned int count)

3.三个重要的结构

struct file_operations

struct file

struct inode

struct file_operations一个函数指针集合,定义能在设备上进行的操作,常用的有:

int (*open)(structinode *inode,stuuct file *filep)

void (*release)(structinode *inode,struct file *filep)

ssize_t(*read)(struct file *filep,char __user *buff,size_t size,loff_t *offp)

ssize_t(*write)(struct file *filep,char __user *buff,size_t seze,loff_t * offp)

int(*ioctl)(struct inode *inode,struct file *filep,unsigned int cmd,unsigned longarg) off_t(*llseek)(struct file *filp,loff_t,int)

struct file表示一个打开的文件,一个文件被打开十次,则有10个structfile结构

struct file结构成员有:

mode_t f_mode 文件模式,例如:可读可写

lofft_t f_pos 当前读/写位置

struct file_operations *f_op 与文件相关操作,执行open操作时对这个指针赋值

void *private_data在open时置为NULL,用于跨系统调用时保存非常有用的资源

struct inode用来记录文件的物理上的信息,一个文件被打开10次,但只有一个structinode结构,struct inode结构成员如下:

dev_t i_rdev 用来保存设备号

struct cdev*i_cdev 指向字符设备结构struct cdev的指针

4.字符设备的注册

内核使用struct cdev结构表示字符设备,定义在linux/cdev.h中。

初始化cdev结构体有两种方式

静态:

struct cdev my_cdev;

cdev_init(&my_cdev,&fops);
my_cdev.owner = THIS_MODULE;

动态(就是通过kmalloc去申请cdev结构):

struct cdev *my_cdev = cdev_alloc();

my_cdev->ops= &my_fops;

my_cdev.owner= THIS_MODULE;

注册

int cdev_add(struct cdev *dev,dev_t num,unsigned int count)

num是设备号,count经常取1

注销

void cdev_del(struct cdev *dev)

早起比较经典的字符设备驱动注册和注销方法

注册

int register_chrdev(unsigned int major,const char *name,struct file_operations*fops)

注销

int unregister_chrdev(unsigned int major,const char *name)

转载于:https://www.cnblogs.com/phonegap/archive/2011/12/09/2536134.html

Linux字符设备驱动相关推荐

  1. ()shi linux字符设备,Linux字符设备驱动基础(三)

    Linux字符设备驱动基础(三) 6 创建设备节点 6.1 手动创建设备节点 查看申请的设备名及主设备号: cat /proc/devices # cat /proc/devices Characte ...

  2. linux设备模型 字符设备,Linux 字符设备驱动模型之框架解说

    一.软件操作硬件设备模型 在进行嵌入式开发的过程中,在常做的事情就是驱动配置硬件设 备,然后根据功能需求使用硬件设备,实现功能的逻辑.如下图为其 相互之间的关系. 如上图所示: 驱动程序:主要作为操作 ...

  3. linux字符设备文件的打开操作,Linux字符设备驱动模型之字符设备初始化

    因为Linux字符设备驱动主要依赖于struct cdev结构,原型为: 所以我们需要对所使用到的结构成员进行配置,驱动开发所使用到的结构成员分别为:[unsigned int count;].[de ...

  4. linux生成驱动编译的头文件,嵌入式Linux字符设备驱动——5生成字符设备节点

    嵌入式Linux字符设备驱动开发流程--以LED为例 前言 留空 头文件 #include 查看系统设备类 ls /sys/class 设备类结构体 文件(路径):include/linux/devi ...

  5. linux字符设备驱动的 ioctl 幻数

    在Linux字符设备驱动入门(一)中,我们实现了字符设备的简单读写字符功能,接下来我们要在这个基础上加入ioctl功能.首先,我们先来看看3.0内核下../include/linux/fs.h中fil ...

  6. Linux 字符设备驱动结构(四)—— file_operations 结构体知识解析

    前面在 Linux 字符设备驱动开发基础 (三)-- 字符设备驱动结构(中) ,我们已经介绍了两种重要的数据结构 struct inode{...}与 struct file{...} ,下面来介绍另 ...

  7. linux字符设备驱动在哪里设置,从点一个灯开始学写Linux字符设备驱动!

    原标题:从点一个灯开始学写Linux字符设备驱动! [导读] 前一篇文章,介绍了如何将一个hello word模块编译进内核或者编译为动态加载内核模块,本篇来介绍一下如何利用Linux驱动模型来完成一 ...

  8. Linux字符设备驱动中container_of宏的作用

    Linux字符设备驱动中container_of宏的作用 首先看看这个宏的原型: container_of(ptr,type,member) 功能:根据一个结构体变量中的一个成员变量的指针来获取指向整 ...

  9. linux3.0字符设备驱动,linux字符设备驱动的 ioctl 幻数

    在Linux字符设备驱动入门(一)中,我们实现了字符设备的简单读写字符功能,接下来我们要在这个基础上加入ioctl功能.首先,我们先来看看3.0内核下../include/linux/fs.h中fil ...

最新文章

  1. 面试命中率 90% 的点 :MySQL 锁
  2. kindle刷多看系统_疑问解答 | kindle真的能护眼吗?
  3. 2013\Province_C_C++_A\3.振兴中华
  4. python中排序从小到大_从Python看排序:冒泡排序
  5. 使用 gunicorn 部署flask项目
  6. VMware 安装kali——linux
  7. ipc (进程间通信
  8. 2019年7月9日星期二(C语言)
  9. 关于Unity3D脚本调试
  10. 由浅入深探究mysql索引结构原理、性能分析与优化
  11. java 获取拦截url,java – 从数据库或属性中获取Spring Security拦截URL
  12. 解决未在此计算机注册ActiveX 控件
  13. python输入矩阵_python矩阵输入
  14. Linux固态硬盘 设置写入缓存,Win10下的写入缓存策略严重影响SSD硬盘的性能!
  15. 不越狱将ipa安装到iphone
  16. EXCEL插入、数据灰色不能使用的解决办法之一
  17. 数组(一维数组,二维数组)
  18. 固态硬盘在线测试软件,ssd测试软件,详细教您ssd测试软件
  19. wireshark源码分析二
  20. Omnipeek空口抓包(2):扫描无线网络

热门文章

  1. C++函数参数传递--值传递和地址传递
  2. 详解机器学习的凸优化、图神经网络、强化学习、贝叶斯方法等四大主题
  3. Unet美发实例分割,染发展示
  4. yum update upgrade 区别_CentOS与RedHat的区别
  5. oracle 11g Flashback Data Archive(闪回数据归档)
  6. Qt实现Areo效果_vortex_新浪博客
  7. egg风格 什么意思_egg裙什么意思
  8. 嵌入式实时操作系统ucos-ii_「正点原子NANO STM32开发板资料连载」第三十八章 UCOSII 实验 3...
  9. mysql性能优化方案总结
  10. Nancy之从403到错误处理