/sys和 /dev的疑问

1、/dev 下放的是设备文件,是由应用层mknod创建的文件。假设底层驱动对mknod的设备号有相应的驱动,如open等函数。那么应用层open “/dev/**”时,就会调用究竟层的驱动。说白了,/dev下放的是内核和应用层交互的文件,让应用层去open,write,poll等。

2、/sys 是个文件系统,你写内核代码时,假设有调用kobj_init等函数,就会在/sys下的相应文件夹生成相应文件。 它的作用是将内核注冊的设备、驱动、BUS连成一个树形结构。

另外,应用层也能够通过读写/sys下的文件和内核进行交互(ktype)。 说白了/sys就是一个树形结构。让你明确内核都有哪些驱动和设备已经bus。方便电源管理。

3、http://blog.csdn.net/eliot_shao/article/details/13019389

在篇博客里《图解linux设备模型》中,对udev和sysfs的关系做了更具体的说明。

sysfs底层操作

1、kobject结构

一提到kobject非常多人就不想看了。千篇一律。可是使用这个结构,我们能够建立设备驱动模型,所以必须明确。开发驱动程序对我来说,也就是建几个文件夹,创几个属性文件。内核的设备驱动架构已经打好了,调几个函数来用就能够了。在sysfs文件系统里,kobject相应文件夹。属性(attribute)相应文件。

struct kobject {
const char * k_name;
char name[KOBJ_NAME_LEN];
struct kref kref;
struct list_head entry;
struct kobject * parent;
struct kset * kset;
struct kobj_type * ktype;
struct sysfs_dirent * sd;
wait_queue_head_t poll;
};

kobject内容包括文件夹的名字。parent上层文件夹,假设parent=NULL就在/sys以下创建文件夹。ktype可理解为这个文件夹的属性。

struct kobj_type {
void (*release)(struct kobject *);
struct sysfs_ops * sysfs_ops;
struct attribute ** default_attrs;
};
struct sysfs_ops {
ssize_t (*show)(struct kobject *, struct attribute *,char *);//读方法
ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);//写方法
};
struct attribute {
const char * name;
struct module * owner;
mode_t mode;
};//属性文件的名字。模式,仅仅读设为S_IRUGO,可写设为S_IWUSR

2、方法(operations)

想一想在文件系统上能干什么呢?无非是创建文件夹(kobject),创建文件(属性)。

    // kobject初始化函数
void kobject_init(struct kobject * kobj);
// 设置指定kobject的名称
int kobject_set_name(struct kobject *kobj, const char *format, ...);
// 将kobj 对象的引用计数加,同一时候返回该对象的指针
struct kobject *kobject_get(struct kobject *kobj);
// 将kobj对象的引用计数减,假设引用计数降为。则调用kobject release()释放该kobject对象
void kobject_put(struct kobject * kobj);
// 将kobj对象添加Linux设备层次。 挂接该kobject对象到kset的list链中,添加父文件夹各级kobject的引// 用计数,在其parent指向的文件夹下创建文件节点,并启动该类型内核对象的hotplug函数
int kobject_add(struct kobject * kobj);
// kobject注冊函数,调用kobject init()初始化kobj,再调用kobject_add()完毕该内核对象的注冊
int kobject_register(struct kobject * kobj);
// 从Linux设备层次(hierarchy)中删除kobj对象
void kobject_del(struct kobject * kobj);
// kobject注销函数. 与kobject register()相反。它首先调用kobject del从设备层次中删除该对象。再调// 用kobject put()降低该对象的引用计数,假设引用计数降为,则释放kobject对象
void kobject_unregister(struct kobject * kobj);

设备模型上层容器

这里说的上层容器指的是总线类型(bus_type)、设备(device)和驱动(device_driver)。LDD3里面举过一个例如。把kobject当成一个基类,总线类型、设备、驱动和kobject都是继承关系。这些上层的容器自然具备了sysfs的操作方法!

总线类型一般不须要我们创建了。内核支持大多数总线类型(pci。usb,iic…),还包括了虚拟总线类型(platform_bus),所以这里就不涉及怎样创建总线,怎样建立总线的属性文件云云。

1. 设备 device

设备的操作可简单理解为1、注冊设备;2、创建设备属性文件。

通常的注冊和注销函数:

int device_register(struct device *dev);

void device_unregister(struct device *dev);

设备的注冊和注销包括了对底层的sysfs的操作。诸如kobject_init。kobject_add…

创建属性

struct device_attribute {
struct attribute attr;
ssize_t (*show)(struct device *dev, char *buf);
ssize_t (*store)(struct device *dev, const char *buf,
size_t count);
};

这些属性结构可在编译时建立, 使用这些宏:

DEVICE_ATTR(name, mode, show, store);

结果结构通过前缀 dev_attr_ 到给定名子上来命名. 属性文件的实际管理使用通常的函数对来处理:

int device_create_file(struct device *device, struct device_attribute *entry);

void device_remove_file(struct device *dev, struct device_attribute *attr);

2. 驱动 driver

驱动的操作可简单理解为1、注冊驱动;2、创建驱动属性文件。

通常的注冊和注销函数:

int driver_register(struct device_driver *drv);

void driver_unregister(struct device_driver *drv);

设备的注冊和注销包括了对底层的sysfs的操作,诸如kobject_init,kobject_add…

创建属性

DRIVER_ATTR(name, mode, show, store);

int driver_create_file(struct device_driver *drv, struct driver_attribute *attr);

void driver_remove_file(struct device_driver *drv, struct driver_attribute *attr);

摘一段驱动代码来讲讲

#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/pci.h>
#include <linux/input.h>
#include <linux/platform_device.h> struct input_dev *vms_input_dev; /* Representation of an input device */
static struct platform_device *vms_dev; /* Device structure */ /* Sysfs method to input simulated
coordinates to the virtual
mouse driver */
static ssize_t
write_vms(struct device *dev,
struct device_attribute *attr,
const char *buffer, size_t count)
{
int x,y;
sscanf(buffer, "%d%d", &x, &y);
/* Report relative coordinates via the
event interface */
input_report_rel(vms_input_dev, REL_X, x);
input_report_rel(vms_input_dev, REL_Y, y);
input_sync(vms_input_dev);
return count;
}
/* Attach the sysfs write method */
DEVICE_ATTR(coordinates, 0644, NULL, write_vms);
/* Attribute Descriptor */
static struct attribute *vms_attrs[] = {
&dev_attr_coordinates.attr,
NULL
};
/* Attribute group */
static struct attribute_group vms_attr_group = {
.attrs = vms_attrs,
};
/* Driver Initialization */
int __init
vms_init(void)
{
/* Register a platform device */
vms_dev = platform_device_register_simple("vms", -1, NULL, 0);
if (IS_ERR(vms_dev)) {
PTR_ERR(vms_dev);
printk("vms_init: error\n");
}
/* Create a sysfs node to read simulated coordinates */
sysfs_create_group(&vms_dev->dev.kobj, &vms_attr_group);
/* Allocate an input device data structure */
vms_input_dev = input_allocate_device();
if (!vms_input_dev) {
printk("Bad input_alloc_device()\n");
}
/* Announce that the virtual mouse will generate
relative coordinates */
set_bit(EV_REL, vms_input_dev->evbit);
set_bit(REL_X, vms_input_dev->relbit);
set_bit(REL_Y, vms_input_dev->relbit); /* Register with the input subsystem */
input_register_device(vms_input_dev);
printk("Virtual Mouse Driver Initialized.\n");
return 0;
}
/* Driver Exit */
void
vms_cleanup(void)
{
/* Unregister from the input subsystem */
input_unregister_device(vms_input_dev);
/* Cleanup sysfs node */
sysfs_remove_group(&vms_dev->dev.kobj, &vms_attr_group);
/* Unregister driver */
platform_device_unregister(vms_dev);
return;
} module_init(vms_init);
module_exit(vms_cleanup);

这是从《Essential Linux Device Drivers》第七章输入设备摘的代码,实现从虚拟鼠标读取数据坐标上报的功能。

这里使用了总线platform_bus。

vms_dev = platform_device_register_simple(“vms”, -1, NULL, 0);注冊设备到总线;

sysfs_create_group(&vms_dev->dev.kobj, &vms_attr_group);创建属性文件。在linux/sysfs.h中引用,相似于sysfs_create_file。

input_register_device(vms_input_dev);注冊设备文件到input子系统,具体细节參考源代码;

总的来说,就是干了两件事,创建文件夹对象和创建属性,然后加到设备模型中。建立一个资源管理树!

文章仅仅是片面的。宏观的略谈驱动模型。经验不足,仅作參考!

參考资料

http://bbs.csdn.net/topics/380166008

http://blog.csdn.net/xiahouzuoxin/article/details/8943863

The Linux device model的更多相关文章

  1. linux device model简述

    参考: 1)<LINUX设备驱动程序>第十四章 Linux 设备模型 2)内核源码2.6.38 内核初始化的时候会对设备模型作初始化,见init/main.c: start_kernel- ...

  2. The Linux usage model for device tree data

    Linux and the Device Tree The Linux usage model for device tree data Author: Grant Likely grant.like ...

  3. Linux Device Driver && Device File

    catalog . 设备驱动程序简介 . I/O体系结构 . 访问设备 . 与文件系统关联 . 字符设备操作 . 块设备操作 . 资源分配 . 总线系统 1. 设备驱动程序简介 设备驱动程序是内核的关 ...

  4. Linux device tree 简要笔记

    第一.DTS简介     在嵌入式设备上,可能有不同的主板---它们之间差异表现在主板资源不尽相同,比如I2C.SPI.GPIO等接口定义有差别,或者是Timer不同,等等.于是这就产生了BSP的一个 ...

  5. linux device tree源代码解析--转

    //Based on Linux v3.14 source code Linux设备树机制(Device Tree) 一.描述 ARM Device Tree起源于OpenFirmware (OF), ...

  6. How to learn linux device driver

    To learn device driver development, like any other new knowledge, the bestapproach for me is to lear ...

  7. linux device driver —— 环形缓冲区的实现

    还是没有接触到怎么控制硬件,但是在书里看到了一个挺巧妙的环形缓冲区实现. 此环形缓冲区实际为一个大小为bufsize的一维数组,有一个rp的读指针,一个wp的写指针. 在数据满时写进程会等待读进程读取 ...

  8. 《Linux Device Drivers》第十四章 Linux 设备型号

    基本介绍 2.6内核设备模型来提供的抽象叙述性描述的一般系统的结构,为了支持各种不同的任务 电源管理和系统关机 用户空间与通信 热插拔设备 设备类型 kobject.kset和子系统 kobject是 ...

  9. xen 保存快照的实现之 —— device model 状态保存

    xen 保存快照的实现之 —— device model 状态保存 实现要点: 设备状态保存在 /var/lib/xen/qemu-save.x 文件这个文件由 qemu-dm 产生,也由 qemu- ...

随机推荐

  1. [虚拟化/云][全栈demo] 为qemu增加一个PCI的watchdog外设(六)

    目的: 1. 为我们自己的watchdog写一个驱动 步骤: 通过之前的介绍,我们很容易猜想到写我们基于PCI的watchdog驱动,可以分2个步骤. 1. 探测加载PCI设备 这部分代码跟我们的设备 ...

  2. [虚拟化/云][全栈demo] 为qemu增加一个PCI的watchdog外设(三)

    我们已经设计了一个基于qemu的watchdog了.下一步工作就是创建一个含有我们的watchdog的虚拟计算机器了. 准备工作: 1. 使用virt-manager或者virsh创建一个虚拟机器. ...

  3. 新iPhone开售现场:土豪金火了

    今日苹果在全球范围内开始正式发售iPhone 5s与5c手机.在中国王府井苹果零售店,首位购机者李先生在今早4点50分便在此等候. 现场未发现黄牛 本次苹果在中国大陆的自有零售店渠道首批iPhone ...

  4. 安装python模块

    要想在python中使用import的一些模块,前提是要安装这些模块. 可以使用pip来导入模块. 打开终端,输入命令: sudo easy_install pip 安装好pip后,就可以使用pip来 ...

  5. android 抽屉式滑动demo

    下载地址:https://github.com/asijack/AndroidDrawerDemo 直接上效果图如下: 是不是还不错的样子. 先看看布局文件吧 <android.support. ...

  6. 如何学习.Net的步骤

    如果你已经有较多的面向对象开发经验,跳过以下这两步:   第一步 掌握一门.NET面向对象语言,C#或VB.NET 我强烈反对在没系统学过一门面向对象(OO)语言的前提下去学ASP.NET. ASP. ...

  7. javascript中数组循环的方式

    forEach循环:        arr1.forEach(function(value,i)//value 值 i 下标            {console.log([value,i])}); ...

  8. 【译】html5游戏入门

    [译]html5游戏入门 原文链接 简介 如果你想用canvas做个游戏,那么来对地方了. 但是但是你至少知道javascript怎么拼写(╯‵□′)╯︵┻━┻ 既然没问题,那先来玩一下或者下载 创建 ...

  9. 桦仔 笔记7-徐 SQLSERVER日志记录机制

    1 --SQLSERVER日志记录机制 2 --日志记录事务发生的时间,但是不保证记录下发起这个事务的用户名,更不记录发起者的程序名称!!! 3 USE AdventureWorks 4 CREATE ...

  10. Mvc--Html.ActionLink()用法

    },new{ target="_blank"})会生成 <a href="Products/Detail/1" target="_blank&q ...