Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

linux驱动开发之字符设备框架 - 实例

$
0
0

前言

前两小节中介绍了字符设备的cdev和函数操作集 file_operations。理论还需要和实践结合起来,这节主要是给出一个示例代码和测试代码。

正文

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

#include <linux/cdev.h>
#include <linux/fs.h>

#define DEVICE_NAME "cdev_demo"

static struct cdev *pdev = NULL;
static int major = 0;
static int minor = 0;
static int count = 2;

static int cdev_demo_open(struct inode * inode, struct file * file)
{
    printk("%s,%d\n",__func__,__LINE__);
    return 0;
}
static int cdev_demo_release(struct inode *inode, struct file * file)
{
    printk("%s,%d\n",__func__,__LINE__);
    return 0;
}
static ssize_t cdev_demo_read(struct file * file, char __user * buffer, size_t size, loff_t * loff)
{
    printk("%s,%d\n",__func__,__LINE__);
    return 0;
}

static ssize_t cdev_demo_write(struct file * file, const char __user * buffer, size_t size, loff_t * loff)
{
    printk("%s,%d\n",__func__,__LINE__);
    return 0;
}
//函数操作集
static struct file_operations fops ={
    .owner   = THIS_MODULE,
    .open    = cdev_demo_open,
    .release = cdev_demo_release,
    .read    = cdev_demo_read,
    .write   = cdev_demo_write,
};
//入口函数
static int __init cdev_demo_init(void)
{
    dev_t dev;
    int ret;

    printk("%s,%d\n",__func__,__LINE__);
    //申请一个cdev结构体
    pdev = cdev_alloc();
    if(NULL == pdev){
        printk("cdev_alloc failed.\n");
        return -ENOMEM;
    }
    //初始化cdev
    cdev_init(pdev,&fops);
    //申请设备号
    ret = alloc_chrdev_region(&dev,minor,count,DEVICE_NAME);
    if(ret){
        printk("alloc_chrdev_region failed.\n");
        goto ERROR_CDEV;
    }
    major = MAJOR(dev);
    //添加cdev
    ret = cdev_add(pdev, dev,count);
    if(ret) {
        printk("cdev_add failed.\n");
        goto  ERROR_ADD;
    }

    return 0;
ERROR_ADD:
    unregister_chrdev_region(dev,count);
ERROR_CDEV:
    cdev_del(pdev);
    return ret;
}
//出口函数
static void __exit cdev_demo_exit(void)
{
    printk("%s,%d\n",__func__,__LINE__);
    unregister_chrdev_region(MKDEV(major,minor),count);

    cdev_del(pdev);
    return 0;
}

module_init(cdev_demo_init);
module_exit(cdev_demo_exit);
MODULE_LICENSE("GPL");

测试程序:

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

int main(int argc,char* argv[])
{

        int fd = open("/dev/cdev_demo",O_RDWR);
        if(0 > fd){
                perror("open\n");
                return -1;
        }
        printf("fd= %d\n",fd);


        write(fd,0,1);

        read(fd,0,1);

        close(fd);
        return  0;
}

操作步骤:

//安装模块
shell@tiny4412:/mnt # insmod cdev_demo.ko                                      
[  316.087934] cdev_demo_init,49

//查看申请的设备号
shell@tiny4412:/mnt # cat /proc/devices
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
 21 sg
 29 fb
 81 video4linux
 89 i2c
108 ppp
116 alsa
128 ptm
136 pts
153 spi
180 usb
188 ttyUSB
189 usb_device
204 ttySAC
247 cdev_demo  //系统自动分配的设备号
248 hidraw
249 BaseRemoteCtl
250 media
251 ttyGS
252 ump
253 leds
254 rtc


//在我们的驱动程序中,没有创建设备,需要手动的创建设备

shell@tiny4412:/mnt # mknod /dev/cdev_demo c 247 0
//  /dev/cdev_demo 表示我们的设备,c 表示字符设备 247 主设备号, 0 次设备号

运行测试程序
./test 
测试程序:
shell@tiny4412:/mnt # ./test                                                   
[  570.708740] cdev_demo_open,17
fd= 3
[  570.709397] cdev_demo_write,33
[  570.709483] cdev_demo_read,27
[  570.709564] cdev_demo_release,22

总结

目前的代码是在Android系统下运行的,在测试的过程中,出现 no such file or directory。
解决方案,在编译的时候,使用静态连接 -static

参考文献

在Android上运行C语言编写的可执行程序

作者:u013377887 发表于2017/5/17 21:24:19 原文链接
阅读:336 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>