来源:LINUX设备驱动程序第三版配套源码

Table of Contents

simple.c

simple_load

simple_unload

Makefile


simple.c

/** Simple - REALLY simple memory mapping demonstration.** Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet* Copyright (C) 2001 O'Reilly & Associates** The source code in this file can be freely used, adapted,* and redistributed in source or binary form, so long as an* acknowledgment appears in derived source files.  The citation* should list that the code comes from the book "Linux Device* Drivers" by Alessandro Rubini and Jonathan Corbet, published* by O'Reilly & Associates.   No warranty is attached;* we cannot take responsibility for errors or fitness for use.** $Id: simple.c,v 1.12 2005/01/31 16:15:31 rubini Exp $*/#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>#include <linux/kernel.h>   /* printk() */
#include <linux/slab.h>   /* kmalloc() */
#include <linux/fs.h>       /* everything... */
#include <linux/errno.h>    /* error codes */
#include <linux/types.h>    /* size_t */
#include <linux/mm.h>
#include <linux/kdev_t.h>
#include <asm/page.h>
#include <linux/cdev.h>#include <linux/device.h>static int simple_major = 0;
module_param(simple_major, int, 0);
MODULE_AUTHOR("Jonathan Corbet");
MODULE_LICENSE("Dual BSD/GPL");/** Open the device; in fact, there's nothing to do here.*/
static int simple_open (struct inode *inode, struct file *filp)
{return 0;
}/** Closing is just as simpler.*/
static int simple_release(struct inode *inode, struct file *filp)
{return 0;
}/** Common VMA ops.*/void simple_vma_open(struct vm_area_struct *vma)
{printk(KERN_NOTICE "Simple VMA open, virt %lx, phys %lx\n",vma->vm_start, vma->vm_pgoff << PAGE_SHIFT);
}void simple_vma_close(struct vm_area_struct *vma)
{printk(KERN_NOTICE "Simple VMA close.\n");
}/** The remap_pfn_range version of mmap.  This one is heavily borrowed* from drivers/char/mem.c.*/static struct vm_operations_struct simple_remap_vm_ops = {.open =  simple_vma_open,.close = simple_vma_close,
};static int simple_remap_mmap(struct file *filp, struct vm_area_struct *vma)
{if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,vma->vm_end - vma->vm_start,vma->vm_page_prot))return -EAGAIN;vma->vm_ops = &simple_remap_vm_ops;simple_vma_open(vma);return 0;
}/** The nopage version.*/
struct page *simple_vma_nopage(struct vm_area_struct *vma,unsigned long address, int *type)
{struct page *pageptr;unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;unsigned long physaddr = address - vma->vm_start + offset;unsigned long pageframe = physaddr >> PAGE_SHIFT;// Eventually remove these printksprintk (KERN_NOTICE "---- Nopage, off %lx phys %lx\n", offset, physaddr);printk (KERN_NOTICE "VA is %p\n", __va (physaddr));printk (KERN_NOTICE "Page at %p\n", virt_to_page (__va (physaddr)));if (!pfn_valid(pageframe))return NOPAGE_SIGBUS;pageptr = pfn_to_page(pageframe);printk (KERN_NOTICE "page->index = %ld mapping %p\n", pageptr->index, pageptr->mapping);printk (KERN_NOTICE "Page frame %ld\n", pageframe);get_page(pageptr);if (type)*type = VM_FAULT_MINOR;return pageptr;
}static struct vm_operations_struct simple_nopage_vm_ops = {.open =   simple_vma_open,.close =  simple_vma_close,.nopage = simple_vma_nopage,
};static int simple_nopage_mmap(struct file *filp, struct vm_area_struct *vma)
{unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;if (offset >= __pa(high_memory) || (filp->f_flags & O_SYNC))vma->vm_flags |= VM_IO;vma->vm_flags |= VM_RESERVED;vma->vm_ops = &simple_nopage_vm_ops;simple_vma_open(vma);return 0;
}/** Set up the cdev structure for a device.*/
static void simple_setup_cdev(struct cdev *dev, int minor,struct file_operations *fops)
{int err, devno = MKDEV(simple_major, minor);cdev_init(dev, fops);dev->owner = THIS_MODULE;dev->ops = fops;err = cdev_add (dev, devno, 1);/* Fail gracefully if need be */if (err)printk (KERN_NOTICE "Error %d adding simple%d", err, minor);
}/** Our various sub-devices.*/
/* Device 0 uses remap_pfn_range */
static struct file_operations simple_remap_ops = {.owner   = THIS_MODULE,.open    = simple_open,.release = simple_release,.mmap    = simple_remap_mmap,
};/* Device 1 uses nopage */
static struct file_operations simple_nopage_ops = {.owner   = THIS_MODULE,.open    = simple_open,.release = simple_release,.mmap    = simple_nopage_mmap,
};#define MAX_SIMPLE_DEV 2#if 0
static struct file_operations *simple_fops[MAX_SIMPLE_DEV] = {&simple_remap_ops,&simple_nopage_ops,
};
#endif/** We export two simple devices.  There's no need for us to maintain any* special housekeeping info, so we just deal with raw cdevs.*/
static struct cdev SimpleDevs[MAX_SIMPLE_DEV];/** Module housekeeping.*/
static int simple_init(void)
{int result;dev_t dev = MKDEV(simple_major, 0);/* Figure out our device number. */if (simple_major)result = register_chrdev_region(dev, 2, "simple");else {result = alloc_chrdev_region(&dev, 0, 2, "simple");simple_major = MAJOR(dev);}if (result < 0) {printk(KERN_WARNING "simple: unable to get major %d\n", simple_major);return result;}if (simple_major == 0)simple_major = result;/* Now set up two cdevs. */simple_setup_cdev(SimpleDevs, 0, &simple_remap_ops);simple_setup_cdev(SimpleDevs + 1, 1, &simple_nopage_ops);return 0;
}static void simple_cleanup(void)
{cdev_del(SimpleDevs);cdev_del(SimpleDevs + 1);unregister_chrdev_region(MKDEV(simple_major, 0), 2);
}module_init(simple_init);
module_exit(simple_cleanup);

simple_load

#!/bin/sh
module="simple"
device="simple"
mode="664"# Group: since distributions do it differently, look for wheel or use staff
if grep '^staff:' /etc/group > /dev/null; thengroup="staff"
elsegroup="wheel"
fi# invoke insmod with all arguments we got
# and use a pathname, as newer modutils don't look in . by default
/sbin/insmod -f ./$module.ko $* || exit 1major=`cat /proc/devices | awk "\\$2==\"$module\" {print \\$1}"`# Remove stale nodes and replace them, then give gid and perms
# Usually the script is shorter, it's simple that has several devices in it.rm -f /dev/${device}[rn]
mknod /dev/${device}r c $major 0
mknod /dev/${device}n c $major 1
chgrp $group /dev/${device}[rn]
chmod $mode  /dev/${device}[rn]

simple_unload

#!/bin/sh
module="simple"
device="simple"# invoke rmmod with all arguments we got
/sbin/rmmod $module $* || exit 1# Remove stale nodes
rm -f /dev/${device}[rn] 

Makefile

# Comment/uncomment the following line to disable/enable debugging
#DEBUG = y# Add your debugging flag (or not) to CFLAGS
ifeq ($(DEBUG),y)DEBFLAGS = -O -g # "-O" is needed to expand inlines
elseDEBFLAGS = -O2
endifCFLAGS += $(DEBFLAGS) -I$(LDDINCDIR)ifneq ($(KERNELRELEASE),)
# call from kernel build systemobj-m    := simple.oelseKERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD       := $(shell pwd)default:$(MAKE) -C $(KERNELDIR) M=$(PWD) LDDINCDIR=$(PWD)/../include modulesendifclean:rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versionsdepend .depend dep:$(CC) $(CFLAGS) -M *.c > .dependifeq (.depend,$(wildcard .depend))
include .depend
endif

一个Linux驱动:Simple - REALLY simple memory mapping demonstration.相关推荐

  1. i.MX283开发板第一个Linux驱动-LED驱动

    字符设备驱动开发 字符设备是 Linux 驱动中最基本的一类设备驱动,字符设备就是一个一个字节,按照字节流进行读写操作的设备,读写数据是分先后顺序的.比如我们最常见的点灯.按键.IIC.SPI,LCD ...

  2. 实战!手把手教你如何编写一个Linux驱动并写一个支持物联网的LED演示demo

    目录 一.开发环境 二. 准备工作: 1. 创建一个项目工程目录 2. 创建输出与目标目录 3.头文件目录 4. 建立源代码src目录 5. 使用git管理你的项目 三.编写LED驱动 三.一 准备工 ...

  3. 第一个Linux驱动

    1. 建立工程 2. 建立.vscode c_pp_properties.json {"configurations": [{"name": "Lin ...

  4. 如何成为一个Linux内核开发者

    你想成知道如何成为一个Linux内核开发者么?或者你的老板告诉你,"去为这个设备写一个Linux驱动."这篇文档的目的,就是通过描述你需要经历的过程和提示你如何和社区一起工作,来教 ...

  5. linux多进程通过中断实现,Linux驱动中断上下文中会发生什么结果实验测试

    一.前言 每一个Linux驱动工程师都知道这样一个准则:在中断上下文中不能睡眠.但是为什么interrupt context中不能调用导致睡眠的kernel API呢?如果驱动这么做会导致什么样的后果 ...

  6. LINUX驱动、系统底层

    就业模拟测试题-LINUX驱动.系统底层工程师职位 本试卷从考试酷examcoo网站导出,文件格式为mht,请用WORD/WPS打开,并另存为doc/docx格式后再使用 试卷编号:143921 试卷 ...

  7. linux驱动面试题整理

    1.字符型驱动设备你是怎么创建设备文件的,就是/dev/下面的设备文件,供上层应用程序打开使用的文件? 答:mknod命令结合设备的主设备号和次设备号,可创建一个设备文件. 评:这只是其中一种方式,也 ...

  8. 正点原子linux驱动教程,正点原子 手把手教你学Linux之驱动开发篇

    简 介 该课程是正点原子手把手教你学Linux系列课程,该课程配套开发板为正点原子alpha/mini Linux开发板. 手把手教你学Linux之驱动开发篇: 第1讲 Linux驱动开发与裸机开发区 ...

  9. MT6572平台加入呼吸灯功能——编写linux驱动

    上一篇介绍了本实验所使用的主要IC及其通信方式,这里开始记录正式的开发过程.所选用的平台为MTK的MT6572,做过MTK智能平台研发的亲们都知道,MTK将自己的东西都添加在自加的包mediatek下 ...

最新文章

  1. 架构师之路 — API 经济 — Swagger OpenAPI Specification
  2. Mac用户SVN图形界面推荐
  3. UIView的生命周期
  4. 数论练习1 ( 曹冲养猪 + [POJ 2891]Strange Way to Express Integers + 乘法逆元【带证明】)
  5. 【渝粤教育】电大中专学前儿童健康教育_1作业 题库
  6. 关于计算机网络的描述错误的是,【单选题】以下关于计算机网络定义的描述中,错误的是...
  7. ThinkPHP6内核通用网站后台权限管理系统源码
  8. mysql视图_MySQL视图详解
  9. 06-netty之http之文件服务器
  10. 2021年中国传送控制器市场趋势报告、技术动态创新及2027年市场预测
  11. 100 道 Linux 笔试题,能拿90分以上的都去了BAT
  12. 六神不安,生死命悬一线
  13. 正确调用腾讯x5内核详解
  14. Grasshopper Essential Training Grasshopper基础教程 Lynda课程中文字幕
  15. ideaIU-2018.2.2 版本常用设置
  16. wincap函数用法简述
  17. 黑龙江省大学计算机学校排名2015,2015黑龙江省大学排行榜 哈工大第一
  18. WPS网盘怎么显示在我的电脑里?
  19. Segment Routing入门
  20. matlab-基础 复数 实部、虚部、模、共轭、辐角

热门文章

  1. Java基础-IO流
  2. (转)Vue 爬坑之路(四)—— 与 Vuex 的第一次接触
  3. Codeforces 432D Prefixes and Suffixes(KMP+dp)
  4. codeforces 471B. MUH and Important Things 解题报告
  5. XML Drawable
  6. 修改华为服务器管理口地址,修改华为服务器管理口地址
  7. freemarker+生成java_Freemarker + xml 实现Java导出word
  8. android 结束if循环_几款Android反编译器对循环结构的还原能力测试记录
  9. 树莓派连接usb手机_树莓派03 - 树莓派的VNC连接
  10. 规划系统_智慧水务规划系统思维的设计思考