liunx设备驱动有:字符设备驱动,块设备驱动,网络设备驱动。本节简单总结一下字符设备驱动。
static int myfirstdrv_open(struct inode *inode, struct file *file)
{
printk("myfirstdrv_open\n");
return 0;
}
static ssize_t myfirstdrv_read(struct file *file, char *buf,size_t count, loff_t *ofs)
{
printk("myfirstdrv_read\n");
return 0;
}
static ssize_t myfirstdrv_write(struct file *file, const char __user * user_buffer, size_t count, loff_t *ppos)
{
printk("myfirstdrv_write\n");
return 0;
}
static struct file_operations myfirstdrv_fops = {
.owner = THIS_MODULE,
.read = myfirstdrv_read,
.write = myfirstdrv_write,
.open = myfirstdrv_open,
};
static int myfirstdrv_init(void)
{
register_chrdev(<span style="color:#ff0000;">111</span>, "myfirstdrv", &myfirstdrv_fops);
return 0;
}
static void myfirstdrv_exit(void)
{
unregister_chrdev(111, "myfirstdrv");
}
module_init(myfirstdrv_init);
module_exit(myfirstdrv_exit);
MODULE_AUTHOR("wang");
MODULE_LICENSE("GPL");
上述代码是一个最简单的字符设备驱动程序,
字符设备驱动程序就是对
file_operations 结构体的填充。在应用程序里,我们的open,read,write,函数,经过系统调用,最终会到达驱动程序里调用我们相应的open,read,write函数。那应用程序是怎么知道该调用哪一个的呢。答案是通过主设备号和属性等信息。
<pre name="code" class="objc">int main(int argc,char **argv)
{
int iVal=1;
int iFd;
iFd = open("/dev/xxx",O_RDWR);
if(iFd<0)
{
printf("cant open /dev/xxx\n");
return -1;
}
write(iFd, &iVal, 4);
return 0;
}
在一开始的驱动程序里,我们手动写入了主设备号111,我们怎么确定111没有其他设备占用呢,使用cat /proc/devices命令查看,使用没有被使用的主设备号即可。这种方法实在是太笨拙了,每次都要去很查看主设备号。我们可以把主设备号写0,系统就会为其自动分配主设备号。
<pre name="code" class="objc">int major;
static int myfirstdrv_init(void)
{
<span style="color:#ff0000;">major = register_chrdev(0</span>, "myfirstdrv", &myfirstdrv_fops);
return 0;
}
我们又会想到每次都要去手工创建设备节点也是一件相当麻烦的事情。mdev机制则很好的解决了这一麻烦。
<pre name="code" class="objc"><span style="color:#ff0000;">static struct class *myfirstdrv_class;
static struct class_device *myfirstdrv_class_dev;</span>
static int myfirstdrv_init(void)
{
major = register_chrdev(0, "myfirstdrv", &myfirstdrv_fops);
<span style="color:#ff0000;"> myfirstdrv_class = class_create(THIS_MODULE, "myfirstdrv");
myfirstdrv_class_dev = device_create(myfirstdrv_class, NULL, MKDEV(major, 0), NULL, "char"); /* /dev/char */</span>
return 0;
}
static void myfirstdrv_exit(void)
{
unregister_chrdev(111, "myfirstdrv");
<span style="color:#ff0000;">device_destroy(myfirstdrv_class, MKDEV(major, 0));
class_destroy(myfirstdrv_class);</span>
}
mdev会在加载驱动程序时会在sys目录下生成系统信息,创建设备节点。这样就不用我们自己手动创建了。
/mnt # insmod myfirst_drv.ko
/mnt # lsmod
myfirst_drv 1271 0 - Live 0xbf00c000 (O)
/mnt # ./myfirstdrvtest
myfirstdrv_open
myfirstdrv_write
/mnt # cat /proc/devices
Character devices:
1 mem
2 pty
3 ttyp
4 /dev/vc/0
4 tty
5 /dev/tty
5 /dev/console
5 /dev/ptmx
7 vcs
10 misc
13 input
14 sound
21 sg
29 fb
90 mtd
116 alsa
128 ptm
136 pts
180 usb
189 usb_device
204 ttySAC
252 myfirstdrv
</pre><br /><br /><pre>