linux驅動開發(三) 字符設備驅動框架

 

仍是老規矩先上代碼node

demo.clinux

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



int demo_major = 250; int demo_minor = 0; int demo_count = 1; struct cdev cdev; int  demo_open(struct inode *inodep, struct file * filep) // 打開設備
{ printk("%s,%d\n", __func__, __LINE__); return 0; } int demo_release(struct inode * inodep, struct file * filep)  // 關閉設備
{ printk("%s,%d\n", __func__, __LINE__); return 0; } struct file_operations  fops = { .owner = THIS_MODULE, .open = demo_open, .release = demo_release, }; static int __init demo_init(void) { int ret = 0; dev_t devno; printk("%s,%d\n", __func__, __LINE__); //使用下列宏則能夠經過主設備號和次設備號生成 dev_t
    devno = MKDEV(demo_major, demo_minor); printk("devno:%d\n", devno); printk("demo_major:%d\n", demo_major); /**在調用 cdev_add()函數向系統註冊字符設備以前, *應首先調用 register_chrdev_region()或alloc_chrdev_region()函數向系統申請設備號 **/
    if (demo_major)//靜態申請 { ret = register_chrdev_region(devno, 1, "demo"); } else //動態分配 { ret = alloc_chrdev_region(&devno, 0, 1, "demo"); } if(ret) { printk("Failed to register_chrdev_region.\n"); return ret; } //cdev_init()函數用於初始化 cdev 的成員,並創建 cdev 和 file_operations 之間的鏈接
    cdev_init(&cdev, &fops); cdev.owner = THIS_MODULE; //系統添加一個 cdev,完成字符設備的註冊。
    ret = cdev_add(&cdev, devno, demo_count); if(ret) { printk(KERN_NOTICE " Failed to cdev_add [Error] %d adding demo%d", ret, demo_count); unregister_chrdev_region(devno, demo_count); return ret; } return 0; } static void __exit demo_exit(void) { printk("%s,%d\n", __func__, __LINE__); //刪除一個 cdev,完成字符設備的註銷。
    cdev_del(&cdev); //在調用cdev_del()函數從系統註銷字符設備以後,unregister_chrdev_region()應該被調用以釋放原先申請的設備號
 unregister_chrdev_region( MKDEV(demo_major, demo_minor), demo_count ); } module_init(demo_init); module_exit(demo_exit); MODULE_AUTHOR(" libra13179 "); MODULE_LICENSE("GPL v2");

 Makefileshell

VERS = $(shell uname -r) # Kernel modules obj-m += demo.o # Specify flags for the module compilation. #EXTRA_CFLAGS=-g -O0 build: kernel_modules kernel_modules: make -C /lib/modules/$(KVERS)/build M=$(CURDIR) modules clean: make -C /lib/modules/$(KVERS)/build M=$(CURDIR) clean

 make測試一下ide

 使用dmesg指令來查看函數

 

使用 cat /proc/devices看到demo的信息測試

 

 

 

 下面截圖來自https://blog.csdn.net/u012142460/article/details/78932165ui

 

 

如今主要介紹demo.c中使用到函數和宏,結構體等spa

<linux/cdev.h>.net

使用cdev結構體描述一個字符設備code

1 struct cdev 2 { 3     struct kobject kobj; /* 內嵌的 kobject 對象 */
4     struct module *owner;    /*所屬模塊*/
5     struct file_operations *ops;  /*文件操做結構體*/
6     struct list_head list; 7     dev_t dev;           /*設備號*/
8     unsigned int count; 9 };
cdev結構體

cdev 結構體的 dev_t 成員定義了設備號,爲 32 位,其中 12 位主設備號,20 位次設備號。

比較用到三個宏

<linux/kdev_t.h>

#define MAJOR(dev)    ((unsigned int) ((dev) >> MINORBITS))
#define MINOR(dev)    ((unsigned int) ((dev) & MINORMASK))
#define MKDEV(ma,mi)    (((ma) << MINORBITS) | (mi))

 

用下列宏能夠從 dev_t 得到主設備號和次設備號:
MAJOR(dev_t dev)
MINOR(dev_t dev)
使用下列宏則能夠經過主設備號和次設備號生成 dev_t:
MKDEV(int major, int minor)

<linux/cdev.h>

void cdev_init(struct cdev *, const struct file_operations *);//初始化cdev的成員,並創建cdev和file_operations之間關聯起來  struct cdev *cdev_alloc(void);//動態申請(構造)cdev內存(設備對象) void cdev_put(struct cdev *p);//釋放cdev內存 int cdev_add(struct cdev *, dev_t, unsigned);//註冊cdev設備對象(添加到系統字符設備列表中) void cdev_del(struct cdev *);//將cdev對象從系統中移除(註銷 ) 

 

/////////////////////////////////////////////////////////切割線//////////////////////////////////////////////////////////////////////////////

咱們增長一個測試

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


int main(int argc, const char *argv[]) { int fd; int val = 1; fd = open("/dev/xyz", O_RDWR); if (fd < 0) { printf("can't open!\n"); return -1; } else { printf("open success.\n"); } getchar(); close(fd); return 0; }

 

root@lin-virtual-machine:/home/lin/demo# gcc -o demodrvtest demodrvtest.c
root@lin-virtual-machine:/home/lin/demo# ls
demo~    demodrvtest    demo.mod.c  Makefile~       Untitled Document~
demo.c   demodrvtest.c  demo.mod.o  modules.order
demo.c~  demo.ko        demo.o      Module.symvers

 

root@lin-virtual-machine:/home/lin/demo# pwd /home/lin/demo root@lin-virtual-machine:/home/lin/demo# ./demodrvtest can't open!
root@lin-virtual-machine:/home/lin/demo# mknod /dev/xyz c 250 0 root@lin-virtual-machine:/home/lin/demo# ./demodrvtest open success.

 

這邊使用手動來建立

手動建立設備 mknod命令

命令的格式是:mknod  設備名   設備類型(字符:c,塊:b)  主設備號 從設備號

相關文章
相關標籤/搜索