Linux設備模型(十一) - platform設備

一,platform device概述

在Linux2.6以后的設備驅動模型中,需關心總線、設備和驅動這3個實體,總線將設備和驅動綁定。在系統每注冊一個設備的時候,

會尋找與之匹配的驅動;相反的,在系統每注冊一個設備的時候,會尋找與之匹配的設備,而匹配由總線完成。

一個現實的Linux設備和驅動通常都需要掛接在一種總線上,而對于本身依附于PCI、USB、I2C、SPI等的設備而言,這自然不是問題,

但是在嵌入式系統里面,在SoC系統中集成的獨立外設控制器、掛接在SoC內存空間的外設等卻不依附于此類總線。基于這一背景,Linux

發明了一種虛擬總線,稱為platform總線,相應的設備稱為platform_device,而驅動稱為platform_driver。

所謂的platform_device并不是與字符設備、塊設備和網絡設備并存的概念,而是linux系統提供的一種附加手段,例如,我們通常把在

SoC內部集成的I2C、RTC、LCD、看門狗等控制器都歸納為platform_device,而他們本身就是字符設備。這些設備有一個基本的特征:可以通過CPU bus直接尋址(例如在嵌入式系統常見的“寄存器”)。

二,platform模塊的軟件架構

內核中Platform設備有關的實現位于include/linux/platform_device.h和drivers/base/platform.c兩個文件中,它的軟件架構如下:

由圖片可知,Platform設備在內核中的實現主要包括三個部分:

Platform Bus,基于底層bus模塊,抽象出一個虛擬的Platform bus,用于掛載Platform設備;

Platform Device,基于底層device模塊,抽象出Platform Device,用于表示Platform設備;

Platform Driver,基于底層device_driver模塊,抽象出Platform Driver,用于驅動Platform設備。

其中Platform Device和Platform Driver會給其它Driver提供封裝好的API,具體可參考后面的描述。

三,platform bus/platform device/platform driver結構體

1,platform_driver

// msm_kernel\include\linux\platform_device.h
struct platform_driver {int (*probe)(struct platform_device *);int (*remove)(struct platform_device *);void (*shutdown)(struct platform_device *);int (*suspend)(struct platform_device *, pm_message_t state);int (*resume)(struct platform_device *);struct device_driver driver;const struct platform_device_id *id_table; /* 另外這里有一個id_table的指針,該指針和of_match_table、acpi_match_table的功能類似:提供其它方式的設備probe */bool prevent_deferred_probe;ANDROID_KABI_RESERVE(1);
};

2,platform_device

// msm_kernel\include\linux\platform_device.h
struct platform_device {const char    *name; /* 設備的名稱,和struct device結構中的init_name意義相同。實際上,該名稱在設備注冊時,會拷貝到dev.init_name中 */int        id; /* 用于標識該設備的ID。內核允許存在多個名稱相同的設備。而設備驅動的probe,依賴于名稱,Linux采取的策略是:在bus的設備鏈表中查找device,和對應的device_driver比對name,如果相同,則查看該設備是否已經綁定了driver(查看其dev->driver指針是否為空),如果已綁定,則不會執行probe動作,如果沒有綁定,則以該device的指針為參數,調用driver的probe接口。
因此,在driver的probe接口中,通過判斷設備的ID,可以知道此次驅動的設備是哪個*/bool        id_auto; /* 指示在注冊設備時,是否自動賦予ID值 */struct device    dev; /* 真正的設備(Platform設備只是一個特殊的設備,因此其核心邏輯還是由底層的模塊實現) */u64        platform_dma_mask;struct device_dma_parameters dma_parms;u32        num_resources;struct resource    *resource; /* 該設備的資源描述,由struct resource(include/linux/ioport.h)結構抽象 */const struct platform_device_id    *id_entry;char *driver_override; /* Driver name to force a match *//* MFD cell pointer */struct mfd_cell *mfd_cell;/* arch specific additions */struct pdev_archdata    archdata;ANDROID_KABI_RESERVE(1);ANDROID_KABI_RESERVE(2);
};

3,platform bus

// msm_kernel\drivers\base\platform.c
struct bus_type platform_bus_type = {.name        = "platform",.dev_groups    = platform_dev_groups,.match        = platform_match,.uevent        = platform_uevent,.dma_configure    = platform_dma_configure,.pm        = &platform_dev_pm_ops,
};
EXPORT_SYMBOL_GPL(platform_bus_type);

四,platform bus/platform device/platform driver注冊

1,platform bus注冊

struct device platform_bus = {.init_name    = "platform",
};
EXPORT_SYMBOL_GPL(platform_bus);int __init platform_bus_init(void)
{int error;early_platform_cleanup(); /* 清除所有和Early device/driver相關的代碼。因為執行到這里的時候,證明系統已經完成了Early階段的啟動,轉而進行正常的設備初始化、啟動操作,所以不再需要Early Platform相關的東西。 */error = device_register(&platform_bus); /* 在sysfs中創建/sys/devices/platform目錄,所有的platform設備都會包含在此目錄下 */if (error) {put_device(&platform_bus);return error;}error =  bus_register(&platform_bus_type); /* 在sysfs中創建/sys/bus/platform目錄并在此目錄中創建如下attributes和devices目錄,drivers目錄 *//*lynkco:/sys/bus/platform # lsdevices  drivers  drivers_autoprobe  drivers_probe  uevent*/if (error)device_unregister(&platform_bus);of_platform_register_reconfig_notifier();return error;
}

2,platform device注冊

platform_device_register - add a platform device to device hierarchy// msm_kernel\drivers\base\platform.c
platform_device_register(struct platform_device *pdev)
----device_initialize(&pdev->dev);
----platform_device_add(pdev);
--------pdev->dev.parent = &platform_bus; //該設備的sysfs目錄/sys/devices/platform/xxx_device
--------pdev->dev.bus = &platform_bus_type; //該設備的bus type定義為platform_bus_type
--------dev_set_name(&pdev->dev, "%s.%d", pdev->name,  pdev->id); //對于多個同名的設備,可以使用ID區分,在這里將實際名稱修改為“name.id”的形式
--------insert_resource(p, r); /* 調用resource模塊的insert_resource接口,將該設備需要使用的resource統一管理起來(我們知道,在這之前,只是聲明了本設備需要使用哪些resource,但resource模塊并不知情,也就無從管理,因此需要告知)。 */
--------device_add(&pdev->dev); // 將內嵌的struct device變量添加到內核中......

3,platform driver注冊

platform_driver_register - register a driver for platform-level devices// msm_kernel\drivers\base\platform.c
platform_driver_register(drv)
----__platform_driver_register(drv, THIS_MODULE)
--------drv->driver.bus = &platform_bus_type; //該driver的bus type設置為platform_bus_type
------------drv->driver.probe = platform_drv_probe; /* 如果該platform driver提供了probe、remove、shutdown等回調函數,將該它內嵌的struct driver變量的probe、remove、shutdown等指針,設置為platform模塊提供函數,包括platform_drv_probe、platform_drv_remove和platform_drv_shutdown。因為probe等動作會從struct driver變量開始,經過platform_drv_xxx等接口的轉接就可以到達platform diver自身的回調函數中。*/
------------drv->driver.remove = platform_drv_remove;
------------drv->driver.shutdown = platform_drv_shutdown;
--------driver_register(&drv->driver); //將內嵌的struct driver變量添加到內核中......

五,platform device/platform driver提供的API

1,platform driver提供的API

extern int platform_driver_register(struct platform_driver *);
extern void platform_driver_unregister(struct platform_driver *); //platform driver的注冊、注銷接口extern int platform_driver_probe(struct platform_driver *driver,int (*probe)(struct platform_device *)); //主動執行probe動作static inline void *platform_get_drvdata(const struct platform_device *pdev);
static inline void platform_set_drvdata(struct platform_device *pdev,void *data); //設置或者獲取driver保存在device變量中的私有數據

2,platform device提供的API

extern int platform_device_register(struct platform_device *);
extern void platform_device_unregister(struct platform_device *); //Platform設備的注冊/注銷接口,和底層的device_register等接口類似extern struct resource *platform_get_resource(struct platform_device *,unsigned int, unsigned int);
extern int platform_get_irq(struct platform_device *, unsigned int);
extern struct resource *platform_get_resource_byname(struct platform_device *,unsigned int,const char *);
extern int platform_get_irq_byname(struct platform_device *, const char *); //通過這些接口,可以獲取platform_device變量中的resource信息,以及直接獲取IRQ的number等等extern int platform_device_add_resources(struct platform_device *pdev,const struct resource *res,unsigned int num); //向platform device中增加資源描述extern int platform_device_add_data(struct platform_device *pdev,const void *data, size_t size); //向platform device中添加自定義的數據(保存在pdev->dev.platform_data指針中)

六,platform device resource/platform data的定義與獲取

1,struct resource結構體介紹

在platform device結構體的定義中關于device resource的定義如下

    u32        num_resources;struct resource    *resource;

它們描述了platform_device的資源,資源本身由resource結構體描述

/*
* Resources are tree-like, allowing
* nesting etc..
*/
struct resource {resource_size_t start;resource_size_t end;const char *name;unsigned long flags;unsigned long desc;struct resource *parent, *sibling, *child;ANDROID_KABI_RESERVE(1);ANDROID_KABI_RESERVE(2);ANDROID_KABI_RESERVE(3);ANDROID_KABI_RESERVE(4);
};

我們通常關心start、end和flags這3個字段,它們分別標明了資源的開始值、結束值和類型,flags可以為IORESOURCE_IO、IORESOURCE_MEM、IORESOURCE_IRQ、IORESOURCE_DMA等。

start、end的含義會隨著flags而變更,如當flags為IORESOURCE_MEM時,start、end分別表示該platform_device占據的內存的開始地址和結束地址;

當flags為IORESOURCE_IRQ時,start、end分別表示該platform_device使用的中斷號的開始值和結束值,如果只使用了一個中斷號,開始值和結束值相同。

對于同種類型的資源而言,可以有多份,例如說某設備占據了兩個內存區域,則可以定義兩個IORESOURCE_MEM資源。

系統中所有的platform_device,都可以在/sys/devices/platform/路徑下查看。另外,系統中所有的platform_device,有來自設備樹的,也有來自.c文件中注冊的。那么,我們怎么知道哪些platform_device是來自設備樹,哪些是來自.c文件中注冊的?

可以查看該platform_device的相關目錄下,是否有of_node,如果有of_node,那么這個platform_device就來自于設備樹;否則,來自.c文件。

2,來自.c文件中注冊的platform_device

2.1 example
// msm_kernel\arch\arm\mach-ep93xx\core.cstatic struct usb_ohci_pdata ep93xx_ohci_pdata = {.power_on    = ep93xx_ohci_power_on,.power_off    = ep93xx_ohci_power_off,.power_suspend    = ep93xx_ohci_power_off,
};static struct resource ep93xx_ohci_resources[] = {DEFINE_RES_MEM(EP93XX_USB_PHYS_BASE, 0x1000),DEFINE_RES_IRQ(IRQ_EP93XX_USB),
};static struct platform_device ep93xx_ohci_device = {.name        = "ohci-platform",.id        = -1,.num_resources    = ARRAY_SIZE(ep93xx_ohci_resources),.resource    = ep93xx_ohci_resources,.dev        = {.dma_mask        = &ep93xx_ohci_dma_mask,.coherent_dma_mask    = DMA_BIT_MASK(32),.platform_data        = &ep93xx_ohci_pdata,},
};
platform_device_register(&ep93xx_ohci_device);

設備除了可以在BSP中定義資源以外,還可以附加一些數據信息,因為對設備的硬件描述除了中斷、內存等標準資源以外,還可能有一些配置信息,而這些配置信息也依賴于板,不適宜直接放置在設備驅動上。因此platform也提供了platform_data的支持,platform_data的形式是由每個驅動自定義的,如對于usb ohci設備而言,platform_data為一個usb_ohci_pdata結構體,完成定義后將可以將PM operation相關的接口信息放入platform_data中。

在usb ohci驅動msm-kernel/drivers/usb/host/ohci-platform.c的probe()函數中,通過如下方式就拿到了platform_data:

static int ohci_platform_probe(struct platform_device *dev)    
{struct usb_hcd *hcd;struct resource *res_mem;struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev);struct ohci_platform_priv *priv;... ...
}
2.2 memory resource資源的定義
#define DEFINE_RES_MEM(_start, _size)                    \DEFINE_RES_MEM_NAMED((_start), (_size), NULL)#define DEFINE_RES_MEM_NAMED(_start, _size, _name)            \DEFINE_RES_NAMED((_start), (_size), (_name), IORESOURCE_MEM)/* helpers to define resources */
#define DEFINE_RES_NAMED(_start, _size, _name, _flags)            \{                                \.start = (_start),                    \.end = (_start) + (_size) - 1,                \.name = (_name),                    \.flags = (_flags),                    \.desc = IORES_DESC_NONE,                \}
2.3 irq resource資源的定義
#define DEFINE_RES_IRQ(_irq)                        \DEFINE_RES_IRQ_NAMED((_irq), NULL)#define DEFINE_RES_IRQ_NAMED(_irq, _name)                \DEFINE_RES_NAMED((_irq), 1, (_name), IORESOURCE_IRQ)
2.4?IO resources?flags
/*
* IO resources have these defined flags.
*
* PCI devices expose these flags to userspace in the "resource" sysfs file,
* so don't move them.
*/
#define IORESOURCE_BITS        0x000000ff    /* Bus-specific bits */#define IORESOURCE_TYPE_BITS    0x00001f00    /* Resource type */
#define IORESOURCE_IO        0x00000100    /* PCI/ISA I/O ports */
#define IORESOURCE_MEM        0x00000200
#define IORESOURCE_REG        0x00000300    /* Register offsets */
#define IORESOURCE_IRQ        0x00000400
#define IORESOURCE_DMA        0x00000800
#define IORESOURCE_BUS        0x00001000

3,來自設備樹的platform_device

在Linux內核啟動時,內核通過 of_platform_populate() 函數,將dts中的device node創建成platform device。為后續和各類驅動的platform driver匹配做準備。

of_platform_device_create_pdata
----of_device_alloc
--------of_address_to_resource(np, num_reg, &temp_res)
--------num_irq = of_irq_count(np);
--------dev->num_resources = num_reg + num_irq;
--------dev->resource = res;
--------of_address_to_resource(np, i, res);
--------of_irq_to_resource_table(np, res, num_irq); //將dts中的address和irq等信息轉化到resource結構體中
--------dev->dev.bus = &platform_bus_type;
----dev->dev.platform_data = platform_data;
----of_device_add(dev)
--------device_add(&ofdev->dev);

具體解析轉化過程會在后續的dts章節中詳細分析。

4,get resource?API實現及使用

4.1?get resource?API實現

platform_get_resource_byname:

/**
* platform_get_resource_byname - get a resource for a device by name
* @dev: platform device
* @type: resource type
* @name: resource name
*/
struct resource *platform_get_resource_byname(struct platform_device *dev,unsigned int type,const char *name)
{u32 i;for (i = 0; i < dev->num_resources; i++) {struct resource *r = &dev->resource[i];if (unlikely(!r->name))continue;if (type == resource_type(r) && !strcmp(r->name, name)) //匹配type和namereturn r;}return NULL;
}
EXPORT_SYMBOL_GPL(platform_get_resource_byname);

platform_get_resource:

/**
* platform_get_resource - get a resource for a device
* @dev: platform device
* @type: resource type
* @num: resource index
*
* Return: a pointer to the resource or NULL on failure.
*/
struct resource *platform_get_resource(struct platform_device *dev,unsigned int type, unsigned int num)
{u32 i;for (i = 0; i < dev->num_resources; i++) {struct resource *r = &dev->resource[i];if (type == resource_type(r) && num-- == 0) //匹配type和indexreturn r;}return NULL;
}
EXPORT_SYMBOL_GPL(platform_get_resource);
4.2?get resource?API使用示例

get memory resource使用示例:

struct resource *res;res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");return -ENODEV;
}adata->acp3x_base = devm_ioremap(&pdev->dev, res->start,resource_size(res));
if (!adata->acp3x_base)return -ENOMEM;

get irq resource 使用示例:

res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res) {dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");return -ENODEV;
}
adata->i2s_irq = res->start;status = devm_request_irq(&pdev->dev, adata->i2s_irq, i2s_irq_handler,irqflags, "ACP3x_I2S_IRQ", adata);
if (status) {dev_err(&pdev->dev, "ACP3x I2S IRQ request failed\n");return -ENODEV;
}

get resource by name 使用示例:

struct resource *r;/* card: irq assigned to the card itself. */
r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "card");
sock->card_irq = r ? r->start : 0;/* stschg: irq which trigger on card status change (optional) */
r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "stschg");
sock->stschg_irq = r ? r->start : -1;/* 36bit PCMCIA Memory area address */
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-mem");
if (!r) {printk(KERN_ERR "pcmcia%d has no 'pseudo-mem' resource!\n",sock->nr);goto out0;
}
sock->phys_mem = r->start;

由以上分析可知,在設備驅動中引入platform的概念至少有如下好處:

1)使得設備被掛接在一個總線上,符合Linux2.6以后內核的設備模型。其結果是使配套的sysfs節點、設備電源管理都成為可能。

2)隔離BSP和驅動。在BSP中定義platform設備和設備使用的資源、設備的具體配置信息,而在驅動中,只需要通過通用API去獲取資源和數據,做到了板相關代碼和驅動代碼的分離,使得驅動具有更好的可擴展性和跨平臺性。

3)讓一個驅動支持多個設備實例。

參考鏈接:

Linux設備模型(8)_platform設備

dts展開為platform_device結構過程分析-騰訊云開發者社區-騰訊云

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/718259.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/718259.shtml
英文地址,請注明出處:http://en.pswp.cn/news/718259.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Redis】實際應用 - 緩存

文章目錄 1. 緩存的基本概念2. Redis作為緩存的優勢2.1 內存存儲2.2 持久性選項2.3 數據結構豐富 3. Redis緩存的使用3.1 安裝和配置Redis3.2 連接到Redis3.3 存儲和獲取數據3.4 設置過期時間 4. 緩存策略4.1 LRU&#xff08;最近最少使用&#xff09;4.2 數據失效4.3 主動刷新…

可讓照片人物“開口說話”阿里圖生視頻模型EMO,高啟強普法

3 月 1 日消息&#xff0c;阿里巴巴研究團隊近日發布了一款名為“EMO&#xff08;Emote Portrait Alive&#xff09;”的 AI 框架&#xff0c;該框架號稱可以用于“對口型”&#xff0c;只需要輸入人物照片及音頻&#xff0c;模型就能夠讓照片中的人物開口說出相關音頻&#xf…

PDN分析及應用系列二-簡單5V電源分配-Altium Designer仿真分析-AD

PDN分析及應用系列二 —— 案例1:簡單5V電源分配 預模擬DC網絡識別 當最初為PCB設計打開PDN分析儀時,它將嘗試根據公共電源網絡命名法從設計中識別所有直流電源網絡。 正確的DC網絡識別對于獲得最準確的模擬結果非常重要。 在示例項目中已經識別出主DC網絡以簡化該過程。 …

Vulnhub靶機:Bellatrix

一、介紹 運行環境&#xff1a;Virtualbox 攻擊機&#xff1a;kali&#xff08;10.0.2.4&#xff09; 靶機&#xff1a;Bellatrix&#xff08;10.0.2.9&#xff09; 目標&#xff1a;獲取靶機root權限和flag 靶機下載地址&#xff1a;https://www.vulnhub.com/entry/hogwa…

Leetcode 3070. Count Submatrices with Top-Left Element and Sum Less Than k

Leetcode 3070. Count Submatrices with Top-Left Element and Sum Less Than k 1. 解題思路2. 代碼實現 題目鏈接&#xff1a;3070. Count Submatrices with Top-Left Element and Sum Less Than k 1. 解題思路 這一題就是一個二維的累積數組的問題&#xff0c;我們直接求一…

網絡學習:MPLS技術基礎知識

目錄 一、MPLS技術產生背景 二、MPLS網絡組成&#xff08;基本概念&#xff09; 1、MPLS技術簡介&#xff1a;Multiprotocol Lable Switching&#xff0c;多協議標簽交換技術 2、MPLS網絡組成 三、MPLS的優勢 四、MPLS的實際應用 一、MPLS技術產生背景 1、IP采用最長掩碼…

Power BI vs Superset BI 調研報告

調研結論 SupersetPower BI價格開源①. Power BI Pro 每人 $10/月($120/年/人) ②. Power BI Premium 每人 $20/月($240/年/人) ③. Power BI Embedded:4C10G $11W/年 權限基于角色的訪問控制,支持細粒度的訪問: 表級別、庫級別、圖表級別,看板級別,用戶級別 基于角色…

每天一個數據分析題(一百八十五)

給定下述Python代碼段&#xff0c;試問哪個選項正確描述了該代碼段的功能&#xff1f; data_raw[‘gender’] data_raw[‘gender’].map({‘Male’: 1, ‘Female’: 0}) A. 代碼中對gender變量進行了獨熱編碼(One-Hot Encoding)&#xff0c;并將gender中的缺失值填充為類別平…

深度學習API——keras初學

keras定義&#xff1a; Keras是一個深度學習API&#xff08;人工神經網絡庫&#xff09;&#xff0c;使用Python語言編寫的github開源項目&#xff0c;主要開發者為谷歌工程師。Keras底層可調用不同的機器學習平臺&#xff0c;如TensorFlow、Theano或micsoft-CNTK。 作用&…

Tomcat的配置文件

Tomcat的配置文件詳解 一.Tomcat的配置文件 Tomcat的配置文件默認存放在$CATALINA_HOME/conf目錄中&#xff0c;主要有以下幾個&#xff1a; 1.server.xml: Tomcat的主配置文件&#xff0c;包含Service, Connector, Engine, Realm, Valve, Hosts主組件的相關配置信息&#x…

【推薦】免費AI論文寫作神器-「智元兔 AI」

還在為寫論文焦慮&#xff1f;免費AI寫作大師來幫你三步搞定&#xff01; 智元兔AI是ChatGPT的人工智能助手&#xff0c;并且具有出色的論文寫作能力。它能夠根據用戶提供的題目或要求&#xff0c;自動生成高質量的論文。 不論是論文、畢業論文、散文、科普文章、新聞稿件&…

#WEB前端(浮動與定位)

1.實驗&#xff1a; 2.IDE&#xff1a;VSCODE 3.記錄&#xff1a; float、position 沒有應用浮動前 應用左浮動和右浮動后 應用定位 4.代碼&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><me…

pyqt5怎么返回錯誤信息給頁面(警告窗口)

在軟件設計中&#xff0c;我們可能會遇到對異常的處理&#xff0c;有些異常是用戶需要看到的&#xff0c;比如說&#xff0c;當我們登錄出錯的時候&#xff0c;后端需要給我們返回響應的錯誤信息&#xff0c;就像下圖實現的這樣。 類似這種效果&#xff0c;我們該如何實現&…

javaWebssh題庫管理系統myeclipse開發mysql數據庫MVC模式java編程計算機網頁設計

一、源碼特點 java ssh題庫管理系統是一套完善的web設計系統&#xff08;系統采用ssh框架進行設計開發&#xff09;&#xff0c;對理解JSP java編程開發語言有幫助&#xff0c;系統具有完整的源代碼和數據庫&#xff0c;系統主要采用B/S模式開發。開發環境為TOMCAT7.0,Mye…

「MySQL」基本操作類型

&#x1f387;個人主頁&#xff1a;Ice_Sugar_7 &#x1f387;所屬專欄&#xff1a;數據庫 &#x1f387;歡迎點贊收藏加關注哦&#xff01; 數據庫的操作 創建、顯示數據庫 使用 create 創建一個數據庫 create database goods;然后可以用 show databases 來查看已經創建的數…

我們如何知道人工智能系統有多智能?

1967 年&#xff0c;人工智能 &#xff08;AI&#xff09; 領域的創始人馬文明克西 &#xff08;Marvin Minksy&#xff09; 做出了一個大膽的預測&#xff1a;“在一代人之內…創造’人工智能’的問題將得到實質性解決。假設一代人大約是 30 年&#xff0c;明斯基顯然過于樂觀…

javaWebssh網上超市銷售管理系統myeclipse開發mysql數據庫MVC模式java編程計算機網頁設計

一、源碼特點 java ssh網上超市銷售管理系統是一套完善的web設計系統&#xff08;系統采用ssh框架進行設計開發&#xff09;&#xff0c;對理解JSP java編程開發語言有幫助&#xff0c;系統具有完整的源代碼和數據庫&#xff0c;系統主要采用B/S模式開發。開發環境為TOMCA…

指針深刻理解

指針深刻理解 看完鵬哥講的c語言進階視頻后&#xff0c;又找來C語言深度剖析這本書仔細看了一遍&#xff0c;來進一步鞏固和理解指針這個重點。 1&#xff1a;數組 如上圖所示&#xff0c;當我們定義一個數組 a 時&#xff0c;編譯器根據指定的元素個數和元素的類型分配確定大…

突破編程_C++_STL教程( list 的實戰應用)

1 std::list 的排序 1.1 基礎類型以及 std::string 類型的排序 std::list的排序可以通過調用其成員函數sort()來實現。sort()函數使用默認的比較操作符&#xff08;<&#xff09;對std::list中的元素進行排序。這意味著&#xff0c;如果元素類型定義了<操作符&#xff…

身份證識別系統(安卓)

設計內容與要求&#xff1a; 通過手機攝像頭捕獲身份證信息&#xff0c;將身份證上的姓名、性別、出生年月、身份證號碼保存在數據庫中。1&#xff09;所開發Apps軟件至少需由3-5個以上功能性界面組成。要求&#xff1a;界面美觀整潔、方便應用&#xff1b;可以使用Android原生…