uvc摄像头代码解析6

转 http://blog.csdn.net/orz415678659/article/details/10082003


10.扫描视频设备链和注册视频设备

10.1 uvc视频链

[cpp]  view plain  copy
  1. struct uvc_video_chain {    //uvc视频链  
  2.     struct uvc_device *dev;         //uvc设备  
  3.     struct list_head list;          //uvc视频链链表头  
  4.     struct list_head entities;      //uvc实体链表头  
  5.     struct uvc_entity *processing;  //处理Unit实体  
  6.     struct uvc_entity *selector;    //选择器Unit实体  
  7.     struct mutex ctrl_mutex;        /* Protects ctrl.info */  
  8. };  

10.2 uvc扫描设备

[cpp]  view plain  copy
  1. static int uvc_scan_device(struct uvc_device *dev)  
  2. {  
  3.     struct uvc_video_chain *chain;  //uvc视频链  
  4.     struct uvc_entity *term;    //uvc实体  
  5.   
  6.     list_for_each_entry(term, &dev->entities, list) {    //遍历全局实体链表  
  7.         if (!UVC_ENTITY_IS_OTERM(term)) //获取实体链表中的输出Terminal实体  
  8.             continue;  
  9.         if (term->chain.next || term->chain.prev) //已经添加到uvc视频链中了  
  10.             continue;  
  11.         chain = kzalloc(sizeof(*chain), GFP_KERNEL);    //分配uvc视频链内存(有多少个输入Terminal就有多少个uvc_video_chain)  
  12.         if (chain == NULL)  
  13.             return -ENOMEM;  
  14.         INIT_LIST_HEAD(&chain->entities);    //初始化视频链entities(实体)链表  
  15.         mutex_init(&chain->ctrl_mutex);  
  16.         chain->dev = dev;    //捆绑uvc视频链和uvc设备  
  17.         if (uvc_scan_chain(chain, term) < 0) {   //扫描uvc视频链(处理所有相关的输入pin)  
  18.             kfree(chain);  
  19.             continue;  
  20.         }  
  21.         uvc_trace(UVC_TRACE_PROBE, "Found a valid video chain (%s).\n",uvc_print_chain(chain));  
  22.         list_add_tail(&chain->list, &dev->chains);    //添加到uvc设备的uvc视频链链表  
  23.     }  
  24.     if (list_empty(&dev->chains)) {  
  25.         uvc_printk(KERN_INFO, "No valid video chain found.\n");  
  26.         return -1;  
  27.     }  
  28.     return 0;  
  29. }  

10.3 uvc扫描视频链

[cpp]  view plain  copy
  1. static int uvc_scan_chain(struct uvc_video_chain *chain,struct uvc_entity *term)  
  2. {  
  3.     struct uvc_entity *entity, *prev;  
  4.     uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain:");  
  5.     entity = term;  //获取实体  
  6.     prev = NULL;    //前一个实体  
  7.     while (entity != NULL) {  
  8.         /* Entity must not be part of an existing chain */  
  9.         if (entity->chain.next || entity->chain.prev) {   //已经添加到uvc视频链中了  
  10.             uvc_trace(UVC_TRACE_DESCR, "Found reference to entity %d already in chain.\n", entity->id);  
  11.             return -EINVAL;  
  12.         }  
  13.         /* Process entity */  
  14.         if (uvc_scan_chain_entity(chain, entity) < 0)    //扫描当前实体  
  15.             return -EINVAL;  
  16.         /* Forward scan */  
  17.         if (uvc_scan_chain_forward(chain, entity, prev) < 0) //向前扫描实体  
  18.             return -EINVAL;  
  19.         /* Backward scan */  
  20.         prev = entity;      //当前实体作为下一次while循环的前一个实体  
  21.         if (uvc_scan_chain_backward(chain, &entity) < 0) //向后扫描实体  
  22.             return -EINVAL;  
  23.     }  
  24.     return 0;  
  25. }  

将uvc视频链的输入实体添加到uvc视频链的entities链表中
将uvc视频链添加到uvc设备的chains链表中

10.3.1 扫描当前实体

[cpp]  view plain  copy
  1. static int uvc_scan_chain_entity(struct uvc_video_chain *chain,struct uvc_entity *entity)  
  2. {  
  3.     switch (UVC_ENTITY_TYPE(entity)) {  
  4.     case UVC_VC_EXTENSION_UNIT: //扩展Unit  
  5.         if (uvc_trace_param & UVC_TRACE_PROBE)  
  6.             printk(" <- XU %d", entity->id);  
  7.         if (entity->bNrInPins != 1) {  
  8.             uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has more than 1 input pin.\n", entity->id);  
  9.             return -1;  
  10.         }  
  11.         break;  
  12.     case UVC_VC_PROCESSING_UNIT:    //处理Unit  
  13.         if (uvc_trace_param & UVC_TRACE_PROBE)  
  14.             printk(" <- PU %d", entity->id);  
  15.         if (chain->processing != NULL) {  
  16.             uvc_trace(UVC_TRACE_DESCR, "Found multiple Processing Units in chain.\n");  
  17.             return -1;  
  18.         }  
  19.         chain->processing = entity;  //如果是处理Unit则设置其为uvc视频链的processing对象  
  20.         break;  
  21.     case UVC_VC_SELECTOR_UNIT:  //选择器Unit  
  22.         if (uvc_trace_param & UVC_TRACE_PROBE)  
  23.             printk(" <- SU %d", entity->id);  
  24.         /* Single-input selector units are ignored. */  
  25.         if (entity->bNrInPins == 1)  
  26.             break;  
  27.         if (chain->selector != NULL) {  
  28.             uvc_trace(UVC_TRACE_DESCR, "Found multiple Selector Units in chain.\n");  
  29.             return -1;  
  30.         }  
  31.         chain->selector = entity;    //如果是选择器Unit则设置其为uvc视频链的selector对象  
  32.         break;  
  33.     case UVC_ITT_VENDOR_SPECIFIC:   //厂商特殊  
  34.     case UVC_ITT_CAMERA:    //输入Terminal camera  
  35.     case UVC_ITT_MEDIA_TRANSPORT_INPUT: //输入Terminal Media transport  
  36.         if (uvc_trace_param & UVC_TRACE_PROBE)  
  37.             printk(" <- IT %d\n", entity->id);  
  38.         break;  
  39.     case UVC_TT_STREAMING:  //输入Terminal stream  
  40.         if (UVC_ENTITY_IS_ITERM(entity)) {  
  41.             if (uvc_trace_param & UVC_TRACE_PROBE)  
  42.                 printk(" <- IT %d\n", entity->id);  
  43.         }   
  44.         else {  
  45.             if (uvc_trace_param & UVC_TRACE_PROBE)  
  46.                 printk(" OT %d", entity->id);  
  47.         }  
  48.         break;  
  49.     default:  
  50.         uvc_trace(UVC_TRACE_DESCR, "Unsupported entity type 0x%04x found in chain.\n", UVC_ENTITY_TYPE(entity));  
  51.         return -1;  
  52.     }  
  53.     list_add_tail(&entity->chain, &chain->entities);  //添加到uvc视频链的实体链表  
  54.     return 0;  
  55. }  

10.3.2 向前扫描实体

[cpp]  view plain  copy
  1. static int uvc_scan_chain_forward(struct uvc_video_chain *chain,struct uvc_entity *entity, struct uvc_entity *prev)  
  2. {  
  3.     struct uvc_entity *forward;  
  4.     int found;  
  5.     /* Forward scan */  
  6.     forward = NULL;  
  7.     found = 0;  
  8.     while (1) { //获取实体前面的所以实体处理直到前面的实体forward=NULL为止跳出死循环  
  9.         forward = uvc_entity_by_reference(chain->dev, entity->id,forward);    //获取前一个实体  
  10.         if (forward == NULL)  
  11.             break;  
  12.         if (forward == prev)  
  13.             continue;  
  14.         switch (UVC_ENTITY_TYPE(forward)) {  
  15.         case UVC_VC_EXTENSION_UNIT: //扩展Unit  
  16.             if (forward->bNrInPins != 1) {  
  17.                 uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has more than 1 input pin.\n",entity->id);  
  18.                 return -EINVAL;  
  19.             }  
  20.             list_add_tail(&forward->chain, &chain->entities); //添加uvc实体到uvc视频链的entities中  
  21.             if (uvc_trace_param & UVC_TRACE_PROBE) {  
  22.                 if (!found)  
  23.                     printk(" (->");  
  24.                 printk(" XU %d", forward->id);  
  25.                 found = 1;  
  26.             }  
  27.             break;  
  28.         case UVC_OTT_VENDOR_SPECIFIC:   //厂商特殊  
  29.         case UVC_OTT_DISPLAY:   //输出Termianl display  
  30.         case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:    //输出Terminal media transport  
  31.         case UVC_TT_STREAMING: //输出Terminal stream  
  32.             if (UVC_ENTITY_IS_ITERM(forward)) {  
  33.                 uvc_trace(UVC_TRACE_DESCR, "Unsupported input terminal %u.\n", forward->id);  
  34.                 return -EINVAL;  
  35.             }  
  36.             list_add_tail(&forward->chain, &chain->entities); //添加uvc实体到uvc视频链的entities中  
  37.             if (uvc_trace_param & UVC_TRACE_PROBE) {  
  38.                 if (!found)  
  39.                     printk(" (->");  
  40.                 printk(" OT %d", forward->id);  
  41.                 found = 1;  
  42.             }  
  43.             break;  
  44.         }  
  45.     }  
  46.     if (found)  
  47.         printk(")");  
  48.     return 0;  
  49. }  

10.3.3 向后扫描实体

[cpp]  view plain  copy
  1. static int uvc_scan_chain_backward(struct uvc_video_chain *chain,struct uvc_entity **_entity)  
  2. {  
  3.     struct uvc_entity *entity = *_entity;  
  4.     struct uvc_entity *term;  
  5.     int id = -EINVAL, i;  
  6.     switch (UVC_ENTITY_TYPE(entity)) {  
  7.     case UVC_VC_EXTENSION_UNIT: //扩展Unit  
  8.     case UVC_VC_PROCESSING_UNIT:    //处理Unit处理Unit的输入Terminal个数只能为1  
  9.         id = entity->baSourceID[0];  //获取输入pin(Unit/Terminal)的ID  
  10.         break;  
  11.     case UVC_VC_SELECTOR_UNIT:  //选择器实体  
  12.         /* Single-input selector units are ignored. */  
  13.         if (entity->bNrInPins == 1) {    //若输入pin个数为1  
  14.             id = entity->baSourceID[0];  //获取输入in(Unit/Terminal)的ID  
  15.             break;  
  16.         }  
  17.         if (uvc_trace_param & UVC_TRACE_PROBE)  
  18.             printk(" <- IT");  
  19.         chain->selector = entity;    //uvc视频链的selector对象指向uvc实体  
  20.         for (i = 0; i < entity->bNrInPins; ++i) { //总共有多少个输入pin  
  21.             id = entity->baSourceID[i];  //获取输入in(Unit/Terminal)的ID  
  22.             term = uvc_entity_by_id(chain->dev, id); //获取对应的输入pin实体  
  23.             if (term == NULL || !UVC_ENTITY_IS_ITERM(term)) {  
  24.                 uvc_trace(UVC_TRACE_DESCR, "Selector unit %d input %d isn't connected to an input terminal\n", entity->id, i);  
  25.                 return -1;  
  26.             }  
  27.             if (uvc_trace_param & UVC_TRACE_PROBE)  
  28.                 printk(" %d", term->id);  
  29.             list_add_tail(&term->chain, &chain->entities);    //添加uvc实体到uvc视频链的entities链表  
  30.             uvc_scan_chain_forward(chain, term, entity);    //向前扫描实体  
  31.         }  
  32.         if (uvc_trace_param & UVC_TRACE_PROBE)  
  33.             printk("\n");  
  34.         id = 0;  
  35.         break;  
  36.     case UVC_ITT_VENDOR_SPECIFIC:  
  37.     case UVC_ITT_CAMERA:  
  38.     case UVC_ITT_MEDIA_TRANSPORT_INPUT:  
  39.     case UVC_OTT_VENDOR_SPECIFIC:  
  40.     case UVC_OTT_DISPLAY:  
  41.     case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:  
  42.     case UVC_TT_STREAMING:  
  43.         id = UVC_ENTITY_IS_OTERM(entity) ? entity->baSourceID[0] : 0;  
  44.         break;  
  45.     }  
  46.     if (id <= 0) {  
  47.         *_entity = NULL;  
  48.         return id;  
  49.     }  
  50.     entity = uvc_entity_by_id(chain->dev, id);  
  51.     if (entity == NULL) {  
  52.         uvc_trace(UVC_TRACE_DESCR, "Found reference to unknown entity %d.\n", id);  
  53.         return -EINVAL;  
  54.     }  
  55.     *_entity = entity;  
  56.     return 0;  
  57. }  

注意到trace打印的语句会发现有一条

[cpp]  view plain  copy
  1. uvcvideo: Scanning UVC chain: OT 2 <- XU 5 <- XU 4 <- PU 3 <- IT 1  

可以看到这些Unit和Terminal是如何组建起来的

这里补充一下:

1.打开trace:echo 0xffff > /sys/module/uvcvideo/par 消息用dmesg查看,清除dmesg信息带上-c参数就行

2.留意之前lsusb打印出来的描述符表,对应的bTerminalID就是trace打印信息中对应的Unit或Terminal的数字,而baSourceID则是它的前一级Unit或Terminal的ID号

10.3.4 添加链表

list_add_tail(&entity->chain, &chain->entities);



11.注册uvc视频链

11.1 uvc注册视频链

[cpp]  view plain  copy
  1. static int uvc_register_chains(struct uvc_device *dev)  
  2. {  
  3.     struct uvc_video_chain *chain;  
  4.     int ret;  
  5.     list_for_each_entry(chain, &dev->chains, list) { //遍历uvc设备的uvc视频链链表  
  6.         ret = uvc_register_terms(dev, chain);   //注册uvc视频链  
  7.         if (ret < 0)  
  8.             return ret;  
  9.     }  
  10.     return 0;  
  11. }  

11.2 uvc注册实体

[cpp]  view plain  copy
  1. static int uvc_register_terms(struct uvc_device *dev,struct uvc_video_chain *chain)  
  2. {  
  3.     struct uvc_streaming *stream;  
  4.     struct uvc_entity *term;  
  5.     int ret;  
  6.     list_for_each_entry(term, &chain->entities, chain) { //遍历uvc视频链的uvc实体链表  
  7.         if (UVC_ENTITY_TYPE(term) != UVC_TT_STREAMING)  //不是输入Terminal streaming类型  
  8.             continue;  
  9.         stream = uvc_stream_by_id(dev, term->id);    //获取uvc视频流  
  10.         if (stream == NULL) {  
  11.             uvc_printk(KERN_INFO, "No streaming interface found for terminal %u.", term->id);  
  12.             continue;  
  13.         }  
  14.         stream->chain = chain;   //捆绑uvc视频流和uvc视频链  
  15.         ret = uvc_register_video(dev, stream);  //注册uvc视频流  
  16.         if (ret < 0)  
  17.             return ret;  
  18.     }  
  19.     return 0;  
  20. }  

11.3 uvc注册视频

[cpp]  view plain  copy
  1. static int uvc_register_video(struct uvc_device *dev,struct uvc_streaming *stream)  
  2. {  
  3.     struct video_device *vdev;  
  4.     int ret;  
  5.     /* Initialize the streaming interface with default streaming parameters.*/  
  6.     ret = uvc_video_init(stream);   //13.uvc视频初始化  
  7.     if (ret < 0) {  
  8.         uvc_printk(KERN_ERR, "Failed to initialize the device (%d).\n", ret);  
  9.         return ret;  
  10.     }  
  11.     /* Register the device with V4L. */  
  12.     vdev = video_device_alloc();    //分配v4l2设备内存  
  13.     if (vdev == NULL) {  
  14.         uvc_printk(KERN_ERR, "Failed to allocate video device (%d).\n",ret);  
  15.         return -ENOMEM;  
  16.     }  
  17.     vdev->parent = &dev->intf->dev;    //v4l2设备的父设备为usb接口设备  
  18.     vdev->fops = &uvc_fops;  //v4l2操作函数集  
  19.     vdev->release = uvc_release; //释放方法  
  20.     strlcpy(vdev->name, dev->name, sizeof vdev->name); //设置名字  
  21.     stream->vdev = vdev; //捆绑uvc视频流和v4l2设备  
  22.     video_set_drvdata(vdev, stream);    //将uvc视频流作为v4l2设备的驱动数据  
  23.     ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);    //注册v4l2设备  
  24.     if (ret < 0) {  
  25.         uvc_printk(KERN_ERR, "Failed to register video device (%d).\n",ret);  
  26.         stream->vdev = NULL;  
  27.         video_device_release(vdev);  
  28.         return ret;  
  29.     }  
  30.     atomic_inc(&dev->nstreams);  
  31.     return 0;  
  32. }  

12.uvc设备状态初始化

uvc状态的处理由中断端点来控制处理

[cpp]  view plain  copy
  1. int uvc_status_init(struct uvc_device *dev)  
  2. {  
  3.     struct usb_host_endpoint *ep = dev->int_ep;  //获取usb_host_endpoint  
  4.     unsigned int pipe;  
  5.     int interval;  
  6.     if (ep == NULL)  
  7.         return 0;  
  8.     uvc_input_init(dev);    //初始化uvc输入设备  
  9.     dev->status = kzalloc(UVC_MAX_STATUS_SIZE, GFP_KERNEL);  //分配uvc设备状态内存  
  10.     if (dev->status == NULL)  
  11.         return -ENOMEM;  
  12.     dev->int_urb = usb_alloc_urb(0, GFP_KERNEL); //分配urb  
  13.     if (dev->int_urb == NULL) {  
  14.         kfree(dev->status);  
  15.         return -ENOMEM;  
  16.     }  
  17.     pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress);  //中断输入端点  
  18.     interval = ep->desc.bInterval;   //获取间隔  
  19.     if (interval > 16 && dev->udev->speed == USB_SPEED_HIGH &&(dev->quirks & UVC_QUIRK_STATUS_INTERVAL))    //高速设备  
  20.         interval = fls(interval) - 1;  
  21.     usb_fill_int_urb(dev->int_urb, dev->udev, pipe,dev->status, UVC_MAX_STATUS_SIZE, uvc_status_complete,dev, interval);   //填充中断urb  
  22.     return 0;  
  23. }  

这里只填充了urb信息,urb的提交请参看14.2.2.1 uvc_status_start启动状态,在打开uvc的V4L2设备方法时调用

12.1 初始化uvc输入事件

[cpp]  view plain  copy
  1. static int uvc_input_init(struct uvc_device *dev)  
  2. {  
  3.     struct input_dev *input;  
  4.     int ret;  
  5.     input = input_allocate_device();    //分配input设备内存  
  6.     if (input == NULL)  
  7.         return -ENOMEM;  
  8.     usb_make_path(dev->udev, dev->input_phys, sizeof(dev->input_phys));    //设备节点路径  
  9.     strlcat(dev->input_phys, "/button"sizeof(dev->input_phys));  
  10.     input->name = dev->name;  //输入设备名  
  11.     input->phys = dev->input_phys;    //输入设备节点路径  
  12.     usb_to_input_id(dev->udev, &input->id);  
  13.     input->dev.parent = &dev->intf->dev;   //输入设备的父设备为usb接口设备  
  14.     __set_bit(EV_KEY, input->evbit); //设置输入事件类型  
  15.     __set_bit(KEY_CAMERA, input->keybit);    //设置按钮  
  16.     if ((ret = input_register_device(input)) < 0)    //注册input设备  
  17.         goto error;  
  18.     dev->input = input;  //uvc设备捆绑输入设备  
  19.     return 0;  
  20. error:  
  21.     input_free_device(input);  
  22.     return ret;  
  23. }  

12.2 urb回调函数

[cpp]  view plain  copy
  1. static void uvc_status_complete(struct urb *urb)  
  2. {  
  3.     struct uvc_device *dev = urb->context;  
  4.     int len, ret;  
  5.     switch (urb->status) {  
  6.     case 0:  
  7.         break;  
  8.     case -ENOENT:       /* usb_kill_urb() called. */  
  9.     case -ECONNRESET:   /* usb_unlink_urb() called. */  
  10.     case -ESHUTDOWN:    /* The endpoint is being disabled. */  
  11.     case -EPROTO:       /* Device is disconnected (reported by some host controller). */  
  12.         return;  
  13.     default:  
  14.         uvc_printk(KERN_WARNING, "Non-zero status (%d) in status completion handler.\n", urb->status);  
  15.         return;  
  16.     }  
  17.     len = urb->actual_length;  
  18.     if (len > 0) {  
  19.         switch (dev->status[0] & 0x0f) {  
  20.         case UVC_STATUS_TYPE_CONTROL:   //VC事件  
  21.             uvc_event_control(dev, dev->status, len);    //Table 2-2 Status Packet Format (VideoControl Interface as the Originator)  
  22.             break;  
  23.         case UVC_STATUS_TYPE_STREAMING: //VS事件  
  24.             uvc_event_streaming(dev, dev->status, len);  //Table 2-3 Status Packet Format (VideoStreaming Interface as the Originator)  
  25.             break;  
  26.         default  
  27.             uvc_trace(UVC_TRACE_STATUS, "Unknown status event type %u.\n", dev->status[0]);  
  28.             break;  
  29.         }  
  30.     }  
  31.     /* Resubmit the URB. */  
  32.     urb->interval = dev->int_ep->desc.bInterval;  
  33.     if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {   //提交urb  
  34.         uvc_printk(KERN_ERR, "Failed to resubmit status URB (%d).\n",ret);  
  35.     }  
  36. }  

12.2.1 VC状态变化事件处理

[cpp]  view plain  copy
  1. static void uvc_event_control(struct uvc_device *dev, __u8 *data, int len)  
  2. {  
  3.     char *attrs[3] = { "value""info""failure" };  
  4.     if (len < 6 || data[2] != 0 || data[4] > 2) {//长度应该为6,且data[2](bEvent)为0表示(Control Change),data[4]大于2部分为保留值  
  5.         uvc_trace(UVC_TRACE_STATUS, "Invalid control status event received.\n");  
  6.         return;  
  7.     }  
  8.     uvc_trace(UVC_TRACE_STATUS, "Control %u/%u %s change len %d.\n",data[1], data[3], attrs[data[4]], len);  
  9. }  

12.2.2 VS状态变化事件处理

[cpp]  view plain  copy
  1. static void uvc_event_streaming(struct uvc_device *dev, __u8 *data, int len)  
  2. {  
  3.     if (len < 3) {   //长度等于4  
  4.         uvc_trace(UVC_TRACE_STATUS, "Invalid streaming status event received.\n");  
  5.         return;  
  6.     }  
  7.     if (data[2] == 0) { //data[2](bevent)--0x00(Button Press)摄像头上的按钮按下  
  8.         if (len < 4)  
  9.             return;  
  10.         uvc_trace(UVC_TRACE_STATUS, "Button (intf %u) %s len %d\n",data[1], data[3] ? "pressed" : "released", len);  
  11.         uvc_input_report_key(dev, KEY_CAMERA, data[3]); //上报按键事件  
  12.     }   
  13.     else {  
  14.         uvc_trace(UVC_TRACE_STATUS, "Stream %u error event %02x %02x ""len %d.\n", data[1], data[2], data[3], len);  
  15.     }  
  16. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值