今天看啥
    热点:

      天发国际娱乐官网:  想在工地撑起一片天吗?建城学院欢迎你!  欢迎环境学院2016级鲜花鲜肉:等你们来环院,还原出一个碧水蓝天  政府管理学院2016迎新:道器相济胸怀天下,政管齐修志存高远。

      linux driver power,linuxdriver


      p { margin-bottom: 0.08in; }

      static int __init pm_init( void )

      {

      power_kobj = kobject_create_and_add( "power" , NULL);

      if (!power_kobj)

      return -ENOMEM;

      return sysfs_create_group(power_kobj, &attr_group);

      }


      core_initcall(pm_init);


      static struct attribute_group attr_group = {

      .attrs = g,

      };


      static struct attribute * g[] = {

      &state_attr. attr , // 提供 给上面的一个接口

      #ifdef CONFIG_PM_TRACE

      &pm_trace_attr.attr,

      #endif

      #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PM_DEBUG)

      &pm_test_attr.attr, //

      #endif

      NULL,

      };

      cat /sys/power 下就会显示 disk image_size pm_test pm_trace resume state

      state 下面就会显示 mem,disk 这两种状态

      cat /pm_trace 下面就会显示 1 或者 0

      state 下面 mem,disk 的显示 是在以下函数功能实现的

      static ssize_t state_show ( struct kobject *kobj, struct kobj_attribute *attr,

      char *buf)

      {

      char *s = buf;

      #ifdef CONFIG_SUSPEND

      int i;


      for (i = 0; i < PM_SUSPEND_MAX; i++) {

      if (pm_states[i] && valid_state(i))

      s += sprintf(s, "%s " , pm_states[i]);

      }

      #endif

      #ifdef CONFIG_HIBERNATION

      s += sprintf(s, "%s/n" , "disk" );

      #else

      if (s != buf)

      /* convert the last space to a newline */

      *(s-1) = '/n' ;

      #endif

      return (s - buf);

      }

      state 下面的更改 是在以下函数功能实现的

      static ssize_t state_store ( struct kobject *kobj, struct kobj_attribute *attr,

      const char *buf, size_t n)

      {

      #ifdef CONFIG_SUSPEND

      suspend_state_t state = PM_SUSPEND_STANDBY;

      const char * const *s;

      #endif

      char *p;

      int len;

      int error = -EINVAL;


      p = memchr(buf, '/n' , n);

      len = p ? p - buf : n;


      /* First, check if we are requested to hibernate */

      if (len == 4 && !strncmp(buf, "disk" , len)) { // 这里检测是进入硬盘还是 mm, 由于 6410 没有使用 disk ,所以就进入没有

      error = hibernate();

      goto Exit;

      }


      pm_trace 下面就会显示 1 或者 0 ,是在以下函数功能实现的

      static ssize_t pm_trace_show( struct kobject *kobj, struct kobj_attribute *attr,

      char *buf)

      {

      return sprintf(buf, "%d/n" , pm_trace_enabled);

      }

      pm_trace 状态的更改,是在以下函数功能实现的

      pm_trace_store( struct kobject *kobj, struct kobj_attribute *attr,

      const char *buf, size_t n)

      {

      int val;


      if (sscanf(buf, "%d" , &val) == 1) {

      pm_trace_enabled = !!val;

      return n;

      }

      return -EINVAL;

      }



      # echo mem > /sys/power/state


      1. 驱动在收到这个数据时就调用 state_store 函数来处理输入的状态,函数首先检查是否进

      Hibernation 状态;如果 Hibernation 状态,那么就会调用 hibernate() 函数进入

      Hibernation 状态,如果不是就找到要进入的状态,并调用 suspend enter_state 函数进

      suspend 状态。我们看到在驱动的实现上把 Suspend Hibernation 区分开了。因此

      Linux PM Suspend State 就有两个, standby mem 。注意这里没有 on ,因此你不能

      通过发送 on 命来到 /sys/power/state 或其他内核接口函数来唤醒系统,因为这是针对服务

      /PC 的,只能通过按键的方式(大多数的 PC/ 笔记本都提供了 Suspend 键,也可能就是

      Power 键)。

      suspend_state_t state = PM_SUSPEND_STANDBY;

      if (len == 4 && !strncmp(buf, "disk", len)) {

      error = hibernate();

      }

      if (state < PM_SUSPEND_MAX && *s)

      error = enter_state(state);


      enter_state suspend.c 里定义的接口函数,用来使系统进入指定的 suspend 状态。好了,

      剩下的事情就交给 Suspend 系统来处理了。

      2. 接下来调用会调用到 linux /kernel/power/mani.c 中的 enter_stare();

      enter_state() 函数会进入和退出 suspend 状态时的一些常规处理,其过程是:

      1). 调用 sys_sync();

      同步文件系统以保证所有的数据都写到了存储设备上而不会因为 suspend 而丢失数据

      2). 调用 suspend_prepare();

      当进入到 suspend_prepare() 中以后,它使用 pm_prepare_console() 函数给 suspend

      分配一个虚拟终端来输出信息 , 然后调用 pm_notifier_call_chain(PM_SUNPEND_PREPARE)

      广播 一个系统要进入 suspend notify, 使用 usermodehelper_disable() 用户态的 helper , 调用 suspend_freeze_processes() 结所有的用户进 , 在这里也会

      存当前进程的所有状态 .

      3). 调用 suspend_devices_and_enter(state); 进入指定的 suspend 状态 ; 调用 device_suspend(

      PMSG_SUSPEND); 跳到 linux/kernel/drivers/base/power/mani.c 中的 device_suspend(); 会调

      dpm_prepare(); 然后再调用 dpm_suspend(); 调用 disable_noboot_cpus() 关闭非启动

      cpu. 通过调用 suspend_device();

      4). 接下来 suspend_enter() 会被调用, arch_suspend_disabled(); 然后

      device_power_down(PMSG_SUSPEND); 会调用 suspend_device_noirq(); 最后调用

      sysdev_suspend()

      5).supend_ops->enter 来使 cpu 进入到 sleep 式;

      在内核中的 /driver/base/core.c 中的 struct device 中的成员是在 /include/linux/device.h

      struct device {

      struct klist klist_children ;

      struct klist_node knode_parent ; /* node in sibling list */

      struct klist_node knode_driver ;

      struct klist_node knode_bus ;

      struct device * parent ;


      struct kobject kobj ;

      char bus_id [BUS_ID_SIZE]; /* position on parent bus */

      const char * init_name ; /* initial name of the device */

      struct device_type * type ;

      unsigned uevent_suppress :1;


      struct semaphore sem ; /* semaphore to synchronize calls to

      * its driver.

      */


      struct bus_type * bus ; /* type of bus device is on */

      struct device_driver * driver ; /* which driver has allocated this

      device */

      void * driver_data ; /* data private to the driver */

      void * platform_data ; /* Platform specific data, device

      core doesn't touch it */

      struct dev_pm_info power ; 这个很重要进入它的结构可以看到如下信息:


      /include/linux/pm.h 中可以看到 如下 : enum dpm_state {

      DPM_INVALID ,

      DPM_ON ,

      DPM_PREPARING ,

      DPM_RESUMING ,

      DPM_SUSPENDING ,

      DPM_OFF ,

      DPM_OFF_IRQ ,

      };


      struct dev_pm_info {

      pm_message_t power_state ;

      unsigned can_wakeup :1;

      unsigned should_wakeup :1;

      enum dpm_state status ; /* Owned by the PM core */

      #ifdef CONFIG_PM_SLEEP

      struct list_head entry;

      #endif

      };

      www.1click-soft.comtrue/article/20180111/207457.htmlTechArticlelinux driver power,linuxdriver p { margin-bottom: 0.08in; } static int __init pm_init( void ) { power_kobj= kobject_create_and_add( power ,NULL); if (!power_kobj) return -ENOMEM; return sysfs_create_group(power_kobj, attr_group); } core_i...

      相关文章

        暂无相关文章

      帮客评论

      视觉看点
      百度 360 搜狗