转载地址:https://blog.csdn.net/yuzaipiaofei/article/details/50868407

一:wakeup_source简介:

linux 3.4内核PM使用了wakeup_source来保持唤醒状态,也就是keep awake。之前android一直是基于Linux加入了wake_lock机制来阻止系统休眠,后来Linux 3.4内核加入了wakeup_source来管理,安卓4.4跟着升级内核也就摒弃了自己的繁杂的wake_lock机制,在对上层接口并不改变,在内核wake_lock实现直接基于wakeup_source来实现的。当然也会带来debug上的一些问题,比如以前的wake_lock自身带有强大的debug信息,那么我们在调试的时候可以自己看见dmesg中默认打印active wake lock XXX,很直观来辨别需要休眠的时候那个wake lock有问题阻止了休眠。这个需要我们自己来完善。个人认为改进很大,现在使用了autosleep机制,只要不存在任何active wakeup_source了,系统自动休眠,当有active wake_source自动block住,个人认为休眠更及时,非休眠时间在减少,同时不会消耗额外的资源。使用基于queue work与进程block来管理suspend。还有这里的wakeup_source个人觉得应该叫keepawake_source或者stayawake_souce,毕竟系统的唤醒也就是cpu的再次运行是由中断唤醒的而不是wakeup_source。同时安卓4.4还有一个重大改变就是去除了early suspend机制改为fb event通知机制。那么现在就只有suspend与resume,runtime suspend与runtime resume了。

/** 
 * struct wakeup_source - Representation of wakeup sources 
 * 
 * @total_time: Total time this wakeup source has been active. 
 * @max_time: Maximum time this wakeup source has been continuously active. 
 * @last_time: Monotonic clock when the wakeup source's was touched last time. 
 * @prevent_sleep_time: Total time this source has been preventing autosleep. 
 * @event_count: Number of signaled wakeup events. 
 * @active_count: Number of times the wakeup sorce was activated. 
 * @relax_count: Number of times the wakeup sorce was deactivated. 
 * @expire_count: Number of times the wakeup source's timeout has expired. 
 * @wakeup_count: Number of times the wakeup source might abort suspend. 
 * @active: Status of the wakeup source. 
 * @has_timeout: The wakeup source has been activated with a timeout. 
 */ 
struct wakeup_source { 
    const char         *name; 
    struct list_head    entry; 
    struct list_head    list; 
    spinlock_t        lock; 
    struct timer_list    timer; 
    unsigned long        timer_expires; //超时时间,也就是wake_lock_timeout()里面的时间参数,超时后会执行deactivate函数 
    ktime_t total_time; 
    ktime_t max_time; 
    ktime_t last_time; 
    ktime_t start_prevent_time; 
    ktime_t prevent_sleep_time; 
    unsigned long        event_count; //event计数 
    unsigned long        active_count;//active计数 
    unsigned long        relax_count; 
    unsigned long        expire_count; 
    unsigned long        wakeup_count; 
    bool            active:1; //用于判断是否是active状态 
    bool            autosleep_enabled:1;//这个变量是来标记active等时间的 
};

//active任何wakeup_source都会执行该函数,标记active为true 
/** 
 * wakup_source_activate - Mark given wakeup source as active. 
 * @ws: Wakeup source to handle. 
 * 
 * Update the @ws' statistics and, if @ws has just been activated, notify the PM 
 * core of the event by incrementing the counter of of wakeup events being 
 * processed. 
 */ 
static void wakeup_source_activate(struct wakeup_source *ws) 

    unsigned int cec;

ws->active = true; 
    ws->active_count++; 
    ws->last_time = ktime_get(); 
    if (ws->autosleep_enabled) 
        ws->start_prevent_time = ws->last_time;

/* Increment the counter of events in progress. */ 
    cec = atomic_inc_return(&combined_event_count);

trace_wakeup_source_activate(ws->name, cec); 
}

//deactivate任何wakeup_source都会执行该函数,标记active为false 
/** 
 * wakup_source_deactivate - Mark given wakeup source as inactive. 
 * @ws: Wakeup source to handle. 
 * 
 * Update the @ws' statistics and notify the PM core that the wakeup source has 
 * become inactive by decrementing the counter of wakeup events being processed 
 * and incrementing the counter of registered wakeup events. 
 */ 
static void wakeup_source_deactivate(struct wakeup_source *ws) 

    unsigned int cnt, inpr, cec; 
    ktime_t duration; 
    ktime_t now;

ws->relax_count++; 
    /* 
     * __pm_relax() may be called directly or from a timer function. 
     * If it is called directly right after the timer function has been 
     * started, but before the timer function calls __pm_relax(), it is 
     * possible that __pm_stay_awake() will be called in the meantime and 
     * will set ws->active.  Then, ws->active may be cleared immediately 
     * by the __pm_relax() called from the timer function, but in such a 
     * case ws->relax_count will be different from ws->active_count. 
     */ 
    if (ws->relax_count != ws->active_count) { 
        ws->relax_count--; 
        return; 
    }

ws->active = false;

now = ktime_get(); 
    duration = ktime_sub(now, ws->last_time); 
    ws->total_time = ktime_add(ws->total_time, duration); 
    if (ktime_to_ns(duration) > ktime_to_ns(ws->max_time)) 
        ws->max_time = duration;

ws->last_time = now; 
    del_timer(&ws->timer); 
    ws->timer_expires = 0;

if (ws->autosleep_enabled) 
        update_prevent_sleep_time(ws, now);

/* 
     * Increment the counter of registered wakeup events and decrement the 
     * couter of wakeup events in progress simultaneously. 
     */ 
    cec = atomic_add_return(MAX_IN_PROGRESS, &combined_event_count); 
    trace_wakeup_source_deactivate(ws->name, cec);

split_counters(&cnt, &inpr); 
     
    if (!inpr && waitqueue_active(&wakeup_count_wait_queue)){ 
        wake_up(&wakeup_count_wait_queue); //当不存在任何active wake_up source的时候唤醒try_to_suspend进程。 
    } 
     
}

wakup_source的申请与释放: 
1:使用安卓的wake_lock接口:wake_lock(),wake_lock_timeout(),wake_unlock(); 
2: 使用wakeup_source自带的接口:pm_stay_awake(),pm_relax();这里的name就是device name。

二:autosleep分析: 
sys接口:sys/power/autosleep

static ssize_t autosleep_show(struct kobject *kobj, 
                  struct kobj_attribute *attr, 
                  char *buf) 

    suspend_state_t state = pm_autosleep_state();

if (state == PM_SUSPEND_ON) 
        return sprintf(buf, "off\n");

#ifdef CONFIG_SUSPEND 
    if (state < PM_SUSPEND_MAX) 
        return sprintf(buf, "%s\n", valid_state(state) ? 
                        pm_states[state] : "error"); 
#endif 
#ifdef CONFIG_HIBERNATION 
    return sprintf(buf, "disk\n"); 
#else 
    return sprintf(buf, "error"); 
#endif 
}

static ssize_t autosleep_store(struct kobject *kobj, 
                   struct kobj_attribute *attr, 
                   const char *buf, size_t n) 

    suspend_state_t state = decode_state(buf, n); 
    int error;

if (state == PM_SUSPEND_ON 
        && strcmp(buf, "off") && strcmp(buf, "off\n")) 
        return -EINVAL;

error = pm_autosleep_set_state(state);//睡眠时写入mem state 
    return error ? error : n; 
}

power_attr(autosleep);

int pm_autosleep_set_state(suspend_state_t state) 
{

#ifndef CONFIG_HIBERNATION 
    if (state >= PM_SUSPEND_MAX) 
        return -EINVAL; 
#endif

__pm_stay_awake(autosleep_ws); //防止系统休眠

mutex_lock(&autosleep_lock);

autosleep_state = state;

__pm_relax(autosleep_ws); //释放上面的wake up source

if (state > PM_SUSPEND_ON) { 
        pm_wakep_autosleep_enabled(true); //设置所有wake up source里面的autosleep_enabled为真,这个变量不会对休眠有影响,但是会标记active的时间,使用debugfs可以看见 
        queue_up_suspend_work();//调度工作队列,会执行try_to_suspend(),其实state mem执行try_to_suspend(),一次就可以了,下面分析。 
    } else { 
        pm_wakep_autosleep_enabled(false);//设置所有wake up source里面的autosleep_enabled为假 
    }

mutex_unlock(&autosleep_lock); 
    return 0; 
}

重头戏:try_to_suspend

static void try_to_suspend(struct work_struct *work) 

    unsigned int initial_count, final_count;

if (!pm_get_wakeup_count(&initial_count, true)) //获取initial_count,这个函数会block住,当存在active wakeup source的时候,直到wakeup source为detative状态 
        goto out;

mutex_lock(&autosleep_lock);

if (!pm_save_wakeup_count(initial_count)) {//保存initial_count,不会block,当然也会检查是否有active wakeup source,当有active存在再次queue work。 
        mutex_unlock(&autosleep_lock); 
        goto out; 
    }

if (autosleep_state == PM_SUSPEND_ON) {//当为ON状态时,return。//在睡眠期间跟了很久没有遇见过这种情况 
        mutex_unlock(&autosleep_lock); 
        return; 
    } 
    if (autosleep_state >= PM_SUSPEND_MAX) 
        hibernate();                  //hibernate高通平台目前不支持 
    else 
        pm_suspend(autosleep_state); //进入pm_suspend,dmesg会有PM: suspend entry 与PM: suspend exit来标记,这里面会执行freeze task,suspend与resume,disable cpu的操作。内核PM最重要的函数。

mutex_unlock(&autosleep_lock);

if (!pm_get_wakeup_count(&final_count, false))//获取final_count,非block,当然也会检查是否有active wakeup source,当有active存在再次queue work 
        goto out;

/* 
     * If the wakeup occured for an unknown reason, wait to prevent the 
     * system from trying to suspend and waking up in a tight loop. 
     */ 
    if (final_count == initial_count)             //这里遇见未知原因,initial_count与final_count相等,超时500ms后继续往下执行。这种现象我也是跟了许久没有遇见过。 
        schedule_timeout_uninterruptible(HZ / 2);

out: 
    queue_up_suspend_work(); //调度queue work会再次执行该函数,实际上只要一次echo mem > sys/power/autosleep后这个进程一直会在auto_sleep cycle。 
}

pm_get_wakeup_count原型:

bool pm_get_wakeup_count(unsigned int *count, bool block) 

    unsigned int cnt, inpr;

if (block) { //当block为真时,该进程可能会block住 
        DEFINE_WAIT(wait);

for (;;) { 
            prepare_to_wait(&wakeup_count_wait_queue, &wait, 
                    TASK_INTERRUPTIBLE); 
            split_counters(&cnt, &inpr); //有active的wakeup_source存在就是block住,否则block 
            if (inpr == 0 || signal_pending(current)) 
                break; 
             
            schedule();//在这里面block住,直到最后一个active的wakeup_source deactivate时会唤醒该进程,之后会break出来。 
        } 
        finish_wait(&wakeup_count_wait_queue, &wait); 
    }

split_counters(&cnt, &inpr); 
    *count = cnt; 
    return !inpr; 
}

那么有2个问题,按power键唤醒系统是退出try_to_suspend了吗? 
       首先系统是如何被唤醒的?这个是由硬件中断唤醒的,比如我们这里的power键,还有其他的比如alarm等其他硬件中断,只要我们在中断申请时enbale_irq_wake(), 
那么睡眠期间,只要触发该中断就可以唤醒系统。那么在try_to_suspend里面唤醒后pm_suspend()执行完resume后会退出来,接着会获取final_count,在这里是存在active 
wake_up source的(在out之前加添的打印active wakeup_source,下面的dmesg证明了存在的wakeup_source),之后执行out,后调度工作队列,再次进入try_to_suspend(),在第一次获取initial_count后便会遇见active wakeup_source,这里面更多的是系统上层加的wakeup_source,那么try_to_suspend()会一直block在pm_get_wakeup_count()里面直到灭屏和所有wakeup_source deactivate时会再次进入pm_suspend()休眠。 
       这里也就解释了为什么只要执行一次ehco mem > sys/power/autosleep后自动可以休眠了的原因。

看下面的dmesg: 
<6>[  928.536418] CPU0: msm_cpu_pm_enter_sleep mode 000000,00000000,00000000,00000000,00000000,00000020,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000 
<6>[  928.543066] PM: noirq resume of devices complete after 6.020 msecs 
<6>[  928.548512] PM: early resume of devices complete after 2.598 msecs 
<6>[  928.650793] PM: resume of devices complete after 102.266 msecs 
<6>[  928.660290] Restarting tasks ... done. 
<6>[  928.681208] PM: suspend exit 1970-01-05 05:23:32.206389881 UTC 
<6>[  928.681229] active wake lock KeyEvents 
<6>[  928.681267] active wake lock qpnp_soc_wake 
<6>[  928.681284] active wake lock alarm, time left 486 
<6>[  928.681342] active wake lock KeyEvents 
<6>[  928.681584] active wake lock qpnp_soc_wake 
<6>[  928.681600] active wake lock alarm, time left 486 
<6>[  928.696345] request_suspend_state: wakeup at 928691792356 (1970-01-05 05:23:32.221521704 UTC) 
<6>[  928.708608] mdss_dsi_panel_power on=1

还有一个与wakeup source无关的问题,为什么suspend后就一直停留在那里不动了? 
       这个是cpu停止运转了,下面再分析下代码。 
       核心函数suspend_devices_and_enter():

/** 
 * suspend_devices_and_enter - Suspend devices and enter system sleep state. 
 * @state: System sleep state to enter. 
 */ 
int suspend_devices_and_enter(suspend_state_t state) 

    int error; 
    bool wakeup = false;

if (!suspend_ops) 
        return -ENOSYS;

trace_machine_suspend(state); 
    if (suspend_ops->begin) { 
        error = suspend_ops->begin(state); 
        if (error) 
            goto Close; 
    } 
    suspend_console(); 
    suspend_test_start(); 
    error = dpm_suspend_start(PMSG_SUSPEND);//这里会执行所有driver的suspend函数,suspend里面有active wakeup_source或者return 为真的话,suspend会报错 
    if (error) { 
        printk(KERN_ERR "PM: Some devices failed to suspend\n"); 
        goto Recover_platform; 
    } 
    suspend_test_finish("suspend devices"); 
    if (suspend_test(TEST_DEVICES)) 
        goto Recover_platform;

do { 
        error = suspend_enter(state, &wakeup);//这里会diable cpu 
    } while (!error && !wakeup 
        && suspend_ops->suspend_again && suspend_ops->suspend_again());

Resume_devices: 
    suspend_test_start(); 
    dpm_resume_end(PMSG_RESUME); 
    suspend_test_finish("resume devices"); 
    resume_console(); 
 Close: 
    if (suspend_ops->end) 
        suspend_ops->end(); 
    trace_machine_suspend(PWR_EVENT_EXIT); 
    return error;

Recover_platform: 
    if (suspend_ops->recover) 
        suspend_ops->recover(); 
    goto Resume_devices; 
}

static int suspend_enter(suspend_state_t state, bool *wakeup) 

    int error;

if (suspend_ops->prepare) { 
        error = suspend_ops->prepare(); 
        if (error) 
            goto Platform_finish; 
    }

error = dpm_suspend_end(PMSG_SUSPEND); 
    if (error) { 
        printk(KERN_ERR "PM: Some devices failed to power down\n"); 
        goto Platform_finish; 
    }

if (suspend_ops->prepare_late) { 
        error = suspend_ops->prepare_late(); 
        if (error) 
            goto Platform_wake; 
    }

if (suspend_test(TEST_PLATFORM)) 
        goto Platform_wake;

error = disable_nonboot_cpus();  //disable nonboot cpu注意还有cpu需要下面disable的 
    if (error || suspend_test(TEST_CPUS)) 
        goto Enable_cpus;

arch_suspend_disable_irqs(); 
    BUG_ON(!irqs_disabled());

error = syscore_suspend(); 
    if (!error) { 
        *wakeup = pm_wakeup_pending(); 
        if (!(suspend_test(TEST_CORE) || *wakeup)) { 
            error = suspend_ops->enter(state); //在这里cpu会停止运行,直到中断唤醒 
//下面的全部是唤醒的操作了 
            events_check_enabled = false; 
        } 
        syscore_resume(); 
    }

arch_suspend_enable_irqs(); 
    BUG_ON(irqs_disabled());

Enable_cpus: 
    enable_nonboot_cpus();

Platform_wake: 
    if (suspend_ops->wake) 
        suspend_ops->wake();

dpm_resume_start(PMSG_RESUME);

Platform_finish: 
    if (suspend_ops->finish) 
        suspend_ops->finish();

return error; 
}

平台赋值: 
static const struct platform_suspend_ops lpm_suspend_ops = { 
    .enter = lpm_suspend_enter,//在这里面disbale cpu,停止运行程序 
    .valid = suspend_valid_only_mem, 
    .prepare_late = lpm_suspend_prepare, 
    .wake = lpm_suspend_wake, 
};

添加显示wake_lock的dmesg: 
<6>[   90.964850] CPU0: msm_cpu_pm_enter_sleep mode 000000,00000000,00000000,00000000,00000000,00000020,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000 
<6>[   90.965302] Enabling non-boot CPUs ... 
<6>[   90.968303] CPU3 is up 
<6>[   90.970699] PM: noirq resume of devices complete after 2.382 msecs 
<6>[   90.973460] PM: early resume of devices complete after 1.443 msecs 
<6>[   91.097369] PM: resume of devices complete after 123.888 msecs 
<6>[   91.112858] Restarting tasks ... done. 
<6>[   91.141699] PM: suspend exit 1970-01-05 03:59:28.158266979 UTC 
<6>[   91.141776] PM: suspend entry 1970-01-05 03:59:28.158347917 UTC 
<6>[   91.141801] PM: Syncing filesystems ... done. 
<6>[   91.222299] Freezing user space processes ... (elapsed 0.03 seconds) done. 
<6>[   91.258126] Freezing remaining freezable tasks ... (elapsed 0.02 seconds) done. 
<6>[   91.278279] Suspending console(s) (use no_console_suspend to debug) 
<6>[   91.384933] PM: suspend of devices complete after 95.062 msecs 
<6>[   91.397910] PM: late suspend of devices complete after 12.934 msecs 
<6>[   91.413019] PM: noirq suspend of devices complete after 15.064 msecs 
<6>[   91.413059] Disabling non-boot CPUs ... 
<6>[   91.424477] CPU0: msm_cpu_pm_enter_sleep mode 000000,00000000,00000000,00000000,00000000,00000020,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000 
<6>[   91.425144] Enabling non-boot CPUs ... 
<6>[   91.432354] CPU3 is up 
<6>[   91.444416] PM: noirq resume of devices complete after 11.997 msecs 
<6>[   91.460948] PM: early resume of devices complete after 10.458 msecs 
<6>[   91.577213] PM: resume of devices complete after 116.231 msecs 
<6>[   91.584876] Restarting tasks ... done. 
<6>[   91.614571] PM: suspend exit 1970-01-05 03:59:35.550203849 UTC 
<6>[   91.614639] active wake lock rmt_storage_-1220268312 
<6>[   91.689912] PM: suspend entry 1970-01-05 03:59:35.625550620 UTC 
<6>[   91.689921] PM: Syncing filesystems ... done. 
<6>[   91.700706] Freezing user space processes ... 
<3>[   91.712870] Freezing of user space  aborted 
<6>[   91.712898] 
<6>[   91.712903] Restarting tasks ... done. 
<6>[   91.720540] PM: suspend exit 1970-01-05 03:59:35.656175256 UTC 
<6>[   91.720574] PM: suspend entry 1970-01-05 03:59:35.656214579 UTC 
<6>[   91.720586] PM: Syncing filesystems ... done. 
<6>[   91.801097] Freezing user space processes ... 
<3>[   91.815050] Freezing of user space  aborted 
<6>[   91.815075] 
<6>[   91.815083] Restarting tasks ... done. 
<6>[   91.823603] PM: suspend exit 1970-01-05 03:59:35.759241558 UTC 
<6>[   91.823633] PM: suspend entry 1970-01-05 03:59:35.759272964 UTC 
<6>[   91.823643] PM: Syncing filesystems ... done. 
<6>[   91.911985] Freezing user space processes ... (elapsed 0.03 seconds) done. 
<6>[   91.949378] Freezing remaining freezable tasks ... (elapsed 0.01 seconds) done. 
<6>[   91.969089] Suspending console(s) (use no_console_suspend to debug) 
<6>[   92.085594] PM: suspend of devices complete after 98.499 msecs 
<6>[   92.098615] PM: late suspend of devices complete after 12.975 msecs 
<6>[   92.113909] PM: noirq suspend of devices complete after 15.249 msecs 
<6>[   92.113951] Disabling non-boot CPUs ... 
<6>[   92.147320] CPU0: msm_cpu_pm_enter_sleep mode 000000,00000000,00000000,00000000,00000000,00000020,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000 
<6>[   92.148265] Enabling non-boot CPUs ... 
<6>[   92.155121] CPU1 is up 
<6>[   92.163797] CPU2 is up 
<6>[   92.174144] CPU3 is up 
<6>[   92.186556] PM: noirq resume of devices complete after 12.344 msecs 
<6>[   92.199945] PM: early resume of devices complete after 10.020 msecs 
<6>[   92.317528] PM: resume of devices complete after 117.548 msecs 
<6>[   92.326254] Restarting tasks ... done. 
<6>[   92.342025] PM: suspend exit 1970-01-05 04:00:48.122436614 UTC 
<6>[   92.342337] active wake lock qpnp-vadc-f611ac00 
<6>[   92.342357] active wake lock alarm, time left 481 
<6>[   92.411428] PM: suspend entry 1970-01-05 04:00:48.191838905 UTC 
<6>[   92.411451] PM: Syncing filesystems ... done. 
<6>[   92.419086] Freezing user space processes ... 
<3>[   92.431173] Freezing of user space  aborted 
<6>[   92.431213] 
<6>[   92.431225] Restarting tasks ... done. 
<6>[   92.441575] PM: suspend exit 1970-01-05 04:00:48.221987864 UTC 
<6>[   92.441709] active wake lock qpnp-vadc-f611ac00 
<6>[   92.445004] PM: suspend entry 1970-01-05 04:00:48.225417551 UTC 
<6>[   92.445026] PM: Syncing filesystems ... done. 
<6>[   92.525764] Freezing user space processes ... 
<3>[   92.541465] Freezing of user space  aborted 
<6>[   92.541523] 
<6>[   92.541545] Restarting tasks ... done. 
<6>[   92.558768] PM: suspend exit 1970-01-05 04:00:48.339166145 UTC 
<6>[   92.558865] PM: suspend entry 1970-01-05 04:00:48.339268645 UTC 
<6>[   92.558898] PM: Syncing filesystems ... done. 
<6>[   92.656122] Freezing user space processes ... (elapsed 0.04 seconds) done. 
<6>[   92.699091] Freezing remaining freezable tasks ... (elapsed 0.01 seconds) done. 
<6>[   92.718891] Suspending console(s) (use no_console_suspend to debug) 
<6>[   92.832084] PM: suspend of devices complete after 97.905 msecs 
<6>[   92.845099] PM: late suspend of devices complete after 12.971 msecs 
<6>[   92.860407] PM: noirq suspend of devices complete after 15.264 msecs 
<6>[   92.860447] Disabling non-boot CPUs ... 
<6>[   92.895114] CPU0: msm_cpu_pm_enter_sleep mode 000000,00000000,00000000,00000000,00000000,00000020,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000

基于wakeup_source的linux内核睡眠机制相关推荐

  1. Linux内核同步机制之(四):spin lock【转】

    转自:http://www.wowotech.net/kernel_synchronization/spinlock.html 一.前言 在linux kernel的实现中,经常会遇到这样的场景:共享 ...

  2. Linux内核睡眠唤醒调试

    本文基于RockPI 4A单板Debian系统Linux4.4内核介绍下睡眠唤醒(suspend/resume)的一些调试方法. 一.参数设置 1.关闭串口睡眠 在Linux内核睡眠过程中,会先调用s ...

  3. u-boot的linux内核映像加载,基于U_Boot的Linux内核映像加载与引导功能实现.pdf

    基于U_Boot的Linux内核映像加载与引导功能实现 20 10 8 ( ) Aug . 2010 10 4 Journal of Langfang T eachers College( N atu ...

  4. 国外linux内核视频播放器,基于Video for Linux内核的USB摄像头视频信号采集实现

    摘要:Video for Linux是Linux中关于视频设备的内核驱动,本文介绍了在Video for Linux内 >> 基于ARM9和USB摄像头的网络视频采集系统设计 基于嵌入式V ...

  5. 基于树莓派对Linux内核简单认识

    基于树莓派对Linux内核简单认识 树莓派等芯片带操作系统的启动过程 Linux 内核源码 Linux 内核源码目录树 安装tree命令 目录树结构 Linux根目录下 \ 树莓派Linux源码配置 ...

  6. [转载]基于ARM的linux内核裁剪与移植

    基于ARM的linux内核裁剪与移植 http://bbs.elecfans.com/forum.php?mod=viewthread&tid=185020  wutaimin( 楼主 ) 2 ...

  7. 深度剖析Linux内核地址映射机制

    深度剖析Linux内核地址映射机制 1.虚拟空间数据结构   2.进程虚拟空间  3.内存映射 视频讲解如下,点击观看: Linux内核开发系列第7讲--深度剖析Linux内核地址映射机制 C/C++ ...

  8. linux 内核mmap,Linux内核mmap机制

    1. 问:如何将物理地址映射到用户空间的虚拟地址上? 2.linux内核mmap机制 2.1.回顾LED驱动数据流的操作过程 通过分析LED驱动,得出以下结论: 如果利用read,write,ioct ...

  9. 学内核之二:基于QEMU搭建Linux内核运行调试环境

    目录 一 接续上文 二 编译根文件系统 三 构建完善根文件系统 四 内核中指定根文件系统 五 带根文件系统启动内核 一 接续上文 在上一篇文章中,我们展示了通过QEMU仿真软件来运行Linux内核的过 ...

  10. Linux内核同步机制之信号量与锁

    Linux内核同步控制方法有很多,信号量.锁.原子量.RCU等等,不同的实现方法应用于不同的环境来提高操作系统效率.首先,看看我们最熟悉的两种机制--信号量.锁. 一.信号量 首先还是看看内核中是怎么 ...

最新文章

  1. ICLR 6-6-6!自注意力可以替代CNN,能表达任何卷积滤波层
  2. sqlserver 穷举 排列 组合
  3. 向 mysql导入数据 源码_MySQL 导入数据
  4. Linux主机硬盘的主要规划
  5. url中 斜杠如何传输_如何在父子页面中传输数据(layer)
  6. i3处理器能运行python吗_老cpu(10年前的core i3 不支持avx指令集)安装tensorflow2.0...
  7. 新华三模拟器Telnet/远程登录
  8. 2018-10-27
  9. Insomni'hack teaser 2019 - Misc - echoechoechoecho
  10. Swift_学习笔记_调用ObjectiveC方法
  11. 图片上传File对象不兼容IE
  12. 大神之光照耀着我 - 我的成长之路 - 起点
  13. C ++程序将字符串的每个单词的首字母转换为大写,将其他转换为小写
  14. Java笔记 - 网络编程
  15. 【笔记】C#学习笔记
  16. Promise回调地狱的拯救者
  17. tkinter+爬虫实现有道翻译桌面软件
  18. (三)展望Java技术的未来
  19. AE使用函数集10:获取图层组中的所有图层
  20. excel的Countif函数使用详细教程

热门文章

  1. 弹出visual studio 实时调试器解决
  2. revit 转换ifc_将IFC转换成GLTF格式
  3. Fabric-02Peer、Orderer以及CA
  4. 计算机模拟技术在高分子领域的应用,模拟技术的原理、方法及在高分子材料研究中的应用...
  5. Mantis集成富文本插件
  6. HIGEN海坚驱动器维修FDA7045伺服变频器维修
  7. day69_淘淘商城项目_02_dubbo介绍 + dubbo框架整合 + zookeeper + 商品列表查询实现 + 分页 + 逆向工程_匠心笔记
  8. 如何计算文件MD5 sha1 -- 微软MD5/SHA1 校验工具 Microsoft File Checksum Integrity Verifier
  9. Java源码阅读--任重而道远(lang)
  10. JS数组常用方法整理(14种常用方法)