玩转开发板--简单的字符设备

一.前言:

    开发环境:CentOS6.7(虚拟机);

    开发板fl2440使用的Linux版本3.0最小内核;

    编写驱动原则:只提供机制,不实现功能;     

    Linux内核将设备按照访问特性分为三类:字符设备、块设备、网络设备;

    

 

    字符设备(本次学习目标)

 

    一个字符设备是一种可以当做一个字节流来存取的设备(如同一个文件),对于这些设备它一次I/O只访问一个字节。一个字符驱动负责实现这种行为,这样的驱动常常至少实现open,close,read,和write系统调用

    例如:本例程使用命令mknod 创建的led节点如下:

/drivers >: ls /dev/led*
/dev/led0  /dev/led1  /dev/led2  /dev/led3

    注:mknod命令使用法则,可以通过mknod --help查看

 

    块设备

 

    常见的块设备有磁盘、光盘、U盘、SD卡、Nandflash、Norflash等。一个块设备一次I/O通常访问一个块的大小数据,这个大小通常2的幂次方字节(Nnadflash使用2048个字节)。对于块设备的使用,需要分区格式化后建立文件系统,之后在应用程序空间中使用mount命令挂载起来后使用

 

    网络设备

 

    网络设备包括有线网卡(eth0)、无线网卡(wlan0)、回环设备(lo0)、拨号网络设备(ppp0)等,他们在Linux内核里由网络协议栈实现,在/dev路径下并没有相应的设备节点,通过ifconfig -a命令可以查看所有网络设备。在应用程序编程时,所有对网络设备的访问都是通过socket()来访问的

 

二.字符设备驱动(注意要点)

 

    

    1.主次设备号

 

    字符设备通过文件系统中的设备名来存取,惯例上它们位于/dev目录。我们可以通过ls -l /dev 来查看当前有多少字符设备(由于有很多就不列举出来);也可以直接查看当前正在使用的cat /proc/devices;

/drivers >: ls -l /dev/led*
crwxr-xr-x    1 root     root      250,   0 Jan  1 00:01 /dev/led0
crwxr-xr-x    1 root     root      250,   1 Jan  1 00:01 /dev/led1
crwxr-xr-x    1 root     root      250,   2 Jan  1 00:01 /dev/led2
crwxr-xr-x    1 root     root      250,   3 Jan  1 00:01 /dev/led3
Character devices:
  1 mem
  4 /dev/vc/0
  4 tty
  4 ttyS
  5 /dev/tty
  5 /dev/console
  5 /dev/ptmx
  7 vcs
 10 misc
 13 input
....

 

    开头c表示字符设备,d表示文件夹,b表示块设备,s表示网络设备;

 

    250,    0:表示主次设备号;

    在编写底层驱动时,我们可以获取其主次设备号;

MAJOR(dev_t dev);
MINOR(dev_t dev);

    设定主、次设备号有2种方法:1.静态设定    2.动态设定;

    注:1.静态设定时要注意防止与其它设备住次设备号冲突;

           2.由于主次设备号是系统资源,故一定要在程序退出时释放其对应的设备号;

    

    2.file_operation结构

    file_operation就是把系统调用和驱动程序关联起来的关键数据结构。也就是说我们平常的open,read,ioctl,close等函数的使用与其密切相关;以下是部分file_operation说明:(头文件:/usr/include/linux/fs.h)

    

    例如:led_fops包涵open,close,ioctl调用

/* file operations open, close and ioctl */
static struct file_operations led_fops =
{
    .owner = THIS_MODULE,
    .open = led_open,
    .release = led_release,
    .unlocked_ioctl = led_ioctl,
};

    open函数:

static int led_open(struct inode *inode,struct file *file)
{   
    int minor = iminor(inode);

    file->private_data = (void *)minor;
    
    printk(KERN_DEBUG "/dev/drv_led %d opened.\n",minor);
    return 0;
}

 

    3.inode结构

 

    当我们在Linux中创建一个文件时,就会在相应的文件系统中创建一个inode与之对应,文件实体和文件的inode是一一对应的,创建好一个inode会存在存储器中

    当我们使用mknod创建一个设备文件时,也会在文件系统中创建一个inode,这个inode和其他的inode一样,用来存储关于这个文件的静态信息,包括这个设备文件对应的设备号,文件的路径以及对应的驱动对象等。(头文件:/usr/include/linux/fs.h)

    可以查看2.的例子程序,会用到inode关联;

    

    4.file结构

    linux内核会为每一个进程维护一个文件描述符表,这给表其实就是struct file的索引。open()的过程其实就是根据传入的路径填充好一个file结构并将其赋值到数组中并返回其索引。下面是file的主要内容,他一样是定义在include/linuxfs.h文件中;

    可以查看2.的例子程序,会用到file关联;

 

    5.cdev结构体

 

 

    内核在内部适用类型struct cdev的结构代表字符设备。在内核调用你的设备操作前,你必须分配一个这样的结构体并注册给Linux内核,在这个结构体里对于这个设备进行操作的函数,具体定义在file_operation结构体中。

    例如:

static struct cdev      *led_cdev;
static int __init s3c_led_init(void)
{
    led_cdev->owner = THIS_MODULE;
    cdev_init(led_cdev,&led_fops);
    cdev_add(led_cdev,devno,dev_count);
}

    注:cdev结构体还可以以动态方式初始化;也要记得释放cdev结构体;
    

 

    

 

 

 

 

    

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值