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

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

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

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

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

示例1: audpreproc_dsp_event

/* ------------------- dsp preproc event handler--------------------- */static void audpreproc_dsp_event(void *data, unsigned id,  void *msg){	struct audio_in *audio = data;	switch (id) {	case AUDPREPROC_ERROR_MSG: {		struct audpreproc_err_msg *err_msg = msg;		MM_ERR("ERROR_MSG: stream id %d err idx %d/n",		err_msg->stream_id, err_msg->aud_preproc_err_idx);		/* Error case */		wake_up(&audio->wait_enable);		break;	}	case AUDPREPROC_CMD_CFG_DONE_MSG: {		MM_DBG("CMD_CFG_DONE_MSG /n");		break;	}	case AUDPREPROC_CMD_ENC_CFG_DONE_MSG: {		struct audpreproc_cmd_enc_cfg_done_msg *enc_cfg_msg = msg;		MM_DBG("CMD_ENC_CFG_DONE_MSG: stream id %d enc type /			0x%8x/n", enc_cfg_msg->stream_id,			enc_cfg_msg->rec_enc_type);		/* Encoder enable success */		if (enc_cfg_msg->rec_enc_type & ENCODE_ENABLE) {			if(audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {				MM_DBG("routing command/n");				audpreproc_cmd_cfg_routing_mode(audio);			} else {				audaac_in_param_config(audio);			}		} else { /* Encoder disable success */			audio->running = 0;			if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)				audaac_in_record_config(audio, 0);			else				wake_up(&audio->wait_enable);		}		break;	}	case AUDPREPROC_CMD_ENC_PARAM_CFG_DONE_MSG: {		MM_DBG("CMD_ENC_PARAM_CFG_DONE_MSG/n");		if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)			audaac_in_mem_config(audio);		else			audpcm_config(audio);		break;	}	case AUDPREPROC_CMD_ROUTING_MODE_DONE_MSG: {		struct audpreproc_cmd_routing_mode_done/				*routing_cfg_done_msg = msg;		if (routing_cfg_done_msg->configuration == 0) {			MM_INFO("routing configuration failed/n");			audio->running = 0;		} else			audaac_in_param_config(audio);		break;	}	case AUDPREPROC_AFE_CMD_AUDIO_RECORD_CFG_DONE_MSG: {		MM_DBG("AFE_CMD_AUDIO_RECORD_CFG_DONE_MSG/n");		wake_up(&audio->wait_enable);		break;	}	default:		MM_ERR("Unknown Event id %d/n", id);	}}
开发者ID:CL0SeY,项目名称:i957kernel,代码行数:69,


示例2: msm_gemini_core_irq

irqreturn_t msm_gemini_core_irq(int irq_num, void *context){	void *data = NULL;	unsigned long flags;	int gemini_irq_status;	GMN_DBG("%s:%d] irq_num = %d/n", __func__, __LINE__, irq_num);	spin_lock_irqsave(&reset_lock, flags);	reset_done_ack = 1;	spin_unlock_irqrestore(&reset_lock, flags);	gemini_irq_status = msm_gemini_hw_irq_get_status();	pr_err("%s:%d] gemini_irq_status = %0x/n", __func__, __LINE__,		gemini_irq_status);	/*For reset and framedone IRQs, clear all bits*/	if (gemini_irq_status & 0x400) {		wake_up(&reset_wait);		msm_gemini_hw_irq_clear(HWIO_JPEG_IRQ_CLEAR_RMSK,			JPEG_IRQ_CLEAR_ALL);	} else if (gemini_irq_status & 0x1) {		msm_gemini_hw_irq_clear(HWIO_JPEG_IRQ_CLEAR_RMSK,			JPEG_IRQ_CLEAR_ALL);	} else {		msm_gemini_hw_irq_clear(HWIO_JPEG_IRQ_CLEAR_RMSK,			gemini_irq_status);	}	if (msm_gemini_hw_irq_is_frame_done(gemini_irq_status)) {		data = msm_gemini_core_framedone_irq(gemini_irq_status,			context);		if (msm_gemini_irq_handler)			msm_gemini_irq_handler(				MSM_GEMINI_HW_MASK_COMP_FRAMEDONE,				context, data);	}	if (msm_gemini_hw_irq_is_reset_ack(gemini_irq_status)) {		data = msm_gemini_core_reset_ack_irq(gemini_irq_status,			context);		if (msm_gemini_irq_handler)			msm_gemini_irq_handler(				MSM_GEMINI_HW_MASK_COMP_RESET_ACK,				context, data);	}	/* Unexpected/unintended HW interrupt */	if (msm_gemini_hw_irq_is_err(gemini_irq_status) &&		!msm_gemini_hw_irq_is_frame_done(gemini_irq_status)) {		data = msm_gemini_core_err_irq(gemini_irq_status, context);		if (msm_gemini_irq_handler) {			msm_gemini_irq_handler(MSM_GEMINI_HW_MASK_COMP_ERR,				context, data);			data = msm_gemini_core_fe_pingpong_irq(					gemini_irq_status, context);			msm_gemini_irq_handler(MSM_GEMINI_HW_MASK_COMP_FE,				context, data);			data = msm_gemini_core_we_pingpong_irq(					gemini_irq_status, context);			msm_gemini_irq_handler(MSM_GEMINI_HW_MASK_COMP_WE,				context, data);		}		return IRQ_HANDLED;	}	if (msm_gemini_hw_irq_is_fe_pingpong(gemini_irq_status)) {		data = msm_gemini_core_fe_pingpong_irq(gemini_irq_status,			context);		if (msm_gemini_irq_handler)			msm_gemini_irq_handler(MSM_GEMINI_HW_MASK_COMP_FE,				context, data);	}	if (msm_gemini_hw_irq_is_we_pingpong(gemini_irq_status) &&	    !msm_gemini_hw_irq_is_frame_done(gemini_irq_status)) {		data = msm_gemini_core_we_pingpong_irq(gemini_irq_status,			context);		if (msm_gemini_irq_handler)			msm_gemini_irq_handler(MSM_GEMINI_HW_MASK_COMP_WE,				context, data);	}	return IRQ_HANDLED;}
开发者ID:Hadramos,项目名称:android_sony_xperiaz_kernel_sources,代码行数:85,


示例3: irq_handler

static irqreturn_t irq_handler(int irq, void *dev_id){	struct ngene *dev = (struct ngene *)dev_id;	u32 icounts = 0;	irqreturn_t rc = IRQ_NONE;	u32 i = MAX_STREAM;	u8 *tmpCmdDoneByte;	if (dev->BootFirmware) {		icounts = ngreadl(NGENE_INT_COUNTS);		if (icounts != dev->icounts) {			ngwritel(0, FORCE_NMI);			dev->cmd_done = 1;			wake_up(&dev->cmd_wq);			dev->icounts = icounts;			rc = IRQ_HANDLED;		}		return rc;	}	ngwritel(0, FORCE_NMI);	spin_lock(&dev->cmd_lock);	tmpCmdDoneByte = dev->CmdDoneByte;	if (tmpCmdDoneByte &&	    (*tmpCmdDoneByte ||	    (dev->ngenetohost[0] == 1 && dev->ngenetohost[1] != 0))) {		dev->CmdDoneByte = NULL;		dev->cmd_done = 1;		wake_up(&dev->cmd_wq);		rc = IRQ_HANDLED;	}	spin_unlock(&dev->cmd_lock);	if (dev->EventBuffer->EventStatus & 0x80) {		u8 nextWriteIndex =			(dev->EventQueueWriteIndex + 1) &			(EVENT_QUEUE_SIZE - 1);		if (nextWriteIndex != dev->EventQueueReadIndex) {			dev->EventQueue[dev->EventQueueWriteIndex] =				*(dev->EventBuffer);			dev->EventQueueWriteIndex = nextWriteIndex;		} else {			printk(KERN_ERR DEVICE_NAME ": event overflow/n");			dev->EventQueueOverflowCount += 1;			dev->EventQueueOverflowFlag = 1;		}		dev->EventBuffer->EventStatus &= ~0x80;		tasklet_schedule(&dev->event_tasklet);		rc = IRQ_HANDLED;	}	while (i > 0) {		i--;		spin_lock(&dev->channel[i].state_lock);		/* if (dev->channel[i].State>=KSSTATE_RUN) { */		if (dev->channel[i].nextBuffer) {			if ((dev->channel[i].nextBuffer->			     ngeneBuffer.SR.Flags & 0xC0) == 0x80) {				dev->channel[i].nextBuffer->					ngeneBuffer.SR.Flags |= 0x40;				tasklet_schedule(					&dev->channel[i].demux_tasklet);				rc = IRQ_HANDLED;			}		}		spin_unlock(&dev->channel[i].state_lock);	}	/* Request might have been processed by a previous call. */	return IRQ_HANDLED;}
开发者ID:1703011,项目名称:asuswrt-merlin,代码行数:72,


示例4: unlock_metapage

static inline void unlock_metapage(struct metapage *mp){	clear_bit_unlock(META_locked, &mp->flag);	wake_up(&mp->wait);}
开发者ID:325116067,项目名称:semc-qsd8x50,代码行数:5,


示例5: islpci_interrupt

//.........这里部分代码省略.........			/* device is in active state, update the			 * powerstate flag if necessary */			powerstate = ISL38XX_PSM_ACTIVE_STATE;			/* check all three queues in priority order			 * call the PIMFOR receive function until the			 * queue is empty */			if (isl38xx_in_queue(priv->control_block,						ISL38XX_CB_RX_MGMTQ) != 0) {#if VERBOSE > SHOW_ERROR_MESSAGES				DEBUG(SHOW_TRACING,				      "Received frame in Management Queue/n");#endif				islpci_mgt_receive(ndev);				islpci_mgt_cleanup_transmit(ndev);				/* Refill slots in receive queue */				islpci_mgmt_rx_fill(ndev);				/* no need to trigger the device, next                                   islpci_mgt_transaction does it */			}			while (isl38xx_in_queue(priv->control_block,						ISL38XX_CB_RX_DATA_LQ) != 0) {#if VERBOSE > SHOW_ERROR_MESSAGES				DEBUG(SHOW_TRACING,				      "Received frame in Data Low Queue/n");#endif				islpci_eth_receive(priv);			}			/* check whether the data transmit queues were full */			if (priv->data_low_tx_full) {				/* check whether the transmit is not full anymore */				if (ISL38XX_CB_TX_QSIZE -				    isl38xx_in_queue(priv->control_block,						     ISL38XX_CB_TX_DATA_LQ) >=				    ISL38XX_MIN_QTHRESHOLD) {					/* nope, the driver is ready for more network frames */					netif_wake_queue(priv->ndev);					/* reset the full flag */					priv->data_low_tx_full = 0;				}			}		}		if (reg & ISL38XX_INT_IDENT_INIT) {			/* Device has been initialized */#if VERBOSE > SHOW_ERROR_MESSAGES			DEBUG(SHOW_TRACING,			      "IRQ: Init flag, device initialized/n");#endif			wake_up(&priv->reset_done);		}		if (reg & ISL38XX_INT_IDENT_SLEEP) {			/* Device intends to move to powersave state */#if VERBOSE > SHOW_ERROR_MESSAGES			DEBUG(SHOW_TRACING, "IRQ: Sleep flag/n");#endif			isl38xx_handle_sleep_request(priv->control_block,						     &powerstate,						     priv->device_base);		}		if (reg & ISL38XX_INT_IDENT_WAKEUP) {			/* Device has been woken up to active state */#if VERBOSE > SHOW_ERROR_MESSAGES			DEBUG(SHOW_TRACING, "IRQ: Wakeup flag/n");#endif			isl38xx_handle_wakeup(priv->control_block,					      &powerstate, priv->device_base);		}	} else {#if VERBOSE > SHOW_ERROR_MESSAGES		DEBUG(SHOW_TRACING, "Assuming someone else called the IRQ/n");#endif		spin_unlock(&priv->slock);		return IRQ_NONE;	}	/* sleep -> ready */	if (islpci_get_state(priv) == PRV_STATE_SLEEP	    && powerstate == ISL38XX_PSM_ACTIVE_STATE)		islpci_set_state(priv, PRV_STATE_READY);	/* !sleep -> sleep */	if (islpci_get_state(priv) != PRV_STATE_SLEEP	    && powerstate == ISL38XX_PSM_POWERSAVE_STATE)		islpci_set_state(priv, PRV_STATE_SLEEP);	/* unlock the interrupt handler */	spin_unlock(&priv->slock);	return IRQ_HANDLED;}
开发者ID:303750856,项目名称:linux-3.1,代码行数:101,


示例6: mtdchar_erase_callback

/*======================================================================    IOCTL calls for getting device parameters.======================================================================*/static void mtdchar_erase_callback (struct erase_info *instr){	wake_up((wait_queue_head_t *)instr->priv);}
开发者ID:maraz,项目名称:linux-2.6,代码行数:9,


示例7: vfe_7x_ops

static void vfe_7x_ops(void *driver_data, unsigned id, size_t len,		void (*getevent)(void *ptr, size_t len)){	uint32_t evt_buf[3];	struct msm_vfe_resp *rp;	void *data;	len = (id == (uint16_t)-1) ? 0 : len;	data = resp->vfe_alloc(sizeof(struct msm_vfe_resp) + len, vfe_syncdata);	if (!data) {		pr_err("rp: cannot allocate buffer/n");		return;	}	rp = (struct msm_vfe_resp *)data;	rp->evt_msg.len = len;	if (id == ((uint16_t)-1)) {		/* event */		rp->type           = VFE_EVENT;		rp->evt_msg.type   = MSM_CAMERA_EVT;		getevent(evt_buf, sizeof(evt_buf));		rp->evt_msg.msg_id = evt_buf[0];		resp->vfe_resp(rp, MSM_CAM_Q_VFE_EVT, vfe_syncdata);	} else {		/* messages */		rp->evt_msg.type   = MSM_CAMERA_MSG;		rp->evt_msg.msg_id = id;		rp->evt_msg.data = rp + 1;		getevent(rp->evt_msg.data, len);		switch (rp->evt_msg.msg_id) {		case MSG_SNAPSHOT:			rp->type = VFE_MSG_SNAPSHOT;			break;		case MSG_OUTPUT1:			rp->type = VFE_MSG_OUTPUT1;			vfe_7x_convert(&(rp->phy), VFE_MSG_OUTPUT1,				rp->evt_msg.data, &(rp->extdata),				&(rp->extlen));			break;		case MSG_OUTPUT2:			rp->type = VFE_MSG_OUTPUT2;			vfe_7x_convert(&(rp->phy), VFE_MSG_OUTPUT2,					rp->evt_msg.data, &(rp->extdata),					&(rp->extlen));			break;		case MSG_STATS_AF:			rp->type = VFE_MSG_STATS_AF;			vfe_7x_convert(&(rp->phy), VFE_MSG_STATS_AF,					rp->evt_msg.data, NULL, NULL);			break;		case MSG_STATS_WE:			rp->type = VFE_MSG_STATS_WE;			vfe_7x_convert(&(rp->phy), VFE_MSG_STATS_WE,					rp->evt_msg.data, NULL, NULL);			CDBG("MSG_STATS_WE: phy = 0x%x/n", rp->phy.sbuf_phy);			break;		case MSG_STOP_ACK:			rp->type = VFE_MSG_GENERAL;			stopevent.state = 1;			wake_up(&stopevent.wait);			break;		default:			rp->type = VFE_MSG_GENERAL;			break;		}		resp->vfe_resp(rp, MSM_CAM_Q_VFE_MSG, vfe_syncdata);	}}
开发者ID:A2109devs,项目名称:lenovo_a2109a_kernel,代码行数:78,


示例8: InterfaceIdleModeRespond

int InterfaceIdleModeRespond(PMINI_ADAPTER Adapter, unsigned int* puiBuffer){    int	status = STATUS_SUCCESS;    unsigned int	uiRegRead = 0;    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"SubType of Message :0x%X", ntohl(*puiBuffer));    if(ntohl(*puiBuffer) == GO_TO_IDLE_MODE_PAYLOAD)    {        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL," Got GO_TO_IDLE_MODE_PAYLOAD(210) Msg Subtype");        if(ntohl(*(puiBuffer+1)) == 0 )        {            BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Got IDLE MODE WAKE UP Response From F/W");            status = wrmalt (Adapter,SW_ABORT_IDLEMODE_LOC, &uiRegRead, sizeof(uiRegRead));            if(status)            {                BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "wrm failed while clearing Idle Mode Reg");                return status;            }            if(Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING)            {                uiRegRead = 0x00000000 ;                status = wrmalt (Adapter,DEBUG_INTERRUPT_GENERATOR_REGISTOR, &uiRegRead, sizeof(uiRegRead));                if(status)                {                    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "wrm failed while clearing Idle Mode	Reg");                    return status;                }            }            //Below Register should not br read in case of Manual and Protocol Idle mode.            else if(Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)            {                //clear on read Register                status = rdmalt(Adapter, DEVICE_INT_OUT_EP_REG0, &uiRegRead, sizeof(uiRegRead));                if(status)                {                    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "rdm failed while clearing H/W Abort Reg0");                    return status;                }                //clear on read Register                status = rdmalt (Adapter, DEVICE_INT_OUT_EP_REG1, &uiRegRead, sizeof(uiRegRead));                if(status)                {                    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "rdm failed while clearing H/W Abort	Reg1");                    return status;                }            }            BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Device Up from Idle Mode");            // Set Idle Mode Flag to False and Clear IdleMode reg.            Adapter->IdleMode = FALSE;            Adapter->bTriedToWakeUpFromlowPowerMode = FALSE;            wake_up(&Adapter->lowpower_mode_wait_queue);#if 0            if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY)            {                BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"LED Thread is Running. Hence Setting the LED Event as IDLEMODE_EXIT");                Adapter->DriverState = IDLEMODE_EXIT;                wake_up(&Adapter->LEDInfo.notify_led_event);            }#endif        }        else        {            if(TRUE == Adapter->IdleMode)            {                BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Device is already in Idle mode....");                return status ;            }            uiRegRead = 0;            BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Got Req from F/W to go in IDLE mode /n");            if (Adapter->chip_id== BCS220_2 ||                    Adapter->chip_id == BCS220_2BC ||                    Adapter->chip_id== BCS250_BC ||                    Adapter->chip_id== BCS220_3)            {                status = rdmalt(Adapter, HPM_CONFIG_MSW, &uiRegRead, sizeof(uiRegRead));                if(status)                {                    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "rdm failed while Reading HPM_CONFIG_LDO145 Reg 0/n");                    return status;                }                uiRegRead |= (1<<17);                status = wrmalt (Adapter,HPM_CONFIG_MSW, &uiRegRead, sizeof(uiRegRead));                if(status)                {                    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "wrm failed while clearing Idle Mode Reg/n");                    return status;                }//.........这里部分代码省略.........
开发者ID:Claruarius,项目名称:stblinux-2.6.37,代码行数:101,


示例9: request_in_callback

/* * Server's incoming request callback */void request_in_callback(lnet_event_t *ev){	struct ptlrpc_cb_id		  *cbid = ev->md.user_ptr;	struct ptlrpc_request_buffer_desc *rqbd = cbid->cbid_arg;	struct ptlrpc_service_part	  *svcpt = rqbd->rqbd_svcpt;	struct ptlrpc_service	     *service = svcpt->scp_service;	struct ptlrpc_request	     *req;	LASSERT (ev->type == LNET_EVENT_PUT ||		 ev->type == LNET_EVENT_UNLINK);	LASSERT ((char *)ev->md.start >= rqbd->rqbd_buffer);	LASSERT ((char *)ev->md.start + ev->offset + ev->mlength <=		 rqbd->rqbd_buffer + service->srv_buf_size);	CDEBUG((ev->status == 0) ? D_NET : D_ERROR,	       "event type %d, status %d, service %s/n",	       ev->type, ev->status, service->srv_name);	if (ev->unlinked) {		/* If this is the last request message to fit in the		 * request buffer we can use the request object embedded in		 * rqbd.  Note that if we failed to allocate a request,		 * we'd have to re-post the rqbd, which we can't do in this		 * context. */		req = &rqbd->rqbd_req;		memset(req, 0, sizeof (*req));	} else {		LASSERT (ev->type == LNET_EVENT_PUT);		if (ev->status != 0) {			/* We moaned above already... */			return;		}		OBD_ALLOC_GFP(req, sizeof(*req), ALLOC_ATOMIC_TRY);		if (req == NULL) {			CERROR("Can't allocate incoming request descriptor: "			       "Dropping %s RPC from %s/n",			       service->srv_name,			       libcfs_id2str(ev->initiator));			return;		}	}	/* NB we ABSOLUTELY RELY on req being zeroed, so pointers are NULL,	 * flags are reset and scalars are zero.  We only set the message	 * size to non-zero if this was a successful receive. */	req->rq_xid = ev->match_bits;	req->rq_reqbuf = ev->md.start + ev->offset;	if (ev->type == LNET_EVENT_PUT && ev->status == 0)		req->rq_reqdata_len = ev->mlength;	do_gettimeofday(&req->rq_arrival_time);	req->rq_peer = ev->initiator;	req->rq_self = ev->target.nid;	req->rq_rqbd = rqbd;	req->rq_phase = RQ_PHASE_NEW;	spin_lock_init(&req->rq_lock);	INIT_LIST_HEAD(&req->rq_timed_list);	INIT_LIST_HEAD(&req->rq_exp_list);	atomic_set(&req->rq_refcount, 1);	if (ev->type == LNET_EVENT_PUT)		CDEBUG(D_INFO, "incoming [email
C++ wake_up_all函数代码示例
C++ wake_lock_timeout函数代码示例
万事OK自学网:51自学网_软件自学网_CAD自学网自学excel、自学PS、自学CAD、自学C语言、自学css3实例,是一个通过网络自主学习工作技能的自学平台,网友喜欢的软件自学网站。