PCI总线体系结构概述

§1.PCI总线体系结构概述 
PCI总线体系结构是一种层次式的(Hierarchical)体系结构。在这种层次式体系结构中,PCI桥设备占据着重要的地位,它将父总线与子总线连接在一起,从而使整个系统看起来像一颗倒置的树型结构。树的顶端是系统的CPU,它通过一个较为特殊的PCI桥设备——Host/PCI桥设备与根PCI总线(root pci bus)连接起来。下图1是一个较为典型的PCI总线体系结构图。 
(图1) 
从上图也可以看出,作为一种特殊的PCI设备,PCI桥又包括以下几种: 
(1)Host/PCI桥:用于连接CPU与PCI根总线(注意,the first root bus总是编号为0)。由于像Memory Controller这样的设备通常也被集成到Host/PCI桥设备芯片中,因此,Host/PCI桥通常也被称为“北桥芯片组(North Bridge Chipset)”。 
(2)PCI/ISA桥:用于连接遗留的ISA总线。通常,像i8359A中断控制器这样的设备也会被集成到PCI/ISA桥设备中,因此,PCI/ISA桥通常也被称为“南桥芯片组(South Bridge Chipset)”。 
(3)PCI-to-PCI桥:用于连接PCI主总线(primary bus)与次总线(secondary bus)。PCI桥所处的PCI总线称为“主总线”(即次总线的父总线),桥设备所连接的PCI总线称为“次总线”(即主总线的子总线)。 
更多类型的PCI桥分类可以参见《PCI Local Bus Specification》Revision2.2的附录D。 
本文以下部分假设读者对PCI总线规范有一定的了解,因此本文是为那些想要深入了解Linux内核是如何实现PCI总线驱动程序的Kernel Hacker而写的。 

§2 PCI总线驱动程序的核心数据结构 
从前面的图1可以看出,在PCI总线体系结构中,有两个核心的概念存在:PCI总线和PCI设备(桥设备是一种特殊的PCI设备)。基于对这两个核心概念的抽象,Linux PCI总线驱动程序定义了两个关键的数据结构:结构类型pci_bus和结构类型pci_dev,以分别描述pci总线和pci设备。在此基础上,Linux PCI总线驱动程序又将系统中当前存在的所有PCI总线的pci_bus结构组织成一张层次式的链表图,显然该链表图的顶层链表是系统中所有根总线的pci_bus结构链表,因此用一个list_head结构类型的全局变量pci_root_buses来描述该链表图中的顶层链表表头,也即根总线链表的表头。系统中当前存在的所有PCI设备的pci_dev结构也被组织成一条链表,称为“全局pci设备链表”,用一个list_head结构类型的变量pci_devices来表示该链表的表头。通过这两条总链表,Linux内核就可以得到一张当前系统的PCI总线体系结构视图。 

§2.1 PCI设备描述符——pci_dev结构类型 
所有种类的PCI设备都可以用结构类型pci_dev来描述。更为准确地说,应该是每一个PCI功能,即PCI逻辑设备都唯一地对应有一个pci_dev设备描述符。该数据结构的定义如下(include/linux/pci.h): 
/* 
* The pci_dev structure is used to describe both PCI and ISAPnP devices. 
*/ 
struct pci_dev { 
struct list_head global_list; /* node in list of all PCI devices */ 
struct list_head bus_list; /* node in per-bus list */ 
struct pci_bus *bus; /* bus this device is on */ 
struct pci_bus *subordinate; /* bus this device bridges to */ 

void *sysdata; /* hook for sys-specific extension */ 
struct proc_dir_entry *procent; /* device entry in /proc/bus/pci */ 

unsigned int devfn; /* encoded device & function index */ 
unsigned short vendor; 
unsigned short device; 
unsigned short subsystem_vendor; 
unsigned short subsystem_device; 
unsigned int class; /* 3 bytes: (base,sub,prog-if) */ 
u8 hdr_type; /* PCI header type (`multi' flag masked out) */ 
u8 rom_base_reg; /* which config register controls the ROM */ 

struct pci_driver *driver; /* which driver has allocated this device */ 
void *driver_data; /* data private to the driver */ 
dma_addr_t dma_mask; /* Mask of the bits of bus address this 
device implements. Normally this is 
0xffffffff. You only need to change 
this if your device has broken DMA 
or supports 64-bit transfers. */ 

/* device is compatible with these IDs */ 
unsigned short vendor_compatible[DEVICE_COUNT_COMPATIBLE]; 
unsigned short device_compatible[DEVICE_COUNT_COMPATIBLE]; 

/* 
* Instead of touching interrupt line and base address registers 
* directly, use the values stored here. They might be different! 
*/ 
unsigned int irq; 
struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */ 
struct resource dma_resource[DEVICE_COUNT_DMA]; 
struct resource irq_resource[DEVICE_COUNT_IRQ]; 

char name[80]; /* device name */ 
char slot_name[8]; /* slot name */ 
int active; /* ISAPnP: device is active */ 
int ro; /* ISAPnP: read only */ 
unsigned short regs; /* ISAPnP: supported registers */ 

int (*prepare)(struct pci_dev *dev); /* ISAPnP hooks */ 
int (*activate)(struct pci_dev *dev); 
int (*deactivate)(struct pci_dev *dev); 
}; 
各成员的含义如下: 
(1)全局链表元素global_list:每一个pci_dev结构都通过该成员连接到全局pci设备链表pci_devices中。 
(2)总线设备链表元素bus_list:每一个pci_dev结构除了链接到全局设备链表中外,还会通过这个成员连接到其所属PCI总线的设备链表中。每一条PCI总线都维护一条它自己的设备链表视图,以便描述所有连接在该PCI总线上的设备,其表头由PCI总线的pci_bus结构中的devices成员所描述。 
(3)总线指针bus:指向这个PCI设备所在的PCI总线的pci_bus结构。因此,对于桥设备而言,bus指针将指向桥设备的主总线(primary bus),也即指向桥设备所在的PCI总线。 
(4)指针subordinate:指向这个PCI设备所桥接的下级总线。这个指针成员仅对桥设备才有意义,而对于一般的非桥PCI设备而言,该指针成员总是为NULL。 
(5)无类型指针sysdata:指向一片特定于系统的扩展数据。 
(6)指针procent:指向该PCI设备在/proc文件系统中对应的目录项。 
(7)devfn:这个PCI设备的设备功能号,也成为PCI逻辑设备号(0-255)。其中bit[7:3]是物理设备号(取值范围0-31),bit[2:0]是功能号(取值范围0-7)。 
(8)vendor:这是一个16无符号整数,表示PCI设备的厂商ID。 
(9)device:这是一个16无符号整数,表示PCI设备的设备ID。 
(10)subsystem_vendor:这是一个16无符号整数,表示PCI设备的子系统厂商ID。 
(11)subsystem_device:这是一个16无符号整数,表示PCI设备的子系统设备ID。 
(12)class:32位的无符号整数,表示该PCI设备的类别,其中,bit[7:0]为编程接口,bit[15:8]为子类别代码,bit[23:16]为基类别代码,bit[31:24]无意义。显然,class成员的低3字节刚好对应与PCI配置空间中的类代码。 
(13)hdr_type:8位符号整数,表示PCI配置空间头部的类型。其中,bit[7]=1表示这是一个多功能设备,bit[7]=0表示这是一个单功能设备。Bit[6:0]则表示PCI配置空间头部的布局类型,值00h表示这是一个一般PCI设备的配置空间头部,值01h表示这是一个PCI-to-PCI桥的配置空间头部,值02h表示CardBus桥的配置空间头部。 
(14)rom_base_reg:8位无符号整数,表示PCI配置空间中的ROM基地址寄存器在PCI配置空间中的位置。ROM基地址寄存器在不同类型的PCI配置空间头部的位置是不一样的,对于type 0的配置空间布局,ROM基地址寄存器的起始位置是30h,而对于PCI-to-PCI桥所用的type 1配置空间布局,ROM基地址寄存器的起始位置是38h。 
(15)指针driver:指向这个PCI设备所对应的驱动程序定义的pci_driver结构。每一个pci设备驱动程序都必须定义它自己的pci_driver结构来描述它自己。这个数据结构将在后面分析。 
(16)无类型指针driver_data:指向驱动程序为这个PCI设备所分配的一块私有数据区。通常,设备驱动程序会为它所支持的每一种设备类型定义一个特定于设备类型的数据结构,以描述该类型设备的信息。而且,driver会为它所找到的每一个设备实例分配一个特定于该设备类型的数据结构实例。指针driver_data一般就用来指向这个有驱动程序所分配的数据结构实例。 
(17)dma_mask:用于DMA的总线地址掩码,一般来说,这个成员的值是0xffffffff。数据类型dma_addr_t定义在include/asm/types.h中,在x86平台上,dma_addr_t类型就是u32类型。 
(18)vendor_compatible[DEVICE_COUNT_COMPATIBLE]和device_compatible[DEVICE_COUNT_COMPATIBLE]:定义这个PCI设备与哪些设备相兼容。 
(19)无符号的整数irq:表示这个PCI设备通过哪根IRQ输入线产生中断,一般为0-15之间的某个值。 
(20)资源数组resource[DEVICE_COUNT_RESOURCE]:表示该设备可能用到的资源,包括:I/O断口区域、设备内存地址区域以及扩展ROM地址区域。宏DEVICE_COUNT_DEVICE在pci.h头文件中被定义为常值12。但是PCI设备通常仅使用这12各资源区域中的一部分。其中,resource[5:0]分别对应于配置空间中的BAR0-BAR5(注意,桥设备只有BAR0和BAR1),resource[6]对应于配置空间中的ROM基地址寄存器所描述的ROM区域,而resource[10:7]分别对应于桥设备的地址过滤窗口。 
(21)数组dma_resource[DEVICE_COUNT_DMA]:用于DMA的资源,DEVICE_COUNT_DMA为2。 
(22)数组irq_resource[DEVICE_COUNT_IRQ]:用于IRQ的资源,DEVICE_COUNT_IRQ为2。 
(23)name[80]数组:定义这个PCI逻辑设备的名字字符串。 
(24)slot_name[8]数组:如果这个PCI逻辑设备是通过PCI插槽连接到PCI总线上的,则slot_name数组表示该插槽的名字字符串。 
(25)active:被ISAPnP模块用来表示设备是否被激活。 
(26)ro:被ISAPnP模块用来表示设备是否为只读设备。 
(27)regs:被ISAPnP模块用来表示设备设备所支持的寄存器个数。 
(28)函数指针prepare、activate和deactivate:都是仅被ISAPnP模块钩挂的函数指针。 

§2.2 PCI总线描述符——pci_bus结构类型 
该结构定义在include/linux/pci.h头文件中,如下所示: 
struct pci_bus { 
struct list_head node; /* node in list of buses */ 
struct pci_bus *parent; /* parent bus this bridge is on */ 
struct list_head children; /* list of child buses */ 
struct list_head devices; /* list of devices on this bus */ 
struct pci_dev *self; /* bridge device as seen by parent */ 
struct resource *resource[4]; /* address space routed to this bus */ 

struct pci_ops *ops; /* configuration access functions */ 
void *sysdata; /* hook for sys-specific extension */ 
struct proc_dir_entry *procdir; /* directory entry in /proc/bus/pci */ 

unsigned char number; /* bus number */ 
unsigned char primary; /* number of primary bridge */ 
unsigned char secondary; /* number of secondary bridge */ 
unsigned char subordinate; /* max number of subordinate buses */ 

char name[48]; 
unsigned short vendor; 
unsigned short device; 
unsigned int serial; /* serial number */ 
unsigned char pnpver; /* Plug & Play version */ 
unsigned char productver; /* product version */ 
unsigned char checksum; /* if zero - checksum passed */ 
unsigned char pad1; 
}; 
各成员的含义如下: 
(1)链表元素node:对于PCI根总线而言,其pci_bus结构通过node成员链接到本节一开始所述的根总线链表中,根总线链表的表头由一个list_head类型的全局变量pci_root_buses所描述。而对于非根pci总线,其pci_bus结构通过node成员链接到其父总线的子总线链表children中(见下面)。 
(2)parent指针:指向该pci总线的父总线,即pci桥所在的那条总线。 
(3)children指针:描述了这条PCI总线的子总线链表的表头。这条PCI总线的所有子总线都通过上述的node链表元素链接成一条子总线链表,而该链表的表头就由父总线的children指针所描述。 
(4)devices链表头:描述了这条PCI总线的逻辑设备链表的表头。除了链接在全局PCI设备链表中之外,每一个PCI逻辑设备也通过其pci_dev结构中的bus_list成员链入其所在PCI总线的局部设备链表中,而这个局部的总线设备链表的表头就由pci_bus结构中的devices成员所描述。 
(5)指针self:指向引出这条PCI总线的桥设备的pci_dev结构。 
(6)资源指针数组resource[4]:指向应路由到这条pci总线的地址空间资源,通常是指向对应桥设备的pci_dev结构中的资源数组resource[10:7]。 
(7)指针ops:指向一个pci_ops结构,表示这条pci总线所使用的配置空间访问函数。下一节将详细讨论这个数据结构。 
(8)无类型指针sysdata:指向系统特定的扩展数据。 
(9)指针procdir:指向该PCI总线在/proc文件系统中对应的目录项。 
(10)number:这条PCI总线的总线编号(bus number),取值范围0-255。 
(11)primary:表示引出这条PCI总线的“桥设备的主总线”(也即桥设备所在的PCI总线)编号,取值范围0-255。 
(12)secondary:表示引出这条PCI总线的桥设备的次总线号,因此secondary成员总是等于number成员的值。取值范围0-255。 
(13)subordinate:这条PCI总线的下属PCI总线(Subordinate pci bus)的总线编号最大值,它应该等于引出这条PCI总线的桥设备的subordinate值。 
(13)name[48]:这条PCI总线的名字字符串。 
(14)vendor和device:表示引出这条PCI总线的桥设备的厂商ID和设备ID。 
(15)serial:系列号。 
(16)pnpver:Plug&Play版本号。 
(17)productver:产品版本号。 
(18)chechsum:pci_bus结构的校验和,因改为0。 
(19)pad1:为了使pci_bus结构的大小沿内存边界对齐而设立的成员,无实际意义。 
下面对上述结构中的总线编号进行一下说明。假定这样一个PCI总线体系结构:根总线0上有一个PCI桥,它引出子总线bus 1,bus 1上又有一个PCI桥引出bus 2,如下图2所示: 
(图2) 
PCI桥的配置空间头部中定义桥两侧的主、次总线编号,以及桥后面的下级总线编号的最大可能值。因此在上图中,bus 0总线的pci_bus结构中的number、primary、secondary都应该为0,因为它是通过Host/PCI桥引出的根总线;而bus 1总线的pci_bus结构中的number=secondary=1,而bus 1的primary应该为0;而bus 2总线的pci_bus结构中的number=secondary=2,其primary则应该等于1。这三条总线的subordinate值都应该等于2。 

§2.3 PCI设备链表 
前面已经讲过,所有的PCI设备都通过其pci_dev结构中的global_list成员链接一条“全局pci设备链表”pci_devices,表头pci_devices定义在drivers/pci/pci.c文件中: 
LIST_HEAD(pci_device); 
另外,同属一条PCI总线上的所有PCI设备也通过其pci_dev结构中的bus_list成员链接成一条局部这条PCI总线的“总线设备链表”,表头则由该PCI总线的pci_bus结构中的devices成员所定义。 
下图3描述可以很清楚地描述可以很清楚地描述上述这两重链表的关系 
(图3) 
■遍历PCI设备链表的辅助宏 
为了更为方便地遍历上述两类PCI设备链表(全局PCI设备链表和局部总线设备链表),Linux在头文件中pci.h定义了几个辅助宏,从而使得遍历链表的代码更为简单、易懂。它们是: 
(1)宏pci_for_each_dev(dev):正向遍历全局设备链表pce_devices中的每一个PCI 设备,参数dev是一个pci_dev结构类型的指针。 其定义如下: 
#define pci_for_each_dev(dev) \ 
for(dev=pci_dev_g(pci_devices.next);dev!=pci_dev_g(&pci_devices);dev=pci_dev_g(dev->global_list.next)) 
上述定义中的宏pci_dev_g()用于将一个list_head类型的指针转换为一个pci_dev类型的指针(下面谈及)。对这个宏的典型使用方法如下所示: 
pci_dev *dev; 
…… 
pci_for_each_dev(dev) 

……/* 对dev所指向的每一个pci设备进行处理 */ 
} 
(2)宏pci_for_each_dev_reverse(dev):逆向遍历全局设备链表pci_devices中的每一个pci设备。参数dev同样也是一个pci_dev结构类型的指针。其定义如下: 
#define pci_for_each_dev_reverse(dev) \ 
for(dev=pci_dev_g(pci_devices.prev);dev!=pci_dev_g(&pci_devices);dev=pci_dev_g(dev->global_list.prev)) 
显然,上述宏将从全局设备链表中的最后一个元素(由pci_devices.prev所指向)开始逆向遍历整个链表。该宏的使用与pci_for_each_dev()宏相同,只是遍历方向相反而已。 
(3)宏pci_dev_g(n)和pci_dev_b(n):宏pci_dev_g()用来将与全局设备链表对应的list_head类型指针n转换为pci_dev类型的指针,宏pci_dev_b()用来将与总线局部设备链表对应的list_head类型指针n转换为pci_dev类型的指针。实际上,它们都是通过list_entry()宏来实现实际的转换工作,如下所示: 
#define pci_dev_g(n) list_entry(n, struct pci_dev, global_list) 
#define pci_dev_b(n) list_entry(n, struct pci_dev, bus_list) 

§2.4 PCI总线链表 
系统中当前存在的所有根总线都通过其pci_bus结构中的node成员链接成一条全局的根总线链表,其表头由list类型的全局变量pci_root_buses来描述。它的定义如下(drivers/pci/pci.c): 
LIST_HEAD(pci_root_buses); 
而根总线下面的所有下级总线则都通过其pci_bus结构中的node成员链接到其父总线的children链表中。这样,通过这两种PCI总线链表,linux内核就将所有的pci_bus结构以一种倒置树的方式组织起来。假定对于图4所示的PCI总线体系结构,它所对应的总线链表结构如图5所示。 
(图4) 
(图5) 
类似地,宏pci_bus_b(n)则被用来将list_head类型的指针n转换为pci_bus类型的指针。该宏也是定义在include/linux/pci.h头文件中: 
#define pci_bus_b(n) list_entry(n, struct pci_bus, node)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/435452.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

判断深度学习模型的稳定性_问题引领构建数学模型,讲练结合促进深度学习

为了立足校本教研、提升教师专业素养、构建高效课堂、提升数学教学质量,我校数学组于11月12日开展了"问题引领构建数学模型,讲练结合促进深度学习"主题教研活动,区教研员钟文丽老师莅临指导。 教研活动第一环节为王…

数据结构与算法(C#版)第二章 C#语言与面向对象技术(下)V1.0

由于本学期我给本科生上《数据结构与算法》这门课程,边上边把自己的教案进行总结,发到CSDN上面,希望大家多多指正。 第二章 C#语言与面向对象技术(下) 二、面向对象技术 5.属性 6.索引器 7.接口 8.泛型 9.类与类之间的…

一些常用且实用的原生 JavaScript函数[转]

日常开始中常用到的一些原生JavaScript函数,比较实用, 今天特地整理一下,分享给大家,希望对大家有用,会常更新,同时也欢迎大家补充.css及html方面的技巧总结,点此前往: 前端开发中一些常用技巧总结, 你还可以前往兰芝博客, 查看由淘宝UED整理的前端tips: http://www.12sui.cn/c…

Linux内核的时钟中断

前言 时间在一个操作系统内核中占据着重要的地位,它是驱动一个OS内核运行的“起博器”。一般说来,内核主要需要两种类型的时间: 1. 在内核运行期间持续记录当前的时间与日期,以便内核对某些对象和事件作时间标记(tim…

win10命令提示符怎么打开_Win10系统防火墙怎么打开?ARP防火墙启用步骤

ARP防火墙怎么打开?ARP防火墙能够提供多种系统防护功能,那么Win10系统该如何开启ARP防火墙呢?本文就给大家介绍Win10系统电脑ARP防火墙的启用方法。操作步骤:1、右键点击Win10 开始菜单,然后选择“运行”;或者使用快捷…

LSGO软件技术团队2015~2016学年第二周(0907~0912)总结

由于团队的技术博客正在构建当中,所以先借CSDN对团队本周的情况做一个总结。 1.团队成员签到统计 2、团队发表技术博客统计 从第三周开始,要求每组根据自身的情况,至少发表一篇技术类博客。 3、团队技术小组统计 到目前为止,Mat…

vs2005新建类,自定义模板信息(转载)

最近开发科研管理系统,是团队开发,好多东西都要统一,查了一下网上的资料,找到了下面这个修改Visual Studio 2008模版的方法。我们开发的时候习惯在代码顶部加上自己的版权说明。每次拷贝挺麻烦的,上网查了一下&#xf…

WPF随笔(一)

由于笔者的记忆力问题,所以把自己在实际开发中发现的一些东西写下来,便于以后查看,由于涉猎WPF不是很久,故所涉及的东西在老鸟看来都是很简单,很表层的,也希望大家多多指点,若内容存在不合理的地…

电脑上怎么做pdf文件_图片怎么输出为PDF文件?两种办法教你,手机电脑都能转...

我们经常遇到要将图片转换成pdf文件输出的情况,那么我们有什么办法能更快更好进行转换呢?小编今天给大家带来两个办法,一个是手机上操作的,另一个是电脑上的方法,实测好用!手机端转换手机上小编一般会使用图…

LSGO软件技术团队2015~2016学年第三周(0914~0920)总结

很抱歉,由于我的原因,本学期对团队的数据没有及时统计和整理,在团队的管理中有些放松,近期我会补上,让大家在一个充满正能量的氛围中学习成长。简简单单做人,快快乐乐做事! 本周签到情况统计&am…

利用div的定位制作复杂的页面布局

既然是复杂的布局自然用到较多的div以及并列与嵌套。这就要我们在为它们命名的时候遵从一定的规定,以便于可读性。下面先来看一张布局图:这是三九健康网一个频道的页面,原本是很长的页面,但为了说明问题,取了个完整布局…

WSAGetLastError

WSAGetLastError (Wsapiref_2tiq.asp) 函数返回了可能的错误代码。 错误错误宏按字母顺序列出。 不从任何函数返回在 Winsock2.h 中定义一些错误代码。 本文中不包括这些错误代码。 更多信息WSAEINTR (10004) 翻译: 中断函数调用。 说明: A 阻塞操作已被 WSACance…

LSGO软件技术团队2015~2016学年第四周(0921~0927)总结

我们是一个充满正能量的学习型团队! 简简单单做人,快快乐乐做事! 本周签到情况统计(第四周0921至0927): 团队技术博客账号统计: 进入团队需要遵守的规则: 1.进入团队的同学需遵守“…

正则匹配括号里面的内容不包括括号_python正则表达式

是一个计算机科学概念用于使用单个字符串来描述,匹配某个规则的字符串常常用来检索,替换某些模式的文本正则的写法.(点号):表示任意一个字符,除了[](中括号),匹配括号中列举的范围,如[0-9]代表任意单个字数…

专业程序员必知必会的技巧:驯服复杂代码

你从入职第一天起就要应对复杂代码。 若是还未遇到过无法理解的程序,那说明你编程的年头还不够长。在行业里,要不了多久你就会碰到让人发懵的混乱代码:巨兽、面条工厂、来自地狱的遗留系统。我曾接手过一个程序,它的前任在听说要…

使用Nant构建入门

前言:NAnt是一项开源的项目,利用NAnt,你可以方便快捷地对自己.NET项目或解决方案进行自动构建。与VS中可视化化极强的项目和解决方案管理相比,NAnt只能命令行的方式操作,但是这并不影响Nant的流行。NAnt可以根据我们的…

LSGO软件技术团队2015~2016学年第五周(0928~1004)总结

一个充满正能量的学习型团队! 简简单单做人,快快乐乐做事! 本周签到情况统计(第五周0928至1004): 团队技术博客账号统计(第五周0928至1004): 实验室工作台使用情况统计&…

香肠派对电脑版_《香肠派对》是不是除了《和平精英》最成功的吃鸡手游:靠恶搞火了?...

我们知道,自从《绝地求生》自国内外火了之后,国内陆续上线了大大小小不少于10款各种类型的吃鸡手游,从最早的《丛林法则》、到瞬间倒下的《荒野行动》,再到现在最火的《和平精英》和后面即将上线的武侠吃鸡《江湖求生》。国内的游…

C/C++程序员必读的十本书(上)

在Gmail TopLanguage Group 中看到一篇文章“C/C程序员必读的十本书(上)”,大家的讨论都很激励,大家都觉得这篇文章写得很棒,我想在Group里的朋友都能在Lookgirl的这篇文章里获益不少,为此斗胆在此转载该文…

LSGO软件技术团队2015~2016学年第六周(1005~1011)总结

LSGO软件技术团队成立于2010年10月,主要从事的应用方向为互联网与移动互联网(UI设计,前端开发,后台开发),地理信息系统;研究方向为数据分析与计算机视觉。成立几年来为学校培养了一批优秀学生&a…