雜項設備

雜項設備可以說是對一部分字符設備的封裝,還有一部分不好歸類驅動也歸到雜項設備。

?1為什么會引入雜項設備?

? ? ? ? ?第一、節省主設備號

? ? ? ? ? ? ? ?–如果所有的驅動都是用字符設備,那么所有的設備號很快就用完了,總共就255個主設備號。

? ? ? ? ?第二、驅動寫起來相對簡單

? ? ? ? ? ? ?–如果直接使用封裝好的雜項設備,那么就可以減少一步注冊主設備號的過程

?2雜項設備初始化文件

? ? ? ? 雜項設備初始化部分源文件“drivers/char/ misc.c”,這一部分通過Makefile可知,是強制編譯的。

?3 注冊文件

? ? ? ? include/linux/miscdevice.h 頭文件

? ? ? ? struct miscdevice? {

? ? ? ? ? ? ? ? int minor;?常用的參數,設備號

? ? ? ? ? ? ? ? const char *name;?常用的參數,生成設備節點的名稱

? ? ? ? ? ? ? ? const struct file_operations *fops; ?常用的參數, 指向一個設備節點文件

? ? ? ? ? ? ? ? struct list_head list;

? ? ? ? ? ? ? ? struct device *parent;

? ? ? ? ? ? ? ? struct device *this_device;

? ? ? ? ? ? ? ? const char *nodename;

? ? ? ? ? ? ? ?mode_t mode;

? ? ? ?};


? ? ? ? /*

? ? ? ? * NOTE:

? ? ? ?* all file operations except setlease can be called without

? ? ? ?* the big kernel lock held in all filesystems.

? ? ? */

? ? ? ? /*頭文件 include/linux/fs.h*/

? ? ? struct file_operations {

? ? ? ? ? ? ? ? struct module *owner;?必選的是參數,一般是THIS_MODULE

? ? ? ? ? ? ? ? loff_t (*llseek) (struct file *, loff_t, int);

? ? ? ? ? ? ? ? ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);

? ? ? ? ? ? ? ? ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);

? ? ? ? ? ? ? ? ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);

? ? ? ? ? ? ? ? ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);

? ? ? ? ? ? ? ?int (*readdir) (struct file *, void *, filldir_t);

? ? ? ? ? ? ? ?unsigned int (*poll) (struct file *, struct poll_table_struct *);

? ? ? ? ? ? ? ? /* remove by cym 20130408 support for MT660.ko */

? ? ? ? ? ? ? ? #if 0

? ? ? ? ? ? ? ? ? ? ? ?//#ifdef CONFIG_SMM6260_MODEM

? ? ? ? ? ? ? ? ? ? ? ?#if 1// liang, Pixtree also need to use ioctl interface...

? ? ? ? ? ? ? ? ? ? ? ? ? int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);

? ? ? ? ? ? ? ? ? ? ?#endif

? ? ? ? ? ? ? ? ?#endif

? ? ? ? ? ? ? ? ?/* end remove */

? ? ? ? ? ? ? ? ? ? ? ? long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);對GPIO的操作,應用向底層驅動傳值

? ? ? ? ? ? ? ? ? ? ? ? long (*compat_ioctl) (struct file *, unsigned int, unsigned long);

? ? ? ? ? ? ? ? ? ? ? ? int (*mmap) (struct file *, struct vm_area_struct *);

? ? ? ? ? ? ? ? ? ? ? ? int (*open) (struct inode *, struct file *);?必選的是參數

? ? ? ? ? ? ? ? ? ? ? ? int (*flush) (struct file *, fl_owner_t id);

? ? ? ? ? ? ? ? ? ? ? ? int (*release) (struct inode *, struct file *);?必選的是參數

? ? ? ? ? ? ? ? ? ? ? ? int (*fsync) (struct file *, int datasync);

? ? ? ? ? ? ? ? ? ? ? ? ?int (*aio_fsync) (struct kiocb *, int datasync);

? ? ? ? ? ? ? ? ? ? ? ? ?int (*fasync) (int, struct file *, int);

? ? ? ? ? ? ? ? ? ? ? ? ?int (*lock) (struct file *, int, struct file_lock *);

? ? ? ? ? ? ? ? ? ? ? ? ?ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);

? ? ? ? ? ? ? ? ? ? ? ? ?unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);

? ? ? ? ? ? ? ? ? ? ? ? ?int (*check_flags)(int);

? ? ? ? ? ? ? ? ? ? ? ? ?int (*flock) (struct file *, int, struct file_lock *);

? ? ? ? ? ? ? ? ? ? ? ? ?ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);

? ? ? ? ? ? ? ? ? ? ? ? ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);

? ? ? ? ? ? ? ? ? ? ? ??int (*setlease)(struct file *, long, struct file_lock **);

? ? ? ? ? ? ? ? ? ? ? ?long (*fallocate)(struct file *file, int mode, loff_t offset, loff_t len);

? ? ? ? ? ? ? ? ? ? ? /* add by cym 20130408 support for MT6260 and Pixtree */

? ? ? ? ? ? ? ? ? ? ?#if defined(CONFIG_SMM6260_MODEM) || defined(CONFIG_USE_GPIO_AS_I2C)

? ? ? ? ? ? ? ? ? ? ? ? ? ? int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);

? ? ? ? ? ? ? ? ? ? #endif

? ? ? ? ? ? ? ? ? /* end add */

? ? ? ? };

4.例子(devicenode_linux_module.c)

? ? ? ? #include

? ? ? ? #include

? ? ? ? /*驅動注冊的頭文件,包含驅動的結構體和注冊和卸載的函數*

? ? ? ? /#include

? ? ? ? /*注冊雜項設備頭文件*/

? ? ? ? #include

? ? ? ? /*注冊設備節點的文件結構體*/

? ? ? ? #include

? ? ? ? #define DRIVER_NAME "hello_ctl"

? ? ? ? #define DEVICE_NAME "hello_ctl123"

? ? ? ? MODULE_LICENSE("Dual BSD/GPL");

? ? ? ? MODULE_AUTHOR("TOPEET");


? ? ? ? /*ioctl*/? ? ? ?

? ? ? ? static long hello_ioctl( struct file *files, unsigned int cmd, unsigned long arg){

? ? ? ? ? ? ? ? printk("cmd is %d,arg is %d\n",cmd,arg);

? ? ? ? ? ? ? ? return 0;

? ? ? ? }

? ? ? ? ? /*close*/

? ? ? ? static int hello_release(struct inode *inode, struct file *file){

? ? ? ? ? ? ? ? printk(KERN_EMERG "hello release\n");

? ? ? ? ? ? ? ? return 0;

? ? ? ? }

? ? ? ? static int hello_open(struct inode *inode, struct file *file){

? ? ? ? ? ? ? ? printk(KERN_EMERG "hello open\n");

? ? ? ? ? ? ? ? return 0;

? ? ? ? }

? ? ? ? static struct file_operations hello_ops = {

? ? ? ? ? ? ? ? .owner = THIS_MODULE,

? ? ? ? ? ? ? ? .open = hello_open,

? ? ? ? ? ? ? ? .release = hello_release,

? ? ? ? ? ? ? ? .unlocked_ioctl = hello_ioctl,

? ? ? ? };

? ? ? ? static? struct miscdevice hello_dev = {

? ? ? ? ? ? ? ? .minor = MISC_DYNAMIC_MINOR,

? ? ? ? ? ? ? ? .name = DEVICE_NAME,

? ? ? ? ? ? ? ? .fops = &hello_ops,

? ? ? ? };

? ? ? ? static int hello_probe(struct platform_device *pdv){

? ? ? ? ? ? ? ? printk(KERN_EMERG "\tprobe initialized\n");?

? ? ? ? ? ? ? ? misc_register(&hello_dev);

? ? ? ? ? ? ? ? return 0;

? ? ? ? }

? ? ? ? static int hello_remove(struct platform_device *pdv){

? ? ? ? ? ? ? ? printk(KERN_EMERG "\tremove\n");

? ? ? ? ? ? ? ? misc_deregister(&hello_dev);

? ? ? ? ? ? ? ? return 0;

? ? ? ? }

? ? ? ? static void hello_shutdown(struct platform_device *pdv){

? ? ? ? ? ? ? ? ;

? ? ? ? }

? ? ? ? static int hello_suspend(struct platform_device *pdv,pm_message_t pmt){

? ? ? ? ? ? ? ?return 0;

? ? ? ? }

? ? ? ? static int hello_resume(struct platform_device *pdv){

? ? ? ? ? ? ? ? return 0;

? ? ? ? }

? ? ? ? struct platform_driver hello_driver = {

? ? ? ? ? ? ? ?.probe = hello_probe,

? ? ? ? ? ? ? .remove = hello_remove,

? ? ? ? ? ? ? ?.shutdown = hello_shutdown,

? ? ? ? ? ? ? ?.suspend = hello_suspend,

? ? ? ? ? ? ? ?.resume = hello_resume,

? ? ? ? ? ? ? ?.driver = {

? ? ? ? ? ? ? ? ? ? ? ?.name = DRIVER_NAME,

? ? ? ? ? ? ? ? ? ? ? ?.owner = THIS_MODULE,

? ? ? ? ? ? ?}

? ? ? ? };

? ? ? ? static int hello_init(void)

? ? ? ? {

? ? ? ? ? ? ? ?printk(KERN_EMERG "HELLO WORLD enter!\n");

? ? ? ? ? ? ? ?int DriverState = platform_driver_register(&hello_driver);?

? ? ? ? ? ? ? ?printk(KERN_EMERG "\tDriverState is %d\n",DriverState);

? ? ? ? ? ? ? ?return 0;

? ? ? ?}

? ? ? ? static void hello_exit(void)

? ? ? ? {

? ? ? ? ? ? ? ? printk(KERN_EMERG "HELLO WORLD exit!\n");

? ? ? ? ? ? ? ?platform_driver_unregister(&hello_driver);

? ? ? ? }

? ? ? ? module_init(hello_init);

? ? ? ? module_exit(hello_exit);

5.Makefile

? ? ? ? #!/bin/bash

? ? ? ?#通知編譯器我們要編譯模塊的哪些源碼

? ? ? ? #這里是編譯devicenode_linux_module.c這個文件編譯成中間文件devicenode_linux_module.o

? ? ? ??obj-m += devicenode_linux_module.o

? ? ? ? #源碼目錄變量,這里用戶需要根據實際情況選擇路徑

? ? ? ? #作者是將Linux的源碼拷貝到目錄/home/topeet/android4.0下并解壓的

? ? ? ??KDIR := /home/topeet/android4.0/iTop4412_Kernel_3.0

? ? ? ? #當前目錄變量

? ? ? ?PWD ?= $(shell pwd)

? ? ? ?#make命名默認尋找第一個目標

? ? ? ?#make -C就是指調用執行的路徑

? ? ? ? #$(KDIR)Linux源碼目錄,作者這里指的是/home/topeet/android4.0/iTop4412_Kernel_3.0

? ? ? ? #$(PWD)當前目錄變量

? ? ? ? #modules要執行的操作

all:

make -C $(KDIR) M=$(PWD) modules

#make clean執行的操作是刪除后綴為o的文件

clean:

rm -rf *.o

6.make,編譯后同驅動注冊一樣

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容