linux字符驱动之初见

学习驱动也有长达一年多的时间了,受益最深的就是看韦东山老师的视频,如今已经几乎将二期三期的视频全部看完,甚至已经将二期视频看过好几遍,为了再次加深印象,我将韦老师的源码自己全部编写一遍。将所有遇到的问题,记录在此。觉得看了韦老师的视频,再看其他视频都是弱爆了。由于是文章记录,不可能写的非常详细,只摘录关键点,想具体详细的深入,还请去看韦老大的视频吧。

这篇文章是主要是讲解字符驱动的框架,并没有涉及高级字符驱动。

一、字符驱动框架

------------------------------------------------------------------------

APP:     open               read                   write

------------------------------------------------------------------------

C 库

------------------------------------------------------------------------

      system_open    system_read       system_write


------------------------------------------------------------------------

KERNEL:

      led_open           led_read               led_wirte

------------------------------------------------------------------------


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

答:应用程序的open通过C库的open函数,通过系统调用的system_open函数,进而通过swi val指令,进入内核,通过一定的办法来找到驱动程序的open函数。

问:通过什么样的方法来找到驱动程序的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

具体什么含义,我就不多说了,看视频吧,很简单。


问:应用程序一般是由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源码如下:

KERN_DIR = ~/work/s3c2440/linux/kernel/linux-2.6.22.6

all:
	make -C $(KERN_DIR) M=`pwd` modules 

clean:
	make -C $(KERN_DIR) M=`pwd` modules clean
	rm -rf modules.order

obj-m	+= first_drv.o

测试程序如下

#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);
	if(fd < 0)
	{
		printf("open error\n");
	}
	
	write(fd,&val,4);
	
	return 0;
}


编译:arm-linux-gcc first_test.c -omain

测试:insmod first_drv.ko
发现:多了一个first_drv的节点

cat /proc/devices
Character devices:

....
252 first_drv
...
这时候直接调用驱动测试程序main,发现报错

# /mnt/s3c2440/linux/driver/net/1/main
open error

解决方法解释上面的mknod /dev/xxx c 252 0,此就是创建一个主设备好252,次设备号0的设备节点
然后调用main,会提示

# /mnt/s3c2440/linux/driver/net/1/main
first_drv_open
first_drv_write

根据http://blog.csdn.net/lwj103862095/article/details/17468587测试验证修改


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Wireless_Link

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

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

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

打赏作者

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

抵扣说明:

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

余额充值