linux字符驱动之概念介绍

一、字符驱动框架

问:应用程序open、read、write如何找到驱动程序的open、read、write函数?

答:应用程序的open、read、write是在C库里面实现的,它里面通过swi val指令去触发一个异常,这个异常就会进入到内核空间,在内核的异常处理函数里面有根据我们传入的val来决定调用system_open还是system_read、system_write函数,这些函数根据我们打开不同的文件、不同的文件就有不同的属性(例如设备类型(字符设备还是块设备还是网络设备)、主设备号),根据这些属性找到更底层的驱动程序。

 

问:什么是主设备号,什么是次设备号

答:Linux主设备号用来区分不同硬件设备类型,如LED和串口之间的区别;
Linux次设备号用来区分不同硬件设备,如串口1和串口2之间的区别;

 

问:通过什么样的方法来找到驱动程序的open函数

答:通过一个注册函数+设备节点

注册函数如下(旧的注册函数,新的以后再说):

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

参数1:主设备号(重要)

参数2:名字(不重要)

参数3:file_operations结构体(重要)

设备节点:

可以手工创建也可以自动创建,这里暂且只说手工创建

mknod  /dev/xxx  c  252  0

创建一个名为/dev/xxx的设备节点,c表示字符设备节点,252是主设备号,0是次设备号。

 

问:应用程序一般是由main函数开始执行,那么驱动程序一般是先执行什么?

答:通过一个宏,指定驱动程序的入口函数,当装载驱动时就会执行入口函数。

例如:module_init(first_drv_init);  //用于修饰入口函数

自然地,驱动程序的出口函数,则是在卸载驱动时就会执行出口函数。

例如:module_exit(first_drv_exit);  //用于修饰出口函数
 

 

驱动源程序如下:

#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 <linux/module.h>int major;
static int first_drv_open(struct inode * inode, struct file * filp)
{printk("first_drv_open\n");return 0;
}
static int first_drv_write(struct file * file, const char __user * buffer, size_t count, loff_t * ppos)
{printk("first_drv_write\n");return 0;
}/* File operations struct for character device */
static const struct file_operations first_drv_fops = {.owner		= THIS_MODULE,.open		= first_drv_open,.write      = first_drv_write,
};/* 驱动入口函数 */
static int first_drv_init(void)
{/* 主设备号设置为0表示由系统自动分配主设备号 */major = register_chrdev(0, "first_drv", &first_drv_fops);return 0;
}/* 驱动出口函数 */
static void first_drv_exit(void)
{unregister_chrdev(major, "first_drv");
}module_init(first_drv_init);  //用于修饰入口函数
module_exit(first_drv_exit);  //用于修饰出口函数	MODULE_AUTHOR("LWJ");
MODULE_DESCRIPTION("Just for Demon");
MODULE_LICENSE("GPL");  //遵循GPL协议

Makefile源码如下:

ifneq ($(KERNELRELEASE),)obj-m := first_drv.oelseKDIR := /home/opt/EmbedSky/linux-2.6.30.4all:make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-
clean:rm -f *.ko *.o *.mod.o *.mod.c *.symversendif

测试程序如下:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>int main(void){int fd;int val = 1;fd = open("/dev/xxx",O_RDWR);    //打开名为  /dev/xxx  的设备节点if(fd < 0){printf("open error\n");}write(fd,&val,4);return 0;
}

开发板上的测试步骤如下:

[WJ2440]# insmod first_drv.ko 
[WJ2440]# ./first_test 
open error                    //没有创建设备节点
[WJ2440]# cat proc/devices 
Character devices:1 mem4 /dev/vc/04 tty5 /dev/tty5 /dev/console5 /dev/ptmx7 vcs10 misc13 input14 sound29 fb81 video4linux89 i2c90 mtd
116 alsa
128 ptm
136 pts
180 usb
188 ttyUSB
189 usb_device
204 tq2440_serial
252 first_drv                //我们创建的字符设备,主设备号252
253 usb_endpoint
254 rtcBlock devices:
259 blkext7 loop8 sd31 mtdblock65 sd66 sd67 sd68 sd69 sd70 sd71 sd
128 sd
129 sd
130 sd
131 sd
132 sd
133 sd
134 sd
135 sd
179 mmc
[WJ2440]# mknod /dev/xxx c 252 0        //手动创建一个字符设备节点
[WJ2440]# ls -l /dev/xxx 
crw-r--r--    1 root     root      252,   0 Jan  1 20:49 /dev/xxx
[WJ2440]# ./first_test                 //有设备节点后成功我们的应用程序运行了
first_drv_open
first_drv_write
[WJ2440]# 

本文参考:

https://blog.csdn.net/lwj103862095/article/details/17468587

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384502.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

USB摄像头视频监控项目学习笔记

一个摄像头监控应用程序的系统调用如下所示&#xff1a; /* open * VIDIOC_QUERYCAP 确定它是否视频捕捉设备,支持哪种接口(streaming/read,write) * VIDIOC_ENUM_FMT 查询支持哪种格式 * VIDIOC_S_FMT 设置摄像头使用哪种格式 * VIDIOC_REQBUFS 申请buffer 对于 str…

图片缩放算法

项目背景&#xff1a;博主之前做过一个摄像头采集数据&#xff0c;然后在LCD上显示视频数据的项目&#xff0c;假如我们摄像头采集的一帧数据的分辨率比我们的LCD的分辨率要大&#xff0c;那么LCD则无法显示整个图像&#xff0c;这时候我们就要把这么一帧图片进行缩放&#xff…

数码相框项目之显示一张可放大、缩小、拖拽的图片

之前我做过一个电子相框的项目&#xff0c;涉及到的重难点主要为&#xff1a;在LCD上放大、缩小、移动图片。 首先我们得明白的一点是&#xff1a;无论是放大或缩小&#xff0c;实际上都是对原图进行等比例的缩小&#xff0c;然后在LCD上面显示&#xff0c;只不过缩小的程度不…

TCP协议-如何保证传输可靠性

TCP协议传输的特点主要就是面向字节流、传输可靠、面向连接。这篇博客&#xff0c;我们就重点讨论一下TCP协议如何确保传输的可靠性的。 确保传输可靠性的方式 TCP协议保证数据传输可靠性的方式主要有&#xff1a; 校验和序列号确认应答超时重传连接管理流量控制拥塞控制 校…

TCP协议-握手与挥手

认识TCP协议 TCP全称为“传输控制协议”&#xff0c;这是传输层的一个协议&#xff0c;对数据的传输进行一个详细的控制。 特点&#xff1a; 面向字节流安全可靠面向连接 TCP协议段格式 源端口号与目的端口号&#xff1a;这里与UDP的一样&#xff0c;每个数据都要知道从哪个…

ASOC注册过程

一、什么是ASOC 在嵌入式系统里面的声卡驱动为ASOC&#xff08;ALSA System on Chip&#xff09; &#xff0c;它是在ALSA 驱动程序上封装的一层&#xff0c;分为3大部分&#xff0c;Machine&#xff0c;Platform和Codec ,三部分的关系如下图所示&#xff1a;其中Machine是指我…

ASOC调用过程

上一篇文章我们将了嵌入式系统注册声卡的过程&#xff1a;https://blog.csdn.net/qq_37659294/article/details/104748747 这篇文章我们以打开一个声卡的播放节点为例&#xff0c;讲解一下在APP调用open时&#xff0c;最终会如何调用到硬件相关的函数。 在上一篇文章最后我们说…

进程上下文与中断上下文的理解

一.什么是内核态和用户态 内核态&#xff1a;在内核空间执行&#xff0c;通常是驱动程序&#xff0c;中断相关程序&#xff0c;内核调度程序&#xff0c;内存管理及其操作程序。 用户态&#xff1a;用户程序运行空间。 二.什么是进程上下文与中断上下文 1.进程上下文&#xf…

内核的Makefile与Kconfig关系解析

在子目录下的Kconfig里添加make menuconfig的选项&#xff08;如图一&#xff09;&#xff0c;并默认设置为y&#xff0c;make menuconfig的菜单里就会有该项并默认为选上状态&#xff0c;make menuconfig配置完之后在.config文件里就有该选项&#xff0c;并等于y&#xff08;如…

Linux信号之signal函数

1. 信号概述 何为信号&#xff1a;信号就是由用户、系统或进程发送给目标进程的信息&#xff0c;以通知目标进程中某个状态的改变或是异常。 信号产生&#xff1a;总体来说&#xff0c;其产生的条件有两种&#xff0c;分别是&#xff1a;硬件和软件原因&#xff0c;又称为&…

Linux中wait()函数及waitpid()函数

编程过程中&#xff0c;有时需要让一个进程等待另一个进程&#xff0c;最常见的是父进程等待自己的子进程&#xff0c;或者父进程回收自己的子进程资源包括僵尸进程。这里简单介绍一下系统调用函数&#xff1a;wait() 函数原型是 #include <sys/types.h> #include <…

学习笔记 --- DM9000网卡原理与基地址设置

前面有文章分析了网卡也是属于类内存总线的设备&#xff0c;类内存总线的设备有地址总线和数据总线&#xff0c;先来看下DM9000的管脚&#xff1a; 从上面可以看出DM9000的地址总线就一根&#xff0c;它不像CS8900那样地址总线和数据总线都齐全。而这里只有一根地址线(CMD)&…

静态VLAN的配置

在一台交换机上连接3台PC机&#xff0c;然后创建两个VLAN&#xff0c;分别为VLAN 10 和VLAN 20&#xff0c;把第一台PC机分配给VLAN 10&#xff0c;把其他两台分配给VLAN 20.然后测试他们的互通情况。 在这里命令我用的都是简化命令&#xff0c;想卡完整版命令&#xff0c;请到…

静态路由原理

1、路由器的工作原理 路由工作简单原理图 1&#xff09;主机1.1要发生数据包给主机4.1.因为IP地址不在同一网段&#xff0c;所以主机会将数据包发送给本网段的网关路由器。 2&#xff09;路由器A 接收到数据包&#xff0c;先查看数据包IP首部中的目标IP地址。再查找自己的路由表…

静态路由和默认路由

一、静态路由的配置 下边实验对该拓扑图进行配置 实验目标&#xff1a;配置静态路由&#xff0c;实现全网互通 1、配置路由器R1 进入接口f0/0&#xff0c;配置IP&#xff0c;并开启。 进入接口f0/1&#xff0c;配置IP&#xff0c;并开启。 设置静态路由。 查看PC1的路由表 2、配…

IP地址192.168.1.1/24中的/24是什么意思

/24是指子网掩码的位数。 子网掩码的位数总共有32个&#xff0c;写的的/24个就是24个1&#xff0c;其它8位都是0。 /24就可以写成子网掩码是&#xff1a;11111111 11111111 11111111 00000000 例如&#xff1a; /25&#xff0c;就代表有25个1&#xff0c;7个0&#xff0c;…

IP地址中A类、B类、C类地址的区别

区别如下&#xff1a; 1、IP地址表示方法不同&#xff1a; 一个A类IP地址是指&#xff0c; 在IP地址的四段号码中&#xff0c;第一段号码为网络号码&#xff0c;剩下的三段号码为本地计算机的号码。如果用二进制表示IP地址的话&#xff0c;A类IP地址就由1字节的网络地址和3字…

原始套接字简介

一 原始套接字概述 原始套接字&#xff0c;指在传输层下面使用的套接字。流式套接字和数据报套接字这两种套接字工作在传输层&#xff0c;主要为应用层的应用程序提供服务&#xff0c;并且在接收和发送时只能操作数据部分&#xff0c;而不能对IP首部或TCP和UDP首部进行操作&am…

TCP socket心跳包示例程序

TCP socket心跳包示例程序_xqhrs232的专栏-CSDN博客_setsockopt 心跳包 原文地址::TCP socket心跳包示例程序_神奕的专栏-CSDN博客_tcp心跳包 相关文章 1、Linux网络编程--服务端判断客户端断开的经验方法 ----Linux网络编程--服务端判断客户端断开的经验方法_志存高远-CSDN博…

sizeof()计算结构体的大小

原文链接&#xff1a;sizeof()计算结构体的大小_海月汐辰-CSDN博客_结构体的sizeof怎么计算 简要说明&#xff1a;结构体成员按照定义时的顺序依次存储在连续的内存空间&#xff0c;但是结构体的大小并不是简单的把所有成员大小相加&#xff0c;而是遵循一定的规则&#xff0c…