简介
操作系统将虚拟内存分为内核空间和用户空间。内核空间严格保留用于运行内核,内核扩展和大多数设备驱动程序。相反,用户空间是所有用户模式应用程序都在其中工作的存储区,并且可以在必要时将该存储区换出。
在用户空间和内核空间之间进行通信的方法有很多
在这里我们讨论Sysfs
Sysfs是内核导出的虚拟文件系统,类似于。Sysfs中的文件包含有关设备和驱动程序的信息。Sysfs中的某些文件甚至是可写的,用于配置和控制连接到系统的设备。Sysfs始终安装在上 。 /proc``/sys
Sysfs是将系统信息从内核空间导出到特定设备的用户空间的常用方法。sysfs与内核的设备驱动程序模型绑定在一起。procfs用于导出特定于进程的信息,而debugfs用于由开发人员导出调试信息。
在了解Sysfs,我们需要先来了解Kernel Objects.
Kernel Objects
Sysfs的核心模块是kobject, 你可以将kobject看作绑定内核和Sysfs之间的胶水。
# include/linux/kobject.hstruct kobject {const char *name;struct list_head entry;struct kobject *parent;struct kset *kset;struct kobj_type *ktype;struct kernfs_node *sd; /* sysfs directory entry */struct kref kref;...}struct kobject|– name (Name of the kobject. Current kobject is created with this name in sysfs.)|– parent (This is kobject’s parent. When we create a directory in sysfs for current kobject, it will create under this parent directory)|– ktype (the type associated with a kobject)|– kset (a group of kobjects all of which are embedded in structures of the same type)|– sd (points to a sysfs_dirent structure that represents this kobject in sysfs.)|– kref (provides reference counting)
创建以及使用sysfs
/sys中创建目录创建sysfs文件
如果传递struct kobject * kobject_create_and_add ( const char * name, struct kobject * parent);
kernel_kobj给第二个参数,它将在/ sys / kernel /下创建目录。如果传递firmware_kobj第二个参数,它将在/ sys / firmware /下创建目录。如果传递fs_kobj给第二个参数,它将在下创建目录**/sys/fs/**。如果传递NULL给第二个参数,它将在/ sys /下创建目录。该函数动态创建一个kobject结构,并将其注册到sysfs中。如果无法创建kobject,则将返回NULL。完成此结构后,调用kobject_put和该结构将在不再使用时动态释放。 ```c struct kobject *kobj_ref;
/Creating a directory in /sys/kernel/ / kobj_ref = kobject_create_and_add(“etx_sysfs”,kernel_kobj); //sys/kernel/etx_sysfs
/Freeing Kobj/ kobject_put(kobj_ref);
<a name="JUDGC"></a>## 创建Sysfs文件<br />上面我们知道了怎么创建sys下的目录。现在我们需要创建sysfs文件了。<br />该文件用于通过sysfs与用户空间和内核空间进行交互。因此,我们可以使用sysfs属性创建sysfs文件。<a name="6kapL"></a>### 创建属性```cstruct kobj_attribute {struct attribute attr;ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr, char *buf);ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count);};
我们可以使用__ATTR 宏定义来创建
__ATTR(name, permission, show_ptr, store_ptr);
API
int sysfs_create_file ( struct kobject * kobj, const struct attribute * attr);void sysfs_remove_file ( struct kobject * kobj, const struct attribute * attr);
代码
#include <linux/kernel.h>#include <linux/init.h>#include <linux/module.h>#include <linux/kdev_t.h>#include <linux/fs.h>#include <linux/cdev.h>#include <linux/device.h>#include <linux/slab.h> //kmalloc()#include <linux/uaccess.h> //copy_to/from_user()#include <linux/sysfs.h>#include <linux/kobject.h>volatile int etx_value = 0;dev_t dev = 0;static struct class *dev_class;static struct cdev etx_cdev;struct kobject *kobj_ref;static int __init etx_driver_init(void);static void __exit etx_driver_exit(void);/*************** Driver Fuctions **********************/static int etx_open(struct inode *inode, struct file *file);static int etx_release(struct inode *inode, struct file *file);static ssize_t etx_read(struct file *filp,char __user *buf, size_t len, loff_t *off);static ssize_t etx_write(struct file *filp,const char *buf, size_t len, loff_t *off);/*************** Sysfs Fuctions **********************/static ssize_t sysfs_show(struct kobject *kobj,struct kobj_attribute *attr, char *buf);static ssize_t sysfs_store(struct kobject *kobj,struct kobj_attribute *attr, const char *buf, size_t count);struct kobj_attribute etx_attr = __ATTR(etx_value, 0660, sysfs_show, sysfs_store);static struct file_operations fops ={.owner = THIS_MODULE,.read = etx_read,.write = etx_write,.open = etx_open,.release = etx_release,};static ssize_t sysfs_show(struct kobject *kobj,struct kobj_attribute *attr, char *buf){printk(KERN_INFO "Sysfs - Read!!!\n");return sprintf(buf, "%d\n", etx_value);}static ssize_t sysfs_store(struct kobject *kobj,struct kobj_attribute *attr, const char *buf, size_t count){printk(KERN_INFO "Sysfs - Write!!!\n");sscanf(buf, "%d\n", &etx_value);return count;}static int etx_open(struct inode *inode, struct file *file){printk(KERN_INFO "Device File Opened...!!!\n");return 0;}static int etx_release(struct inode *inode, struct file *file){printk(KERN_INFO "Device File Closed...!!!\n");return 0;}static ssize_t etx_read(struct file *filp,char __user *buf, size_t len, loff_t *off){printk(KERN_INFO "Read function\n");return 0;}static ssize_t etx_write(struct file *filp,const char __user *buf, size_t len, loff_t *off){printk(KERN_INFO "Write Function\n");return 0;}static int __init etx_driver_init(void){/*Allocating Major number*/if ((alloc_chrdev_region(&dev, 0, 1, "etx_Dev")) < 0){printk(KERN_INFO "Cannot allocate major number\n");return -1;}printk(KERN_INFO "Major = %d Minor = %d \n", MAJOR(dev), MINOR(dev));/*Creating cdev structure*/cdev_init(&etx_cdev, &fops);/*Adding character device to the system*/if ((cdev_add(&etx_cdev, dev, 1)) < 0){printk(KERN_INFO "Cannot add the device to the system\n");goto r_class;}/*Creating struct class*/if ((dev_class = class_create(THIS_MODULE, "etx_class")) == NULL){printk(KERN_INFO "Cannot create the struct class\n");goto r_class;}/*Creating device*/if ((device_create(dev_class, NULL, dev, NULL, "etx_device")) == NULL){printk(KERN_INFO "Cannot create the Device 1\n");goto r_device;}/*Creating a directory in /sys/kernel/ */kobj_ref = kobject_create_and_add("etx_sysfs", kernel_kobj);/*Creating sysfs file for etx_value*/if (sysfs_create_file(kobj_ref, &etx_attr.attr)){printk(KERN_INFO "Cannot create sysfs file......\n");goto r_sysfs;}printk(KERN_INFO "Device Driver Insert...Done!!!\n");return 0;r_sysfs:kobject_put(kobj_ref);sysfs_remove_file(kernel_kobj, &etx_attr.attr);r_device:class_destroy(dev_class);r_class:unregister_chrdev_region(dev, 1);cdev_del(&etx_cdev);return -1;}void __exit etx_driver_exit(void){kobject_put(kobj_ref);sysfs_remove_file(kernel_kobj, &etx_attr.attr);device_destroy(dev_class, dev);class_destroy(dev_class);cdev_del(&etx_cdev);unregister_chrdev_region(dev, 1);printk(KERN_INFO "Device Driver Remove...Done!!!\n");}module_init(etx_driver_init);module_exit(etx_driver_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("zhouchengzhu <1073355312@qq.com>");MODULE_DESCRIPTION("A Sample Sysfs Demo");MODULE_VERSION("2:1.0");
