Linux设备驱动程序设计(三)----Linux的特殊字符设备:混杂设备,依旧让LED闪烁起来

看了上面的文章,大家也会觉得创建字符设备是一件很复杂的事情,步骤太多,对于初学者要摸好长时间才能慢慢熟悉,然后还要创建设备文件,虽然每一步不难,但是组合到一起就显得有些繁琐了,没办法,开发Linux的都是大牛,更多的精力放到了功能上,而忽略了用户体验与操作的便捷性。

Linux针对像LED这样的操作,有一种设备叫做混杂设备:是一种特殊的字符设备,它的主设备号为10,我们重新启动开发板,然后执行命令:cat /proc/devices ,可以看到:

root@at91sam9260ek:/# cat /proc/devices 
Character devices:
  1 mem
  2 pty
  3 ttyp
  4 /dev/vc/0
  4 tty
  4 ttyS
  5 /dev/tty
  5 /dev/console
  5 /dev/ptmx
  7 vcs
 10 misc
 13 input
 14 sound
 90 mtd
116 alsa
128 ptm
136 pts
153 spi
180 usb
189 usb_device
253 usb_endpoint
254 rtc

说明混杂设备早已经存在,是为了给开发者一个叫为简单的操作方式,因为不用再重新申请一个设备号了(misc就是混杂设备的意思),那么它和普通的字符设备有什么不同呢?其实是操作上方便了很多,然我们先看驱动程序,其实改变也不是很大:

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <mach/gpio.h>

//定义命令
#define LED_ON		_IOW('h',0x01,unsigned long)		//LED开的命令
#define LED_OFF		_IOW('h',0x02,unsigned long)		//LED关的命令

int open_state = 0;			//1为打开,0为关闭

/*-----------------------------------------------------------------------------
  函数名:      led_open
  参数:        struct inode *inode,struct file *filp
  返回值:      int
  描述:        open对应的驱动函数
 *-----------------------------------------------------------------------------*/
int led_open(struct inode *inode,struct file *filp )
{
	if(open_state == 0)
	{
		open_state =  1;
		printk("Open file suc!\n");
		return 0;
	}
	else
	{
		printk("The file has opened!\n");
		return -1;
	}
}
/*-----------------------------------------------------------------------------
  函数名:      led_release
  参数:        struct inode *inode,struct file *filp
  返回值:      int
  描述:        open对应的驱动函数
 *-----------------------------------------------------------------------------*/
int led_release(struct inode *inode,struct file *filp )
{
	if(open_state == 1)
	{
		open_state =  0;
		printk("close file suc!\n");
		return 0;
	}
	else
	{
		printk("The file has closed!\n");
		return -1;
	}
}
/*-----------------------------------------------------------------------------
  函数名:      led_ioctl
  参数:        struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg
  返回值:      int
  描述:        ioctl对应的驱动函数
 *-----------------------------------------------------------------------------*/
int led_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
{
	switch(cmd)
	{
		case LED_ON: printk("ON!\n");
						at91_set_gpio_value(AT91_PIN_PC0, 1); 			//灯亮起来
						break;

		case LED_OFF:printk("OFF\n");
						at91_set_gpio_value(AT91_PIN_PC0, 0); 			//灯灭掉
						break;

		default :printk("Error command!\n");
	}
	return 0;
}

const struct file_operations led_fop =
{
	.owner = THIS_MODULE,
	.open  = led_open,
	.ioctl = led_ioctl,
	.release = led_release,
};

struct miscdevice misc =
{
		.minor = 30,
		.fops = &led_fop,
		.name = "led3"
};
/*-----------------------------------------------------------------------------
  函数名:      gpio_init
  参数:        void
  返回值:      int
  描述:        模块初始化函数,在安装模块时候执行
 *-----------------------------------------------------------------------------*/
static int __init gpio_init(void)  
{
	int ret;

	printk("------GPIO misc test init-----\n");

	/**
	 *  混杂设备主设备号就是10,通过次设备号来区分
	 */
	ret = misc_register(&misc);				//向内核注册设备号
	if(ret < 0)
	{
		printk("Register Error!\n");
		return ret;
	}

	/**
	 * 初始化字符设备
	 */

	at91_set_gpio_output(AT91_PIN_PC0,1);		//设置引脚为输出功能,且为高电平
	return 0;	
}

/*-----------------------------------------------------------------------------
  函数名:      gpio_exit
  参数:        void
  返回值:      void
  描述:        模块卸载函数,在卸载模块时候执行
 *-----------------------------------------------------------------------------*/
static void __exit gpio_exit(void)	
{
	misc_deregister(&misc);
	open_state = 0;
	printk("GPIO test End\n");
}

module_init(gpio_init);
module_exit(gpio_exit);

MODULE_LICENSE("GPL");
从上面可以看到方便了很多,只需要misc_register注册一下,然后在一定一个结构体的时候直接关联file_operations结构即可,不用再申请设备号。

应用程序和上面一样,就是打开的文件变成了led3,这不是重点,重点是看以下操作和运行结果:

root@at91sam9260ek:/mnt/misc_dev# lsmod
Module                  Size  Used by    Not tainted
root@at91sam9260ek:/mnt/misc_dev# ls /dev |grep led          
root@at91sam9260ek:/mnt/misc_dev# insmod misc_dev.ko
------GPIO misc test init-----
root@at91sam9260ek:/mnt/misc_dev# ls /dev |grep led
led3
root@at91sam9260ek:/mnt/misc_dev# ./test
Open file suc!
ON!
OFF
ON!
OFF
ON!
OFF
ON!
OFF
ON!
OFF
ON!
OFF
ON!
OFF
ON!
OFF
ON!
close file suc!
Close the file suc!
root@at91sam9260ek:/mnt/misc_dev# 
可能已经发现了,它会自动生成设备文件,大大方便了我们的操作!

所以建议大家再使用字符设备驱动驱动led的时候,用混杂设备,比重新申请一个字符设备好用很多。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值