博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
驱动 (1.1) linux字符设备驱动的组织及应用程序如何交互
阅读量:4285 次
发布时间:2019-05-27

本文共 9177 字,大约阅读时间需要 30 分钟。

  • 字符设备驱动
#define WITH_SYSFS 0#if WITH_SYSFS#include 
#endif#include
#include
#include
#include
#include
#if WITH_SYSFS#define CLASS_NAME "hello_class"#define DEVICE_NAME "hello_device"#endif#define DATA_SIZE 32static dev_t dev_number;//static struct device * hello_device;#if WITH_SYSFSstatic struct class * hello_class;#endifstatic struct cdev * hello_cdev;typedef struct{ void * data; int data_size;} resource_t;static resource_t resource;int get_cpsr(void){ int tmp; asm volatile ( "mrs r3,cpsr\n\t" "mov %0,r3\n\t" : "=r" (tmp) : ); return tmp;}int print_cpsr(void){ printk("kernel space:0x%x\n",get_cpsr());}static int hello_open(struct inode *inode, struct file *file){ print_cpsr(); dump_stack(); printk("my device is open\n"); file->private_data = &resource; return 0;}static ssize_t hello_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos){ int ret = 0; int actual_readed; int max_free; int need_read; dump_stack(); resource_t * tmp_resource = file->private_data; printk("my device is read\n"); max_free = tmp_resource->data_size - *ppos; printk("max_free:%d\n",max_free); need_read = max_free > count? count : max_free; printk("need_read:%d\n",need_read); if (need_read == 0) printk("hello_device,no space for read\n"); ret = copy_to_user(buffer,((resource_t *)(file->private_data))->data + *ppos, need_read); if (ret == need_read) return -EFAULT; actual_readed = need_read - ret; printk("actual_readed:%d\n",actual_readed); *ppos += actual_readed; return actual_readed;}static ssize_t hello_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos){ int ret = 0; int free; int actual_write; int need_write; resource_t * tmp_resource = file->private_data; printk("my device is write\n"); dump_stack(); free = tmp_resource->data_size - *ppos; printk("free:%d\n",free); need_write = free > count ? count : free; printk("need_write:%d\n",need_write); if (need_write == 0){ printk("hello_device,no space for write\n"); } ret = copy_from_user(((resource_t *)(file->private_data))->data + *ppos,buffer,need_write); if (ret == need_write) return -EFAULT; actual_write = need_write - ret; printk("actual_write:%d\n",actual_write); *ppos += actual_write; return actual_write;}static loff_t hello_llseek (struct file * file, loff_t ppos, int whence){ loff_t newpos; resource_t * tmp_resource = file->private_data; dump_stack(); switch(whence) { case 0: /* SEEK_SET */ newpos = ppos; break; case 1: /* SEEK_CUR */ newpos = file->f_pos + ppos; break; case 2: /* SEEK_END */ newpos = tmp_resource->data_size + ppos; break; default: /* can't happen */ return -EINVAL; } if (newpos < 0) return -EINVAL; file->f_pos = newpos; return newpos;}static int hello_close(struct inode *inode, struct file *file){ dump_stack(); printk("my device is close\n"); return 0;}static struct file_operations hello_fops = { .owner = THIS_MODULE, .open = hello_open, .read = hello_read, .write = hello_write, .llseek = hello_llseek, .release = hello_close, .aio_read = NULL, // 如果不填充,默认为NULL .aio_write = NULL, .read_iter = NULL, .write_iter = NULL, .iterate = NULL, .poll = NULL, .unlocked_ioctl = NULL, .compat_ioctl = NULL, .mmap = NULL, .mremap = NULL, .flush = NULL, .fsync = NULL, .aio_fsync = NULL, .fasync = NULL, .lock = NULL, .sendpage = NULL, .get_unmapped_area = NULL, .check_flags = NULL, .flock = NULL, .splice_write = NULL, .splice_read = NULL, .setlease = NULL, .fallocate = NULL, .show_fdinfo = NULL,};static void data_init(void){ resource.data_size = DATA_SIZE; resource.data = kzalloc(resource.data_size,GFP_KERNEL); strcpy(resource.data,"hello world");}static void data_deinit(void){ kfree(resource.data); resource.data = NULL;}static int __init hello_init(void){ int error; // 申请设备号 error = alloc_chrdev_region(&dev_number, 0, 1, "hello_dev"); if (error) { printk("hello: alloc_chardev_region failed! "); goto out; } printk("major is %d\n",MAJOR(dev_number)); printk("minor is %d\n",MINOR(dev_number)); // 申请 cdev hello_cdev = cdev_alloc(); if (hello_cdev == NULL) { printk("hello: alloc cdev failed! "); error = -ENOMEM; goto out_chrdev; } // 填充 cdev hello_cdev->ops = &hello_fops; hello_cdev->owner = THIS_MODULE; // 绑定设备号到cdev,并注册cdev error = cdev_add(hello_cdev, dev_number, 1); if (error) { printk("hello: cdev_add failed! "); goto out_cdev; }#if WITH_SYSFS // 创建 /sys/CLASS_NAME 文件夹 hello_class = class_create(THIS_MODULE, CLASS_NAME); if (IS_ERR(hello_class)) { error = PTR_ERR(hello_class); goto out_chrdev; } // 在 /sys/CLASS_NAME 文件夹下创建 /sys/CLASS_NAME/DEVICE_NAME device_create(hello_class, NULL, dev_number, NULL, DEVICE_NAME);#endif data_init(); printk("hello: Hello World \n"); return 0;out_cdev: cdev_del(hello_cdev);out_chrdev: unregister_chrdev_region(hello_cdev->dev, 1);out: return error;}static void __exit hello_exit(void){ #if WITH_SYSFS // 销毁文件 device_destroy(hello_class, dev_number); // 销毁 /sys/CLASS_NAME 文件夹 class_destroy(hello_class);#endif // 注销设备号 unregister_chrdev_region(hello_cdev->dev, 1); // 注销 cdev cdev_del(hello_cdev); data_deinit(); printk("hello: Goodbye World \n");}module_init(hello_init);module_exit(hello_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("YWW");MODULE_DESCRIPTION("HELLO_CLASS_AUTO_DEV");
  • 插入驱动
插入之后,打印如下major is 252minor is 0hello: Hello World
  • 手动创建设备文件
mknod  -m 666 /dev/hello_device  c 252 0
  • app
#include 
#include
#include
#include
#include
#include
#define check_read() \ do{\ if (n < 0){\ perror("read");\ } else{\ printf("buf read :%d,%s\n",n,buf);\ }\ }while(0)#define check_write() \ do{\ if (n < 0){\ perror("write");\ } else{\ printf("buf write :%d\n",n);\ }\ }while(0)int main(void){ char buf[32]; int fd = 0; int n = 0; fd = open("/dev/hello_device",O_RDWR); if (fd < 0){ perror("open"); } fd = open("/dev/hello_device",O_RDWR); if (fd < 0){ perror("open"); } n = read(fd,buf,32); check_read(); lseek(fd,0,SEEK_SET); // 从 SEEK_SET 移动 0 // SEEK_CUR // SEEK_END n = read(fd,buf,32); check_read(); lseek(fd,0,SEEK_END); // 从 SEEK_SET 移动 0 // SEEK_CUR // SEEK_END n = read(fd,buf,32); check_read(); lseek(fd,0,SEEK_SET); // 从 SEEK_SET 移动 0 // SEEK_CUR // SEEK_END n = write(fd,"hello2",6); check_write(); memset(buf,0,32); read(fd,buf,32); check_read(); close(fd); return 0;}

调用堆栈

  • open
CPU: 0 PID: 704 Comm: char_user_test Tainted: G           O    4.0.0+ #62Hardware name: ARM-Versatile Express[<80016cb0>] (unwind_backtrace) from [<80012bc4>] (show_stack+0x20/0x24)[<80012bc4>] (show_stack) from [<80543528>] (dump_stack+0x80/0x90)[<80543528>] (dump_stack) from [<7f0040a8>] (hello_open+0x24/0x2c [class_test])[<7f0040a8>] (hello_open [class_test]) from [<8011b5a4>] (chrdev_open+0xdc/0x19c)[<8011b5a4>] (chrdev_open) from [<80115020>] (do_dentry_open.isra.2+0x204/0x31c)[<80115020>] (do_dentry_open.isra.2) from [<801151d4>] (vfs_open+0x54/0x58)[<801151d4>] (vfs_open) from [<80124a74>] (do_last.isra.17+0x458/0xc8c)[<80124a74>] (do_last.isra.17) from [<80125334>] (path_openat+0x8c/0x5f8)[<80125334>] (path_openat) from [<80126818>] (do_filp_open+0x3c/0x98)[<80126818>] (do_filp_open) from [<80116290>] (do_sys_open+0x120/0x1e4)[<80116290>] (do_sys_open) from [<8011637c>] (SyS_open+0x28/0x2c)[<8011637c>] (SyS_open) from [<8000ebc0>] (ret_fast_syscall+0x0/0x34)
  • write
CPU: 0 PID: 704 Comm: char_user_test Tainted: G           O    4.0.0+ #62Hardware name: ARM-Versatile Express[<80016cb0>] (unwind_backtrace) from [<80012bc4>] (show_stack+0x20/0x24)[<80012bc4>] (show_stack) from [<80543528>] (dump_stack+0x80/0x90)[<80543528>] (dump_stack) from [<7f004050>] (hello_write+0x24/0x2c [class_test])[<7f004050>] (hello_write [class_test]) from [<80117368>] (vfs_write+0xb0/0x1c0)[<80117368>] (vfs_write) from [<801179fc>] (SyS_write+0x4c/0xa0)[<801179fc>] (SyS_write) from [<8000ebc0>] (ret_fast_syscall+0x0/0x34)
  • read
CPU: 0 PID: 704 Comm: char_user_test Tainted: G           O    4.0.0+ #62Hardware name: ARM-Versatile Express[<80016cb0>] (unwind_backtrace) from [<80012bc4>] (show_stack+0x20/0x24)[<80012bc4>] (show_stack) from [<80543528>] (dump_stack+0x80/0x90)[<80543528>] (dump_stack) from [<7f004024>] (hello_read+0x24/0x2c [class_test])[<7f004024>] (hello_read [class_test]) from [<801177c8>] (__vfs_read+0x28/0x5c)[<801177c8>] (__vfs_read) from [<80117884>] (vfs_read+0x88/0x114)[<80117884>] (vfs_read) from [<8011795c>] (SyS_read+0x4c/0xa0)[<8011795c>] (SyS_read) from [<8000ebc0>] (ret_fast_syscall+0x0/0x34)
  • close
CPU: 0 PID: 704 Comm: char_user_test Tainted: G           O    4.0.0+ #62Hardware name: ARM-Versatile Express[<80016cb0>] (unwind_backtrace) from [<80012bc4>] (show_stack+0x20/0x24)[<80012bc4>] (show_stack) from [<80543528>] (dump_stack+0x80/0x90)[<80543528>] (dump_stack) from [<7f00407c>] (hello_close+0x24/0x2c [class_test])[<7f00407c>] (hello_close [class_test]) from [<80118570>] (__fput+0x90/0x1d8)[<80118570>] (__fput) from [<80118728>] (____fput+0x18/0x1c)[<80118728>] (____fput) from [<80040c04>] (task_work_run+0xbc/0xf4)[<80040c04>] (task_work_run) from [<8001241c>] (do_work_pending+0x8c/0xb4)[<8001241c>] (do_work_pending) from [<8000ec04>] (work_pending+0xc/0x20)

转载地址:http://roigi.baihongyu.com/

你可能感兴趣的文章
linux產生 core dump文件方法及設置
查看>>
How to pass macro definition from “makefile” command line arguments to C source code?
查看>>
英文句型
查看>>
mtd and /dev/mtd*相關資料
查看>>
cp: cannot create symbolic link to fat format of usb: Operation not permitted
查看>>
MTD bad Block issue
查看>>
How to change network interface name
查看>>
ubifs and ubi and mtd
查看>>
shell script set 用法
查看>>
英文序數寫法與唸法 Ordinal Numbers(轉載)
查看>>
DVB-S info
查看>>
绿盟扫描操作指导
查看>>
理解链路本地址与站点本地地址
查看>>
/proc/mtd 各个参数含义 -- linux内核
查看>>
linux nand flash常用命令
查看>>
NESSUS扫描操作指导
查看>>
C语言读取文件大小,载入文件全部内容
查看>>
C语言 static静态变量的作用
查看>>
Linux(C/C++)下的文件操作open、fopen与freopen
查看>>
C语言 文件操作的头文件
查看>>