/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. CPU核心数

    Process.ProcessorAffinity 属性: public IntPtr ProcessorAffinity { get; set; }属性值:位掩码,表示关联进程内的线程可以在其上运行 ...

  2. Table的分割线偏移量设置 及其 UIEdgeInset详解

    -(void)viewDidLayoutSubviews { if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)] ...

  3. Perfmon 介绍

    1.UI 1.笔图标,可以把视图里的细线加粗. 2.加号图标.可以为视图添加新的记数器. 3.操作-->属性.可以用于设置默认的采样时间. 2.增加计数据器页面 1.一个计数据器会包涵多个对象. ...

  4. dell PowerEdge R720 自动重启分析

    dell PowerEdge R720 自动重启分析 摘要: 一,问题描述: 在同一批服务器当中,碰到这样一台服务器,如果不跑任何服务时没有问题,但一跑任务就是自动重启.既然同样的系统别的服务器都没出 ...

  5. 九度OnlineJudge之1021:统计字符

    题目描述:     统计一个给定字符串中指定的字符出现的次数. 输入:     测试输入包含若干测试用例,每个测试用例包含2行,第1行为一个长度不超过5的字符串,第2行为一个长度不超过80的字符串.注 ...

  6. MFC上下浮动与渐入渐出消息提示框实现

    类似QQ与360软件,消息提示有两种.上下浮动.渐入渐出. 1.上下浮动提示框实现 机制,定时器响应上下浮动消息. 主要API:MoveWindow. 源码如下UpDownTipDlg.h.UpDow ...

  7. 【转】Loss Function View

    感谢原文作者!原文地址:http://eletva.com/tower/?p=186 一.Loss Function 什么是Loss Function?wiki上有一句解释我觉得很到位,引用一下:Th ...

  8. Eclipse无法识别(手机)设备的解决方案

    遇到问题 开始学习android一个多月了,用Eclipse开发,用android手机调试.之前一直好好的,突然Eclipse无法识别手机设备了.纠结了好久,找了各种解决方法,弄了一晚上终于解决问题了 ...

  9. NPOI 辅助类

    using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; using NPOI.XSSF.UserModel; using System; using S ...

  10. history.js 一个无刷新就可改变浏览器栏地址的插件(不依赖jquery)

    示例: http://browserstate.github.io/history.js/demo/     简介   HTML4有一些对浏览历史的前进后退API的支持如:   window.hist ...