您当前的位置:首页 > IT编程 > C++
| C语言 | Java | VB | VC | python | Android | TensorFlow | C++ | oracle | 学术与代码 | cnn卷积神经网络 | gnn | 图像修复 | Keras | 数据集 | Neo4j | 自然语言处理 | 深度学习 | 医学CAD | 医学影像 | 超参数 | pointnet | pytorch | 异常检测 | Transformers | 情感分类 | 知识图谱 |

自学教程:C++ this_cpu_write函数代码示例

51自学网 2021-06-03 08:48:17
  C++
这篇教程C++ this_cpu_write函数代码示例写得很实用,希望能帮到您。

本文整理汇总了C++中this_cpu_write函数的典型用法代码示例。如果您正苦于以下问题:C++ this_cpu_write函数的具体用法?C++ this_cpu_write怎么用?C++ this_cpu_write使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。

在下文中一共展示了this_cpu_write函数的30个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的C++代码示例。

示例1: __sbitmap_queue_get

int __sbitmap_queue_get(struct sbitmap_queue *sbq){	unsigned int hint, depth;	int nr;	hint = this_cpu_read(*sbq->alloc_hint);	depth = READ_ONCE(sbq->sb.depth);	if (unlikely(hint >= depth)) {		hint = depth ? prandom_u32() % depth : 0;		this_cpu_write(*sbq->alloc_hint, hint);	}	nr = sbitmap_get(&sbq->sb, hint, sbq->round_robin);	if (nr == -1) {		/* If the map is full, a hint won't do us much good. */		this_cpu_write(*sbq->alloc_hint, 0);	} else if (nr == hint || unlikely(sbq->round_robin)) {		/* Only update the hint if we used it. */		hint = nr + 1;		if (hint >= depth - 1)			hint = 0;		this_cpu_write(*sbq->alloc_hint, hint);	}	return nr;}
开发者ID:AshishNamdev,项目名称:linux,代码行数:26,


示例2: initialize_tlbstate_and_flush

/* * Call this when reinitializing a CPU.  It fixes the following potential * problems: * * - The ASID changed from what cpu_tlbstate thinks it is (most likely *   because the CPU was taken down and came back up with CR3's PCID *   bits clear.  CPU hotplug can do this. * * - The TLB contains junk in slots corresponding to inactive ASIDs. * * - The CPU went so far out to lunch that it may have missed a TLB *   flush. */void initialize_tlbstate_and_flush(void){	int i;	struct mm_struct *mm = this_cpu_read(cpu_tlbstate.loaded_mm);	u64 tlb_gen = atomic64_read(&init_mm.context.tlb_gen);	unsigned long cr3 = __read_cr3();	/* Assert that CR3 already references the right mm. */	WARN_ON((cr3 & CR3_ADDR_MASK) != __pa(mm->pgd));	/*	 * Assert that CR4.PCIDE is set if needed.  (CR4.PCIDE initialization	 * doesn't work like other CR4 bits because it can only be set from	 * long mode.)	 */	WARN_ON(boot_cpu_has(X86_FEATURE_PCID) &&		!(cr4_read_shadow() & X86_CR4_PCIDE));	/* Force ASID 0 and force a TLB flush. */	write_cr3(build_cr3(mm, 0));	/* Reinitialize tlbstate. */	this_cpu_write(cpu_tlbstate.loaded_mm_asid, 0);	this_cpu_write(cpu_tlbstate.next_asid, 1);	this_cpu_write(cpu_tlbstate.ctxs[0].ctx_id, mm->context.ctx_id);	this_cpu_write(cpu_tlbstate.ctxs[0].tlb_gen, tlb_gen);	for (i = 1; i < TLB_NR_DYN_ASIDS; i++)		this_cpu_write(cpu_tlbstate.ctxs[i].ctx_id, 0);}
开发者ID:EMFPGA,项目名称:linux_media,代码行数:43,


示例3: clear_asid_other

/* * We get here when we do something requiring a TLB invalidation * but could not go invalidate all of the contexts.  We do the * necessary invalidation by clearing out the 'ctx_id' which * forces a TLB flush when the context is loaded. */static void clear_asid_other(void){	u16 asid;	/*	 * This is only expected to be set if we have disabled	 * kernel _PAGE_GLOBAL pages.	 */	if (!static_cpu_has(X86_FEATURE_PTI)) {		WARN_ON_ONCE(1);		return;	}	for (asid = 0; asid < TLB_NR_DYN_ASIDS; asid++) {		/* Do not need to flush the current asid */		if (asid == this_cpu_read(cpu_tlbstate.loaded_mm_asid))			continue;		/*		 * Make sure the next time we go to switch to		 * this asid, we do a flush:		 */		this_cpu_write(cpu_tlbstate.ctxs[asid].ctx_id, 0);	}	this_cpu_write(cpu_tlbstate.invalidate_other, false);}
开发者ID:AlexShiLucky,项目名称:linux,代码行数:31,


示例4: init_hvm_pv_info

static void __init init_hvm_pv_info(void){	int major, minor;	uint32_t eax, ebx, ecx, edx, base;	base = xen_cpuid_base();	eax = cpuid_eax(base + 1);	major = eax >> 16;	minor = eax & 0xffff;	printk(KERN_INFO "Xen version %d.%d./n", major, minor);	xen_domain_type = XEN_HVM_DOMAIN;	/* PVH set up hypercall page in xen_prepare_pvh(). */	if (xen_pvh_domain())		pv_info.name = "Xen PVH";	else {		u64 pfn;		uint32_t msr;		pv_info.name = "Xen HVM";		msr = cpuid_ebx(base + 2);		pfn = __pa(hypercall_page);		wrmsr_safe(msr, (u32)pfn, (u32)(pfn >> 32));	}	xen_setup_features();	cpuid(base + 4, &eax, &ebx, &ecx, &edx);	if (eax & XEN_HVM_CPUID_VCPU_ID_PRESENT)		this_cpu_write(xen_vcpu_id, ebx);	else		this_cpu_write(xen_vcpu_id, smp_processor_id());}
开发者ID:asmalldev,项目名称:linux,代码行数:35,


示例5: choose_new_asid

static void choose_new_asid(struct mm_struct *next, u64 next_tlb_gen,			    u16 *new_asid, bool *need_flush){	u16 asid;	if (!static_cpu_has(X86_FEATURE_PCID)) {		*new_asid = 0;		*need_flush = true;		return;	}	for (asid = 0; asid < TLB_NR_DYN_ASIDS; asid++) {		if (this_cpu_read(cpu_tlbstate.ctxs[asid].ctx_id) !=		    next->context.ctx_id)			continue;		*new_asid = asid;		*need_flush = (this_cpu_read(cpu_tlbstate.ctxs[asid].tlb_gen) <			       next_tlb_gen);		return;	}	/*	 * We don't currently own an ASID slot on this CPU.	 * Allocate a slot.	 */	*new_asid = this_cpu_add_return(cpu_tlbstate.next_asid, 1) - 1;	if (*new_asid >= TLB_NR_DYN_ASIDS) {		*new_asid = 0;		this_cpu_write(cpu_tlbstate.next_asid, 1);	}	*need_flush = true;}
开发者ID:EMFPGA,项目名称:linux_media,代码行数:33,


示例6: cpu_bringup

static void __cpuinit cpu_bringup(void){	int cpu;	cpu_init();	touch_softlockup_watchdog();	preempt_disable();	xen_enable_sysenter();	xen_enable_syscall();	cpu = smp_processor_id();	smp_store_cpu_info(cpu);	cpu_data(cpu).x86_max_cores = 1;	set_cpu_sibling_map(cpu);	xen_setup_cpu_clockevents();	notify_cpu_starting(cpu);	ipi_call_lock();	set_cpu_online(cpu, true);	ipi_call_unlock();	this_cpu_write(cpu_state, CPU_ONLINE);	wmb();		local_irq_enable();	wmb();			}
开发者ID:DirtyDroidX,项目名称:android_kernel_htc_m8ul,代码行数:33,


示例7: cpu_bringup

static void __cpuinit cpu_bringup(void){	int cpu;	cpu_init();	touch_softlockup_watchdog();	preempt_disable();	/* PVH runs in ring 0 and allows us to do native syscalls. Yay! */	if (!xen_feature(XENFEAT_supervisor_mode_kernel)) {		xen_enable_sysenter();		xen_enable_syscall();	}	cpu = smp_processor_id();	smp_store_cpu_info(cpu);	cpu_data(cpu).x86_max_cores = 1;	set_cpu_sibling_map(cpu);	xen_setup_cpu_clockevents();	notify_cpu_starting(cpu);	set_cpu_online(cpu, true);	this_cpu_write(cpu_state, CPU_ONLINE);	wmb();	/* We can take interrupts now: we're officially "up". */	local_irq_enable();	wmb();			/* make sure everything is out */}
开发者ID:mbgg,项目名称:linux,代码行数:33,


示例8: takeover_tasklets

static int takeover_tasklets(unsigned int cpu){	/* CPU is dead, so no lock needed. */	local_irq_disable();	/* Find end, append list for that CPU. */	if (&per_cpu(tasklet_vec, cpu).head != per_cpu(tasklet_vec, cpu).tail) {		*__this_cpu_read(tasklet_vec.tail) = per_cpu(tasklet_vec, cpu).head;		this_cpu_write(tasklet_vec.tail, per_cpu(tasklet_vec, cpu).tail);		per_cpu(tasklet_vec, cpu).head = NULL;		per_cpu(tasklet_vec, cpu).tail = &per_cpu(tasklet_vec, cpu).head;	}	raise_softirq_irqoff(TASKLET_SOFTIRQ);	if (&per_cpu(tasklet_hi_vec, cpu).head != per_cpu(tasklet_hi_vec, cpu).tail) {		*__this_cpu_read(tasklet_hi_vec.tail) = per_cpu(tasklet_hi_vec, cpu).head;		__this_cpu_write(tasklet_hi_vec.tail, per_cpu(tasklet_hi_vec, cpu).tail);		per_cpu(tasklet_hi_vec, cpu).head = NULL;		per_cpu(tasklet_hi_vec, cpu).tail = &per_cpu(tasklet_hi_vec, cpu).head;	}	raise_softirq_irqoff(HI_SOFTIRQ);	local_irq_enable();	return 0;}
开发者ID:h4ck3rm1k3,项目名称:linux,代码行数:25,


示例9: cpu_bringup

static void __cpuinit cpu_bringup(void){	int cpu;	cpu_init();	touch_softlockup_watchdog();	preempt_disable();	xen_enable_sysenter();	xen_enable_syscall();	cpu = smp_processor_id();	smp_store_cpu_info(cpu);	cpu_data(cpu).x86_max_cores = 1;	set_cpu_sibling_map(cpu);	xen_setup_cpu_clockevents();	notify_cpu_starting(cpu);	set_cpu_online(cpu, true);	this_cpu_write(cpu_state, CPU_ONLINE);	wmb();	/* We can take interrupts now: we're officially "up". */	local_irq_enable();	wmb();			/* make sure everything is out */}
开发者ID:garyvan,项目名称:openwrt-1.6,代码行数:31,


示例10: enter_lazy_tlb

/* * Please ignore the name of this function.  It should be called * switch_to_kernel_thread(). * * enter_lazy_tlb() is a hint from the scheduler that we are entering a * kernel thread or other context without an mm.  Acceptable implementations * include doing nothing whatsoever, switching to init_mm, or various clever * lazy tricks to try to minimize TLB flushes. * * The scheduler reserves the right to call enter_lazy_tlb() several times * in a row.  It will notify us that we're going back to a real mm by * calling switch_mm_irqs_off(). */void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk){	if (this_cpu_read(cpu_tlbstate.loaded_mm) == &init_mm)		return;	this_cpu_write(cpu_tlbstate.is_lazy, true);}
开发者ID:AlexShiLucky,项目名称:linux,代码行数:20,


示例11: random_tag

/* * If a preemption happens between this_cpu_read and this_cpu_write, the only * side effect is that we'll give a few allocated in different contexts objects * the same tag. Since tag-based KASAN is meant to be used a probabilistic * bug-detection debug feature, this doesn't have significant negative impact. * * Ideally the tags use strong randomness to prevent any attempts to predict * them during explicit exploit attempts. But strong randomness is expensive, * and we did an intentional trade-off to use a PRNG. This non-atomic RMW * sequence has in fact positive effect, since interrupts that randomly skew * PRNG at unpredictable points do only good. */u8 random_tag(void){	u32 state = this_cpu_read(prng_state);	state = 1664525 * state + 1013904223;	this_cpu_write(prng_state, state);	return (u8)(state % (KASAN_TAG_MAX + 1));}
开发者ID:AlexShiLucky,项目名称:linux,代码行数:21,


示例12: set_cpuid_faulting

static void set_cpuid_faulting(bool on){	u64 msrval;	msrval = this_cpu_read(msr_misc_features_shadow);	msrval &= ~MSR_MISC_FEATURES_ENABLES_CPUID_FAULT;	msrval |= (on << MSR_MISC_FEATURES_ENABLES_CPUID_FAULT_BIT);	this_cpu_write(msr_misc_features_shadow, msrval);	wrmsrl(MSR_MISC_FEATURES_ENABLES, msrval);}
开发者ID:Anjali05,项目名称:linux,代码行数:10,


示例13: trace_hardirqs_on

void trace_hardirqs_on(void){	if (this_cpu_read(tracing_irq_cpu)) {		if (!in_nmi())			trace_irq_enable_rcuidle(CALLER_ADDR0, CALLER_ADDR1);		tracer_hardirqs_on(CALLER_ADDR0, CALLER_ADDR1);		this_cpu_write(tracing_irq_cpu, 0);	}	lockdep_hardirqs_on(CALLER_ADDR0);}
开发者ID:AlexShiLucky,项目名称:linux,代码行数:11,


示例14: xen_read_cr0

static unsigned long xen_read_cr0(void){	unsigned long cr0 = this_cpu_read(xen_cr0_value);	if (unlikely(cr0 == 0)) {		cr0 = native_read_cr0();		this_cpu_write(xen_cr0_value, cr0);	}	return cr0;}
开发者ID:DirtyDroidX,项目名称:android_kernel_htc_m8ul,代码行数:11,


示例15: echainiv_write_iv

static void echainiv_write_iv(const u8 *src, unsigned size){    const u32 *a = (const u32 *)src;    u32 __percpu *b = echainiv_iv;    for (; size >= 4; size -= 4) {        this_cpu_write(*b, *a);        a++;        b++;    }}
开发者ID:quadcores,项目名称:cbs_4.2.4,代码行数:11,


示例16: trace_hardirqs_off_caller

__visible void trace_hardirqs_off_caller(unsigned long caller_addr){	if (!this_cpu_read(tracing_irq_cpu)) {		this_cpu_write(tracing_irq_cpu, 1);		tracer_hardirqs_off(CALLER_ADDR0, caller_addr);		if (!in_nmi())			trace_irq_disable_rcuidle(CALLER_ADDR0, caller_addr);	}	lockdep_hardirqs_off(CALLER_ADDR0);}
开发者ID:AlexShiLucky,项目名称:linux,代码行数:11,


示例17: trace_hardirqs_off

void trace_hardirqs_off(void){	if (!this_cpu_read(tracing_irq_cpu)) {		this_cpu_write(tracing_irq_cpu, 1);		tracer_hardirqs_off(CALLER_ADDR0, CALLER_ADDR1);		if (!in_nmi())			trace_irq_disable_rcuidle(CALLER_ADDR0, CALLER_ADDR1);	}	lockdep_hardirqs_off(CALLER_ADDR0);}
开发者ID:AlexShiLucky,项目名称:linux,代码行数:11,


示例18: queue_ue_paddr

static void queue_ue_paddr(unsigned long paddr){	int index;	index = __this_cpu_inc_return(rtas_ue_count) - 1;	if (index >= MAX_MC_EVT) {		__this_cpu_dec(rtas_ue_count);		return;	}	this_cpu_write(rtas_ue_paddr[index], paddr);	schedule_work(&hwpoison_work);}
开发者ID:avagin,项目名称:linux,代码行数:12,


示例19: xen_write_cr0

static void xen_write_cr0(unsigned long cr0){	struct multicall_space mcs;	this_cpu_write(xen_cr0_value, cr0);	mcs = xen_mc_entry(0);	MULTI_fpu_taskswitch(mcs.mc, (cr0 & X86_CR0_TS) != 0);	xen_mc_issue(PARAVIRT_LAZY_CPU);}
开发者ID:DirtyDroidX,项目名称:android_kernel_htc_m8ul,代码行数:12,


示例20: fpsimd_update_current_state

/* * Load an updated userland FPSIMD state for 'current' from memory and set the * flag that indicates that the FPSIMD register contents are the most recent * FPSIMD state of 'current' */void fpsimd_update_current_state(struct fpsimd_state *state){	preempt_disable();	fpsimd_load_state(state);	if (test_and_clear_thread_flag(TIF_FOREIGN_FPSTATE)) {		struct fpsimd_state *st = &current->thread.fpsimd_state;		this_cpu_write(fpsimd_last_state, st);		st->cpu = smp_processor_id();	}	preempt_enable();}
开发者ID:BORETS24,项目名称:Marshmallow-kernel-for-Asus-Zenfone-2-ZE551ML-ZE550ML,代码行数:17,


示例21: intel_epb_save

static int intel_epb_save(void){	u64 epb;	rdmsrl(MSR_IA32_ENERGY_PERF_BIAS, epb);	/*	 * Ensure that saved_epb will always be nonzero after this write even if	 * the EPB value read from the MSR is 0.	 */	this_cpu_write(saved_epb, (epb & EPB_MASK) | EPB_SAVED);	return 0;}
开发者ID:pranith,项目名称:linux,代码行数:13,


示例22: xen_write_cr0

static void xen_write_cr0(unsigned long cr0){	struct multicall_space mcs;	this_cpu_write(xen_cr0_value, cr0);	/* Only pay attention to cr0.TS; everything else is	   ignored. */	mcs = xen_mc_entry(0);	MULTI_fpu_taskswitch(mcs.mc, (cr0 & X86_CR0_TS) != 0);	xen_mc_issue(PARAVIRT_LAZY_CPU);}
开发者ID:253627764,项目名称:GT-I9500,代码行数:14,


示例23: fpsimd_restore_current_state

/* * Load the userland FPSIMD state of 'current' from memory, but only if the * FPSIMD state already held in the registers is /not/ the most recent FPSIMD * state of 'current' */void fpsimd_restore_current_state(void){	if (!system_supports_fpsimd())		return;	preempt_disable();	if (test_and_clear_thread_flag(TIF_FOREIGN_FPSTATE)) {		struct fpsimd_state *st = &current->thread.fpsimd_state;		fpsimd_load_state(st);		this_cpu_write(fpsimd_last_state, st);		st->cpu = smp_processor_id();	}	preempt_enable();}
开发者ID:farrellpeng,项目名称:MX283Linux,代码行数:19,


示例24: mce_intel_cmci_poll

bool mce_intel_cmci_poll(void){	if (__this_cpu_read(cmci_storm_state) == CMCI_STORM_NONE)		return false;	/*	 * Reset the counter if we've logged an error in the last poll	 * during the storm.	 */	if (machine_check_poll(0, this_cpu_ptr(&mce_banks_owned)))		this_cpu_write(cmci_backoff_cnt, INITIAL_CHECK_INTERVAL);	else		this_cpu_dec(cmci_backoff_cnt);	return true;}
开发者ID:CCNITSilchar,项目名称:linux,代码行数:16,


示例25: supdrvOSChangeCR4

RTCCUINTREG VBOXCALL supdrvOSChangeCR4(RTCCUINTREG fOrMask, RTCCUINTREG fAndMask){#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 20, 0)    RTCCUINTREG uOld = this_cpu_read(cpu_tlbstate.cr4);    RTCCUINTREG uNew = (uOld & fAndMask) | fOrMask;    if (uNew != uOld)    {        this_cpu_write(cpu_tlbstate.cr4, uNew);        __write_cr4(uNew);    }#else    RTCCUINTREG uOld = ASMGetCR4();    RTCCUINTREG uNew = (uOld & fAndMask) | fOrMask;    if (uNew != uOld)        ASMSetCR4(uNew);#endif    return uOld;}
开发者ID:sobomax,项目名称:virtualbox_64bit_edd,代码行数:18,


示例26: fpsimd_cpu_pm_notifier

static int fpsimd_cpu_pm_notifier(struct notifier_block *self,				  unsigned long cmd, void *v){	switch (cmd) {	case CPU_PM_ENTER:		if (current->mm && !test_thread_flag(TIF_FOREIGN_FPSTATE))			fpsimd_save_state(&current->thread.fpsimd_state);		this_cpu_write(fpsimd_last_state, NULL);		break;	case CPU_PM_EXIT:		if (current->mm)			set_thread_flag(TIF_FOREIGN_FPSTATE);		break;	case CPU_PM_ENTER_FAILED:	default:		return NOTIFY_DONE;	}	return NOTIFY_OK;}
开发者ID:BORETS24,项目名称:Marshmallow-kernel-for-Asus-Zenfone-2-ZE551ML-ZE550ML,代码行数:19,


示例27: enter_lazy_tlb

/* * enter_lazy_tlb() is a hint from the scheduler that we are entering a * kernel thread or other context without an mm.  Acceptable implementations * include doing nothing whatsoever, switching to init_mm, or various clever * lazy tricks to try to minimize TLB flushes. * * The scheduler reserves the right to call enter_lazy_tlb() several times * in a row.  It will notify us that we're going back to a real mm by * calling switch_mm_irqs_off(). */void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk){	if (this_cpu_read(cpu_tlbstate.loaded_mm) == &init_mm)		return;	if (static_branch_unlikely(&tlb_use_lazy_mode)) {		/*		 * There's a significant optimization that may be possible		 * here.  We have accurate enough TLB flush tracking that we		 * don't need to maintain coherence of TLB per se when we're		 * lazy.  We do, however, need to maintain coherence of		 * paging-structure caches.  We could, in principle, leave our		 * old mm loaded and only switch to init_mm when		 * tlb_remove_page() happens.		 */		this_cpu_write(cpu_tlbstate.is_lazy, true);	} else {		switch_mm(NULL, &init_mm, NULL);	}}
开发者ID:EMFPGA,项目名称:linux_media,代码行数:30,


示例28: kernel_neon_begin_partial

/* * Kernel-side NEON support functions */void kernel_neon_begin_partial(u32 num_regs){	if (in_interrupt()) {		struct fpsimd_partial_state *s = this_cpu_ptr(			in_irq() ? &hardirq_fpsimdstate : &softirq_fpsimdstate);		BUG_ON(num_regs > 32);		fpsimd_save_partial_state(s, roundup(num_regs, 2));	} else {		/*		 * Save the userland FPSIMD state if we have one and if we		 * haven't done so already. Clear fpsimd_last_state to indicate		 * that there is no longer userland FPSIMD state in the		 * registers.		 */		preempt_disable();		if (current->mm &&		    !test_and_set_thread_flag(TIF_FOREIGN_FPSTATE))			fpsimd_save_state(&current->thread.fpsimd_state);		this_cpu_write(fpsimd_last_state, NULL);	}}
开发者ID:BORETS24,项目名称:Marshmallow-kernel-for-Asus-Zenfone-2-ZE551ML-ZE550ML,代码行数:25,


示例29: leave_lazy

static void leave_lazy(enum paravirt_lazy_mode mode){	BUG_ON(this_cpu_read(paravirt_lazy_mode) != mode);	this_cpu_write(paravirt_lazy_mode, PARAVIRT_LAZY_NONE);}
开发者ID:JcShang,项目名称:linux-80211n-csitool,代码行数:6,


示例30: enter_lazy

static inline void enter_lazy(enum paravirt_lazy_mode mode){	BUG_ON(this_cpu_read(paravirt_lazy_mode) != PARAVIRT_LAZY_NONE);	this_cpu_write(paravirt_lazy_mode, mode);}
开发者ID:JcShang,项目名称:linux-80211n-csitool,代码行数:6,



注:本文中的this_cpu_write函数示例整理自Github/MSDocs等源码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。


C++ this_object函数代码示例
C++ this_cpu_read函数代码示例
万事OK自学网:51自学网_软件自学网_CAD自学网自学excel、自学PS、自学CAD、自学C语言、自学css3实例,是一个通过网络自主学习工作技能的自学平台,网友喜欢的软件自学网站。