/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. AutoIt 函数学习之----WinWaitActive

    WinWaitActive函数 暂停脚本的执行直至指定窗口被激活(成为活动状态)为止. WinWaitActive ( "窗口标题"[, "窗口文本"[, 超时 ...

  2. Python 正则表达式应用【转载】

    将从正则表达式开始讲Python的标准库.正则表达式是文字处理中常用的工具,而且不需要额外的系统知识或经验.我们会把系统相关的包放在后面讲解. 正则表达式(regular expression)主要功 ...

  3. SQL Server MySQL 中的 in 与 null

    例子: create table t(x int,y int); insert into t(x,y) values(1,1),(2,2),(null,null); 查询一: select x,y f ...

  4. IIS应用程序池监控

    最近发现公司运行的web网站应用程序池会突然停止,做的负载均衡(路由负载)又无法监测到IIS应用程序池的情况,就想着通过某一种监控方式监测IIS应用程序池的情况,如果处关闭状态则立刻重新启动.所说的I ...

  5. 信号和槽有一个非常精炼的C++实现,作者是Sarah Thompson,该实现只有一个头文件sigslot.h,跨平台且线程安全

    关于信号和槽有一个非常精炼的C++实现,作者是Sarah Thompson,该实现只有一个头文件sigslot.h,跨平台且线程安全. 源码在:http://sigslot.cvs.sourcefor ...

  6. 再来一个学历重要性讨论——QQ技术群聊

    ----------------------------------------------------------------------- 正方:学历重要 大专,刚毕业那会太坑爹了.太受学历限制. ...

  7. Java学习疑惑(8)----可视化编程, 对Java中事件驱动模型的理解

    我们编写程序就是为了方便用户使用, 我觉得UI设计的核心就是简洁, 操作过于繁琐的程序让很大一部分用户敬而远之. 即使功能强大, 但是人们更愿意使用易于操作的软件. 近年流行起来的操作手势和逐渐趋于成 ...

  8. 分析java中clone()方法 (转载+修改)

    Java中的clone() 方法 java所有的类都是从java.lang.Object类继承而来的,而Object类提供下面的方法对对象进行复制. protected native Object c ...

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

    通过前面的操作,我们已经可以创建一个带有我们自己的PCI的watchdog外设qemu 虚拟机了. 目的: 1. 了解我们的外设情况. 2. 为在guest中开发我们自己的linux PCI驱动程序做 ...

  10. HDU 3641 Treasure Hunting(阶乘素因子分解+二分)

    题目链接:pid=3641">传送门 题意: 求最小的 ( x! ) = 0 mod (a1^b1*a2^b2...an^bn) 分析: 首先吧a1~an进行素因子分解,然后统计下每一 ...