漫谈android系统硬件抽象层kernel分析

Posted AlexKingWang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了漫谈android系统硬件抽象层kernel分析相关的知识,希望对你有一定的参考价值。

前言

最近在拜读罗升阳的《android系统源代码情景分析》一书,相信有许多搞android系统的人会去看看本书,那么针对于第二章的硬件抽象层,联系一下实际的工作,有必要将自己学习的东西做一个总结分析。当然这部分将依据老罗的书的思路一一揭开硬件抽象层的面纱。

文件系统接口

一般kernel层会给用户层暴露相关的接口供用户空间去使用。大致上可以被分为三类。

  • proc文件系统接口
  • 传统设备文件系统接口
  • devfs文件系统接口

其中proc文件系统接口与传统设备文件系统接口一脉相承,它们和起来才能做一个较为完善的文件系统接口。

proc文件系统接口与传统设备文件系统接口

它是由传统设备文件操作方法与传统设备文件操作方法表fops组成。老罗一书中用了freg.c这个文件来做解释的,但实际真正在使用过程中还需大家自己去体悟。

在这里将通过我自己写的charger接口作为例子进行分析。

看到static int smbchg_probe(struct spmi_device *spmi)函数,会让其直接调用create函数来创建一个文件系统接口。

create_batt_voltage_proc_file();

然后看这个函数的定义

void static create_batt_voltage_proc_file(void)
{
    batt_voltage_proc_file = proc_create(batt_voltage_PROC_FILE, 0644, NULL, &batt_voltage_fops);

    if (batt_voltage_proc_file) {
        printk("[Proc]%s sucessed!\\n", __FUNCTION__);
    } else{
        printk("[Proc]%s failed!\\n", __FUNCTION__);
    }
}

可以看到,其主要工作是将fops挂载上去。按图索骥。

#define batt_voltage_PROC_FILE  "batt_voltage_now"
static const struct file_operations batt_voltage_fops = {
    .owner = THIS_MODULE,
    .open = batt_voltage_proc_open,
    .read = seq_read,
    .release = single_release,
};

fops已经出现了,其实他会挂在载/porc/batt_voltage_now,这都得归功于函数proc_create(batt_voltage_PROC_FILE, 0644, NULL, &batt_voltage_fops);当然在这里没有看到

下面看open。

static int batt_voltage_proc_open(struct inode *inode, struct  file *file)
{
    return single_open(file, batt_voltage_proc_read, NULL);
}

其主要就是为了回调single_open(file, batt_voltage_proc_read, NULL);中的batt_voltage_proc_read。

static int batt_voltage_proc_read(struct seq_file *buf, void *v)
{
    int ret = -1;
    struct power_supply *psy;
    union power_supply_propval val;
    int voltage_now=0;

    psy = get_psy_battery();
    ret = psy->get_property(psy, POWER_SUPPLY_PROP_VOLTAGE_NOW, &val);
    if (!ret) {
        voltage_now = val.intval / 1000;
        seq_printf(buf, "%d\\n", voltage_now);
    } else{
        printk("%s: can't get voltage_now, ret = %d!\\n", __FUNCTION__, ret);
        voltage_now = ret;
    }

    return 0;
}

这样就可以看到这个函数的主要功能就是将电压值除以1000后回传给接口。

小结一下:其核心思想就是为了将fops挂载上去。

devfs文件系统接口

我们以hall_sensor为例。

static DEVICE_ATTR(status, 0664, show_action_status, store_action_status);
static struct attribute *hall_sensor_attrs[] = {
    &dev_attr_status.attr,
    NULL
};

static struct attribute_group hall_sensor_group = {
    .name = "hall_sensor",
    .attrs = hall_sensor_attrs
};

这段code已经清晰显示需要架设的东西了。通过DEVICE_ATTR去建立devfs文件系统。并提供相关的操作节点show_action_status, store_action_status。

/*===========================
 *|| sysfs DEVICE_ATTR part ||
 *===========================
 *
 */
static ssize_t show_action_status(struct device *dev,struct device_attribute *attr, char *buf)
{
    if(!hall_sensor_dev)
        return sprintf(buf, "Hall sensor does not exist!\\n");
    return sprintf(buf, "%d\\n",hall_sensor_dev->status);
}
static ssize_t store_action_status(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
    int request;
    unsigned long flags;

    //if(!hall_sensor_dev)
       //         return sprintf(buf, "Hall sensor does not exist!\\n");
        sscanf(buf, "%du", &request);

        spin_lock_irqsave(&hall_sensor_dev->mHallSensorLock, flags);
            if (!request)
                    hall_sensor_dev->status = 0;
        else
                hall_sensor_dev->status = 1;
     spin_unlock_irqrestore(&hall_sensor_dev->mHallSensorLock, flags);

        log("[ATTR] status rewite value = %d\\n",!hall_sensor_dev->status);
    return count;
}

在此我不便分析其具体功能。但其思想便是做挂载的动作。

后续

当然在这里我仅仅是将kernel部分的节点方式做了简单介绍,抽空将hardware,framwork层如何工作的补上。

参考博客

proc_create的使用方法

proc_create和create_proc_entry的区别

以上是关于漫谈android系统硬件抽象层kernel分析的主要内容,如果未能解决你的问题,请参考以下文章

Android图形显示之硬件抽象层Gralloc

分析系统体系结构: 自下而上分析

Android的硬件抽象层和驱动体系为啥这么弱暴

Android硬件抽象层模块编写规范

Android硬件抽象层(HAL)深入剖析

Android 系统框架简介