/* 内核如何调用驱动入口函数 ? */
/* 答: 使用module_init()函数,
module_init()函数定义一个结构体,这个结构体里面有一个函数指针,
指向first_drv_init()这个驱动入口函数,当我们加载或安装一个驱动程序时,
内核就会自动找到这样一个结构体,然后调用这个结构体中的函数指针,
从而调用了驱动入口函数first_drv_init(void),该驱动入口函数中有
register_chrdev(主设备号,设备名,struct file_operations结构体指针)函数,
该函数会将驱动程序的file_operations结构体连同其主设备号一起向内核进行注册,
从而该驱动入口函数将一个struct file_operations 类型的结构体传送给内核,
内核可以调用这个结构中的函数指针,从而调用具体的驱动操作函数,
    应用程序操作设备文件时所调用的open, read,write等函数,最终都会
调用struct file_operations类型的结构体,例如在应用程序中用Open()函数打开驱动文件时,

linux内核会根据该设备文件的类型以及主设备号找到在内核中注册的file_operations类型的结构体*/

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h> static struct class *firstdrv_class;
static struct class_device *firstdrv_class_dev; volatile unsigned long *gpfcon = NULL;
volatile unsigned long *gpfdat = NULL; static int first_drv_open(struct inode *inode, struct file *file)
{
//printk("first_drv_open\n");
/* 配置GPF4,5,6为输出 */
*gpfcon &= ~((0x3<<(*)) | (0x3<<(*)) | (0x3<<(*)));
*gpfcon |= ((0x1<<(*)) | (0x1<<(*)) | (0x1<<(*)));
return ;
} static ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
int val; //printk("first_drv_write\n"); copy_from_user(&val, buf, count); // copy_to_user(); if (val == )
{
// 点灯
*gpfdat &= ~((<<) | (<<) | (<<));
}
else
{
// 灭灯
*gpfdat |= (<<) | (<<) | (<<);
} return ;
} static struct file_operations first_drv_fops = {
.owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
.open = first_drv_open,
.write = first_drv_write,
}; int major;
static int first_drv_init(void)/*驱动的入口函数*/
{
major = register_chrdev(, "first_drv", &first_drv_fops); /*注册, 把first_drv_fops告诉内核*/ firstdrv_class = class_create(THIS_MODULE, "firstdrv"); firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, ), NULL, "xyz"); /* /dev/xyz */ gpfcon = (volatile unsigned long *)ioremap(0x56000050, );
gpfdat = gpfcon + ; return ;
} static void first_drv_exit(void)
{
unregister_chrdev(major, "first_drv"); // 卸载 class_device_unregister(firstdrv_class_dev);
class_destroy(firstdrv_class);
iounmap(gpfcon);
}
/* 内核如何调用驱动入口函数 ? */
/* 答: 使用module_init()函数,
module_init()函数定义一个结构体,这个结构体里面有一个函数指针,
指向first_drv_init()这个驱动入口函数,当我们加载或安装一个驱动程序时,
内核就会自动找到这样一个结构体,然后调用这个结构体中的函数指针,
从而调用了驱动入口函数first_drv_init(void),该驱动入口函数中有
register_chrdev(主设备号,设备名,struct file_operations结构体指针)函数,
该函数会将驱动程序的file_operations结构体连同其主设备号一起向内核进行注册,
从而该驱动入口函数将一个struct file_operations 类型的结构体传送给内核,
内核可以调用这个结构中的函数指针,从而调用具体的驱动操作函数,
应用程序操作设备文件时所调用的open, read,write等函数,最终都会
调用struct file_operations类型的结构体*/
module_init(first_drv_init);
/**/
module_exit(first_drv_exit); /**/
MODULE_LICENSE("GPL");

linux字符设备驱动中内核如何调用驱动入口函数 一点记录的更多相关文章

  1. 深入理解Linux字符设备驱动

    文章从上层应用访问字符设备驱动开始,一步步地深入分析Linux字符设备的软件层次.组成框架和交互.如何编写驱动.设备文件的创建和mdev原理,对Linux字符设备驱动有全面的讲解.本文整合之前发表的& ...

  2. Linux字符设备驱动结构(一)--cdev结构体、设备号相关知识机械【转】

    本文转载自:http://blog.csdn.net/zqixiao_09/article/details/50839042 一.字符设备基础知识 1.设备驱动分类 linux系统将设备分为3类:字符 ...

  3. Linux字符设备中的两个重要结构体(file、inode)

    对于Linux系统中,一般字符设备和驱动之间的函数调用关系如下图所示 上图描述了用户空间应用程序通过系统调用来调用程序的过程.一般而言在驱动程序的设计中,会关系 struct file 和 struc ...

  4. Linux字符设备驱动

    一.字符设备基础 字符设备 二.字符设备驱动与用户空间访问该设备的程序三者之间的关系 三.字符设备模型 1.Linux内核中,使用 struct cdev 来描述一个字符设备 动态申请(构造)cdev ...

  5. Linux字符设备驱动实现

    Linux字符设备驱动实现 要求 编写一个字符设备驱动,并利用对字符设备的同步操作,设计实现一个聊天程序.可以有一个读,一个写进程共享该字符设备,进行聊天:也可以由多个读和多个写进程共享该字符设备,进 ...

  6. linux字符设备驱动--基本知识介绍

    一.设备驱动的分类 1.字符设备 字符设备是指那些能一个字节一个字节读取数据的设备,如LED灯.键盘.鼠标等.字符设备一般需要在驱动层实现open().close().read().write().i ...

  7. Linux字符设备驱动基本结构

    1.Linux字符设备驱动的基本结构 Linux系统下具有三种设备,分别是字符设备.块设备和网络设备,Linux下的字符设备是指只能一个字节一个字节读写的设备,不能随机读取设备内存中某一数据,读取数据 ...

  8. (57)Linux驱动开发之三Linux字符设备驱动

    1.一般情况下,对每一种设备驱动都会定义一个软件模块,这个工程模块包含.h和.c文件,前者定义该设备驱动的数据结构并声明外部函数,后者进行设备驱动的具体实现. 2.典型的无操作系统下的逻辑开发程序是: ...

  9. 谈谈Linux字符设备驱动的实现

    @ 目录 字符设备驱动基础 申请设备号 创建设备节点 在驱动中实现操作方法 文件IO调用驱动中的操作 应用程序与驱动的数据交互 内核驱动如何控制外设 控制LED的简单驱动实例 驱动程序的改进 框架复盘 ...

随机推荐

  1. spring 5.x 系列第10篇 —— 整合mongodb (代码配置方式)

    源码Gitub地址:https://github.com/heibaiying/spring-samples-for-all 一.说明 1.1 项目结构说明 配置文件位于com.heibaiying. ...

  2. 微信小程序商城(Java版)

    体验 后台演示地址(账号:admin 密码:admin) 小程序体验如下: 技术选型 1 后端使用技术 1.1 springframework4.3.7.RELEASE 1.2 mybatis3.1. ...

  3. springboot-redis-crda example

    springboot-redis-crda example 1. 从 https://github.com/XLuffyStory/springboot-redis-crdu 拿到源码之后,导入到ST ...

  4. Python开发【第九篇】: 并发编程

    内容概要 操作系统介绍 进程 线程 协程 二. 进程 python并发编程之多进程理论部分 在python程序中的进程操作 运行中的程序就是一个进程.所有的进程都是通过它的父进程来创建的.因此,运行起 ...

  5. MyBatis从入门到精通(十):使用association标签实现嵌套查询

    最近在读刘增辉老师所著的<MyBatis从入门到精通>一书,很有收获,于是将自己学习的过程以博客形式输出,如有错误,欢迎指正,如帮助到你,不胜荣幸! 本篇博客主要讲解使用associati ...

  6. 《C#并发编程经典实例》学习笔记—2.7 避免上下文延续

    避免上下文延续 在默认情况下,一个 async 方法在被 await 调用后恢复运行时,会在原来的上下文中运行. 为了避免在上下文中恢复运行,可让 await 调用 ConfigureAwait 方法 ...

  7. zeroMQ 4 java

    自己最开始是在cloud foundry中接触过消息服务器(nats),或者说是消息中间件,也算是初步知道了一个消息服务器对于分布式的网络系统的重要性,后来自己也曾想过在一些项目中使用它,尤其是在一些 ...

  8. 微信小程序全局变量改变监听

    问题来源 最近工作需要写小程序页面,其中有个页面情况为:父页面中包含了一个组件页面,组件页面中又包含了另外一个组件页面.需求为:点击最后一个组件页面中的一个view,需要显示最外层父页面中的一个弹出层 ...

  9. Node热部署插件

    一.supervisor 首先需要使用 npm 安装 supervisor(这里需要注意一点,supervisor必须安装到全局) $ npm install -g supervisor Linux ...

  10. 数据结构-堆栈和队列最简单的实现(Python实现)

    OK,上篇博客我们介绍了双向链表以及代码实现,这篇文章我们来学习堆栈和队列. 队.栈和链表一样,在数据结构中非常基础一种数据结构,同样他们也有各种各样.五花八门的变形和实现方式.但不管他们形式上怎么变 ...