5.2.10.应用程序如何调用驱动 mknod /dev/test c 250 0 创建设备文件,应用app 程序 调用 我们 驱动 壳子

5.2.10.应用程序如何调用驱动


5.2.10.1、驱动设备文件的创建
(1)何为设备文件

 

  索引驱动
(2)设备文件的关键信息是:设备号 = 主设备号 + 次设备号,使用ls -l去查看设备文件,就可以得到这个设备文件对应的主次设备号。

        4颗LED不可能 都占用 主设备号,设备号 = 主设备号 + 次设备号
(3)使用mknod创建设备文件:mknod /dev/xxx c 主设备号 次设备号

  xxx : 设备文件名 ,我们这里是 test

c : 字符设备;  主设备号: 我们这里是 250;  次设备号: 0

 

 

5.2.10.2、写应用来测试驱动
(1)还是原来的应用
(2)open、write、read、close等

1.  增加了 app.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


#define FILE  "/dev/test"   // 刚才mknod创建的设备文件 名,必须保持一致


int main(void)
{
	int fd = -1;
	
	fd = open(FILE, O_RDWR);
	if(fd < 0)
	{
		printf("open %s error \n",FILE);
		return -1;
	}
	printf("open %s success..\n",FILE);
	
	//读文件
	
	
	
	
	
	//关闭 文件
	close(fd);
	
	return 0;
}


2.  Makefile 文件

#ubuntu的内核源码树,如果要编译在ubuntu中安装的模块就打开这2个
#KERN_VER = $(shell uname -r)
#KERN_DIR = /lib/modules/$(KERN_VER)/build	

		
# 开发板的linux内核的源码树目录  
KERN_DIR = /root/driver/kernel

obj-m	+= module_test.o

all:
	make -C $(KERN_DIR) M=`pwd` modules 
	# app 是在 开发板运行 所以 arm-linux-gcc 
	arm-linux-gcc app.c -o app
cp:
	cp *.ko app /root/rootfs/rootfs/driver_test
	#cp app  /root/rootfs/rootfs/driver_test	

.PHONY: clean	
clean:
	make -C $(KERN_DIR) M=`pwd` modules clean
	

3. module_test.c  无更改,只是 KERN_INFO 更换 KERN_DEBUG

#include <linux/module.h>		// module_init  module_exit
#include <linux/init.h>			// __init   __exit
#include <linux/fs.h>


#define MYMAJOR 200  /* 定义 register_chrdev 注册设备的 主设备号 */

#define MYNAME  "test_char" /* 定义 register_chrdev 注册设备的 设备名字 */

int mymajor; /* 定义 register_chrdev 注册设备号*/

/* NOTE  自己定义函数指针  test_chrdev_open  */
static int test_chrdev_open(struct inode *inode, struct file *file)
{
	/* 这个函数中真正应该 放置 打开这个硬件设备的 操作代码 ,我们先 printk 代替一下 */
	printk(KERN_INFO "test_chrdev_open\n");  
	
	return 0;

} /* test_chrdev_open() */




/* NOTE  自己定义函数指针 test_chrdev_release ,   release对应的就是 close  */
static int test_chrdev_release(struct inode *inode, struct file *file)
{
	printk(KERN_INFO "test_chrdev_release\n");

	return 0;
}



//自定义  file_operations 结构体 及其元素填充
/* NOTE  定义 register_chrdev 注册设备的 设备结构体 test_fops */
static const struct file_operations test_fops = {
	.owner		= THIS_MODULE,                    /* 所有的驱动 代码这一行不需要动,所有的都是这样,不是函数指针, 惯例直接写即可 */
	
	.open		= test_chrdev_open,  /* 将来应用 open 打开这个设备时实际 调用的就是这个 .open  函数指针*/
	.release	= test_chrdev_release,         /* release对应的就是 close    函数指针 */
};









// 模块安装函数
static int __init chrdev_init(void)
{	
	int ret = -1;  /* 定义 register_chrdev 的返回值  */
	
	printk(KERN_INFO "chrdev_init helloworld init\n");
	
	
	// 在 module_init 宏 调用函数中去注册字符串 设备驱动
	mymajor = register_chrdev(0, "test_char", &test_fops);   /* major设成0,内核帮我们自动分配空白的设备号,分配的值会 做返回值 ,负数还是返回失败  */
	if(mymajor < 0)
	{
		printk(KERN_ERR "registe_chrdev fail \n");
		return -EINVAL;  /* 返回一个错误码 需要加 ’-‘负号*/
	}
	printk(KERN_INFO "自动分配 register_chrdev success....mymajor = %d \n",mymajor);
	
	return 0;
}

// 模块卸载函数
static void __exit chrdev_exit(void)
{
	printk(KERN_INFO "chrdev_exit helloworld exit\n");
	
	// 在 module_exit宏 调用函数中去注销 字符串 设备驱动
	unregister_chrdev(mymajor, "test_char");  /* 这里不判断返回值 了,一般不会出错 */
}


module_init(chrdev_init);
module_exit(chrdev_exit);

// MODULE_xxx这种宏作用是用来添加模块描述信息
MODULE_LICENSE("GPL");				// 描述模块的许可证
MODULE_AUTHOR("aston");				// 描述模块的作者
MODULE_DESCRIPTION("module test");	// 描述模块的介绍信息
MODULE_ALIAS("alias xxx");			// 描述模块的别名信息




/***********************************************************
如果 KERN_DEBUG 打印不出来,更改打印级别 或者  	
printk(KERN_DEBUG "chrdev_init helloworld init\n"); 

[root@liang_x210 driver_test]# cat /proc/sys/kernel/printk
7       4       1       7
[root@liang_x210 driver_test]# echo 8 > /proc/sys/kernel/printk
[root@liang_x210 driver_test]# cat /proc/sys/kernel/printk
8       4       1       7
************************************************************/



(3)实验现象预测和验证

 

5.2.10.3、总结
(1)整体流程梳理、注意分层

1.当我们 执行 ./app 程序时
    fd = open(FILE, O_RDWR);

2.其实就是执行 module_test.c
    static int test_chrdev_open(struct inode *inode, struct file *file)
    { printk(KERN_INFO "test_chrdev_open\n");  }


3.  当我们 执行 close(fd); /* app.c文件 */
4.  其实就是执行 module_test.c
    static int test_chrdev_release(struct inode *inode, struct file *file)
    { printk(KERN_INFO "test_chrdev_release\n"); }

 代码更改图片:

 

(2)后续工作:添加读写接口

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大漠飞鹰6666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值