Linux 设备驱动程序(四)

news2024/12/25 9:00:54

在这里插入图片描述

系列文章目录


Linux 内核设计与实现
深入理解 Linux 内核
Linux 设备驱动程序(一)
Linux 设备驱动程序(二)
Linux 设备驱动程序(三)
Linux 设备驱动程序(四)
Linux设备驱动开发详解
深入理解Linux虚拟内存管理


文章目录

  • 系列文章目录
  • 第十六章、块设备驱动程序
    • 1、快速参考
  • 第十七章、块设备驱动程序
    • 1、快速参考
  • 第十八章、TTY驱动程序
    • 1、快速参考
  • 符号


第十六章、块设备驱动程序

1、快速参考

#include <linux/fs.h>
int register_blkdev(unsigned iat major, const char *name);
int unregister_blkdev(unsigned int major, const char *name);
// register_blkdev 用来向内核注册一个块设备驱动程序,还可获得主设备号。一个驱
// 动程序可以使用 unregister_blkdev 函数注销。
struct block_device_operations
// 用来保存块设备驱动程序大多数方法的数据结构。

#include <linux/genhd.h>
struct gendisk;
// 用来描述内核中单个块设备的结构。
struct gendisk *alloc_disk(int minors);
void add_disk(struct gendisk *gd);
// 用来分配 gendisk 结构并将其返回给系统的函数。
void set_capacity(struct gendisk *gd, sector_t sectors);
// 在 gendisk 结构中保存设备容量(用 512 字节扇区为单位)。
void add_disk(struct gendisk *gd);
// 向内核添加一个磁盘。一且调用了该函数,内核就能调用磁盘方法了。
int check_disk_change(struct block_device *bdev);
// 用来对指定磁盘驱动器进行介质变化检查的内核函数,当介质改变被侦测到后,采
// 取必要的清除动作。

#include <linux/blkdev.h>
request_queue_t blk_init_queue(request_fn_proc *request, spinlock_t *lock);
void blk_cleanup_queue(request_queue_t *):
// 用来创建和删除块设备请求队列的函数。
struct request *elv_next_request(request_queue_t *queue);
void end_request(struct request *req, int success);
// elv_next_request获得请求队列中的下一个请求;end_request用在简单的驱动程序
// 中,以完成(或部分完成)一个请求。
void blkdev_dequeue_request(struct request *req);
void elv_requeue_request (request_queue_t *queue, struct request *req);
// 从队列中删除一个请求的函数、如果需要,还可以把该请求放回队列。
void blk_stop_queue(request_queue_t *queue);
void blk_start_queue(request_queue_t *queve);
// 如果不想让自己的请求函数被调用、blk_stop_queue 可以做到这点。为了能使请求
// 函数被调用,必须调用 blk_start_queue 的函数。
void blk_queue_bounce_limit(request_queue_t *queue, u64 dma_addr);
void blk_queue_max_sectors(request_queue_t *queue, unsigned short max);
void blk_queue_max_phys_segment.s (request_queue_t *queue, unsigned short max);
void blk_queue_max_hw_segments(request_queue_t *queue, unsigned short max);
void blk_queue_max_segment_size(request_queue_t *queue, unsigmed int max);
blk_queue_segment_boundary(request_queue_t *queue, unsigned long mask);
void blk_queue_dma_alignment(request_queue_t *queue, int mask);
void blk_queue_hardsect_size(request_queue_t *queue, unsigned short max);
// 用来设置队列参数的函数。这些参数控制了对一个特定设备请求的创建。参数的具
// 体解释在"队列控制函数"一节。

#include <linux/bio.h>
struct bio;
// 表示部分块设备 I/O 请求的底层结构。
bio_sectors(struct bio *bio);
bio_data_dir(struct bio *bio);
// 这两个宏用来获得 bio 结构描述的大小和传输方向。
bio_for_each_segment (bvec, bio, segno);
// 用来遍历组成 bio 结构的段的伪控制结构。
char *__bio_kmap_atomic(struct bio *bio, int i, enum km_type type);
void __bio_kurmap_atomic(char *buffer, enum km_type type);
// __bio_kmap_atomic用来为bio结构中指定的段创建内核虚拟地址。取消该映射必
// 须使用 __bio_kunmap_atomic。
struct page *bio_page(struct bio *bio);
int bio_offset(struct bio *bio);
int bio_cur_sectors(struct bio *bio);
char *bio_data(struct bio *bio);
char *bio_kmap_irq(struct bio *bio, unsigned long *flags);
void bio_kunmap_irq(char *buffer, unsigned long *flags);
// 这是一组访问宏,用来访问 bio 结构中的"当前"段。
void blk_queue_ordered(request_queue_t *queue, int flag);
int blk_barrier_rq(struct request *req);
// 如果驱动程序实现了屏障请求,则调用 blk_queue_ordered。如果当前请求是一个。
// 屏障请求,则宏 blk_barrier_rq 返回非零值。
int blk_noretry_request(struct request *req);
// 该宏返回非零值表示指定的请求因错误不能再次被执行。
int end_that_request_first(struct request *req, int success, int count);
void end_that_request_last(struct request *req);
// 使用 end_that_request_first 表示完成一个块设备 I/O 请求的过程。如果该函数返回
// 0,则表示请求已经完成,应该被传递给 end_that_request_last。
rq_for_each_bio(bio, request)
// 另外一个以宏的形式实现的控制结构,它将遍历请求中的每个 bio 结构。
int blk_rq_map_sq(request_queue_t *queue, struct request *req, struct
scatterlist *list);
// 为DMA传输,需要将缓冲区映射到指定的 request 中,使用这些信息填充分散表。
typedef int (make_request_fn) (request_queue_t *q, struct bio *bio);
// make_request 函数的原型。
void bio_endio(struct bio *bio, unsigned int bytes, int error);
// 指定的 bio 结构的信号完成函数。只有当驱动程序通过 make_request 函数直接从
// 块设备层获得 bio 结构时,才使用该函数。
request_queue_t *blk_alloc_queue(int flags);
void blk_queue_make_request (request_queue_t *queue, make_request_fn *func);
// 使用 blk_alloc_queue 来分配一个请求队列,以便为用户定义的 make_request 函数
// 所使用。该函数要用 blk_queue_make_request 设置。
typedef int (prep_rq_fn) (request_queue_t *queue, struct request *req);
void blk_queue_prep_rq(request_queue_t *queue, prep_rq_fn *func);
// 命令预处理函数的原型和设置,它可以在请求传递到请求处理函数前,为硬件准备
// 需要的命令。
int blk_queue_init_tags(request_queue_t *queue, int depth, struct
blk_queue_tag *tags);
int blk_queue_resize_tags(request_queue_t *queue, int new_depth);
int blk_queue_start_tag(request_queue_t *queue, struct request *req);
void blk_queue_end_tag(request_queue_t *queue, struct request *req);
struct request *blk_queue_find_tag(request_queue_t *qeue, int tag);
void blk_queue_invalidate_tags(request_queue_t *queue);
// 为了让驱动程序使用标记命令队列而提供的支持函数。

第十七章、块设备驱动程序

1、快速参考

#include <linux/netdevice.h>
// 这个头文件保存有net_device和net_device_stats结构的定义,并包含了
// 网络驱动程序需要的其他几个头文件。
struct net_device *alloc_netdev(int sizeof_priv, char *name, void
(*setup)(struct net_device *);
struct net_device *alloc_etherdev(int sizeof_priv);
void free_netdev(struct net_device *dev);
// 分配和释放 net_device结构的函数。
int register_netdev(struct net_device *dev);
void unregister_netdev(struct net_device *dev);
// 注册和注销一个网络设备。
void *netdev_priv(struct net_device *dev);
// 获得指向网络设备结构中驱动程序私有数据区指针的函数。
struct net_device_stats;
// 保存设备统计信息的结构。
netif_start_queue(struct net_device *dev);
netif_stop_queue(struct net_device *dev);
netif_wake_queue(struct net_device *dev);
// 上述函数控制外发数据包向驱动程序的传递。在调用 netif_start_queue 之前,不会
// 传输任何数据包。netif_stop_queue 暂停传输,而 netif_wake_queue 重新启动队列
// 并通知网络层重新启动数据包的传输。
skb_shinfo(struct sk_buff *skb);
// 提供对数据包缓存区中"共享信息"访问的宏。
void netif_rx(struct sk_buff *skb);
// 调用(包括中断期间)这个函数可通知内核已经接收到一个数据包,并封装入一个
// 套接字缓冲区。
void netif_rx_schedule(dev);
// 调用该函数通知内核数据包已经存在,并且在接口上启动轮询机制;它只在NAPI
// 驱动程序中使用。
int netif_receive_skb(struct sk_buff *skb);
void netif_rx_complete(struct net_device *dev);
// 这两个函数只在NAPI驱动程序中使用。NAPI中的netif_receive_skb函数与netif_rx
// 等价;它将数据包发送给内核。当NAPI驱动程序耗尽了为接收数据包准备的内存,
// 则它将重新启动中断,然后调用 netif_rx_complete 终止轮询函数。

#include <linux/if.h>
// netdevice.h 中包含该头文件。在该文件中声明了接口标志(IFF_macros)和ifmap
// 结构、在网络驱动程序的 ioctl 实现中、其扮演了重要角色。
void netif_carrier_off(struct net_device *dev);
void netif_carrier_on(struct net_device *dev);
int netif_carrier_ok(struct net_device *dev);
// 前两个函数告诉内核在指定接口上是否存在载波信号。netif_carrier_ok检查载波状
// 态作为在 device 结构中的应答。

#include <linux/if_ether.h>
ETH_ALEN
ETH_P_IP
struct ethhdr;
// netdevice.h 中包含该头文件。if_ether.h 中定义了所有的 ETH_ 宏,用来表示 octet
// 的长度(比如地址长度)和网络协议(比如 IP)。它还定义了 ethhdr 结构。

#include <linux/skbuff.h>
// 定义了sk_buff 及其相关结构,同时定义了许多作用于缓冲区的内联函数。该头
// 文件包含在 netdevice.h 中。
struct sk_buff *alloc_skb(unsigned int ler, int priority);
struct sk_buff *dev_alloc_skb(unsigned int len);
void kfree_skb(struct sk_buff *skb);
void dev_kfree_skb(struct sk_buff *skb);
void dev_kfree_skb_irq(struct sk_buff *skb);
void dev_kfree_skb_any(struct sk_buff *skb);
// 分配和释放套接字缓冲区的函数。因此驱动程序通常使用具有 dev_ 前级的变种。
unsigned char *skb_put(struct sk_buff *skb, int len);
unsigned char *__skb_put(struct sk_buff *skb, int len);
unsigned char *skb_push(struct sk_buff *skb, int 1en);
_unsigned char *__skb_push(struct sk_buff *skb, int len);
// 将数据添加到 skb 的函数;skb_put 将数据放在 skb 的末尾,而 skb_push 将数据放
// 在开头。常用的版本还负责检查是否有足够的空间存放数据;而有双下划线前级的
// 版本不进行该项检查。
int skb_headroom(struct sk_buff *skb);
int skb_tailroom(struct sk_buff *skb);
void skb_reserve(struct sk_buff *skb, int len);
// 在 skb 中实现空间管理的函数。skb_headroom和 skb_tailroom分别返回在 skb 的
// 开头和结尾,还有多少空间可用。skb_reserve 用于在 skb 开头部分保留空间,保
// 留的空间必须为空。
unsigned char *skb_pull(struct sk_buff *skb, int len);
// skb_pull 通过调整内部指针而"删除"skb 内的数据。
int skb_is_nonlinear(struct sk_buff *skb);
// 如果使用分散 / 聚集 I/O, 并且skb 分离成多个数据片段,则该函数返回真实值。
int skb_headlen(struct sk_buff *skb);
// 返回 skb 中 skb->data 的第一个段的长度。
void *kmap_skb_frag(skb_frag_t *frag);
void kunmap_skb_frag(void *vaddr);
// 提供对非线性skb 中的数据片段的直接访问。

#include <linux/etherdevice.h>
void ether_setup(struct net_device *dev);
// 为以太网驱动程序设置大部分通用设备方法的函数。它还设置了 dev->flags。如
// 果设备名称的第一个字符为空,或者是空格的话,这个函数将把下一个可用的ethx
// 名称赋给 dev->name。
unsigned short eth_type_trans(struct sk_buff *skb, struct net_device *dev);
// 当以太网接口接收到一个数据包时,调用该函数设置skb->pkt_type。返回值是
// 保存在 skb->protocol 中的协议号。

#include <linux/sockios.h>
SIOCDEVPRIVATE
// 16 个ioctl 命令中的第一个,每个驱动程序都能够出于自身的考虑实现它。在
// sockios.h 中定义了所有的网络 ioctl 命令。

#include <linux/mii.h>
struct mii_if_info;
// 支持实现 MII 标准的设备驱动程序的声明和结构。
#include <linux/ethtool.h>
struct ethtool_ops;
// 让设备可使用 ethtool 工具的声明和结构。

第十八章、TTY驱动程序

1、快速参考

#include <linux/tty_driver.h>
// 包含 tty_driver 结构定义,以及在该结构中一些不同标志位的声明。

#include <linux/tty.h>
// 该头文件包含了tty_struct结构的定义以及许多不同的宏定义,使得对termios
// 结构各成员值的访问更简单。它还包含了 tty 驱动程序核心的函数声明。

#include <linux/tty_flip.h>
// 包含了一些 tty 交替缓冲区 inline 函数的 头文件,这些 inline 通数能简化对交替缓
// 冲区结构的操作。

#include <asm/termios.h>
// 特定硬件平台创建内核时,使用的是包含 termio 结构定义的头文件。
struct tty_driver *alloc_tty_driver(int 1ines);
// 创建 tty_driver 结构的函数,该结构以后将被传递给 tty_register_driver 和
// tty_unregister_driver 函数。
void put_tty_driver(struct tty_driver *driver);
// 如果使用tty_driver结构向tty核心的注册没有成功,该函数负责清空 tty_driver
// 结构。
void tty_set_operations(struct tty_driver *driver, struct tty_operations *op);
// 负责初始化结构 tty_driver 中的回调函数的函数。在调用 tty_register_driver 前
// 必须调用它。
int tty_register_driver(struct tty_driver *driver);
int tty_unregister_driver(struct tty_driver *driver);
// 从 tty 核心注册和注销一个 tty 驱动程序的函数。
void tty_register_device(struct tty_driver *driver, unsigned minor, struct
device *device);
void tty_unregister_device(struct tty_driver *driver, unsigned minor);
// 向 tty 核心注册和注销一个 tty 设备的函数。
void tty_insert_flip_char(struct tty_struct *tty, unsigned char ch,
char flag);
// 将字符插入到 ty 设备的交替缓冲区使用户能够读到的函数。
TTY_NORMAL
TTY_BREAK
TTY_FRAME
TTY_PARITY
TTY_OVERRUN
// 在 tty_insert_flip_char 函数中使用的不同的标志位。
int tty_get_baud_rate(struct tty_struct *tty);
// 获得指定 tty 设备当前波特率的函数。
void tty_flip_buffer_push(struct tty_struct *tty);
// 把数据放入当前交替缓冲区并传递给用户的函数。
tty_std_termios
// 用常见的默认线路设置初始化 termios 结构的变量。

符号

   
⇐ ⇒ ⇔ ⇆ ⇒ ⟺
①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴㊵㊶㊷㊸㊹㊺㊻㊼㊽㊾㊿
⑴⑵⑶⑷⑸⑹⑺⑻⑼⑽⑿⒀⒁⒂⒃⒄⒅⒆⒇
➊➋➌➍➎➏➐➑➒➓⓫⓬⓭⓮⓯⓰⓱⓲⓳⓴
⒜⒝⒞⒟⒠⒡⒢⒣⒤⒥⒦⒧⒨⒩⒪⒫⒬⒭⒮⒯⒰⒱⒲⒳⒴⒵
ⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ
ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏ
🅐🅑🅒🅓🅔🅕🅖🅗🅘🅙🅚🅛🅜🅝🅞🅟🅠🅡🅢🅣🅤🅥🅦🅧🅨🅩

123

y = x 2 + z 3 y = x^2 + z_3 y=x2+z3

y = x 2 + z 3 + a b + b a y = x^2 + z_3 + \frac {a}{b} + \sqrt[a]{b} y=x2+z3+ba+ab

y = x 2 + z 3 (1) y = x^2 + z^3 \tag{1} y=x2+z3(1)

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

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

相关文章

大数据应用——spark实验

任务一&#xff1a;比较Spark和hadoop的区别 Spark和Hadoop都是用于分布式计算的框架&#xff0c;但两者有以下区别&#xff1a; 1、处理方式不同。Hadoop是基于MapReduce的&#xff0c;而Spark则是基于内存的分布式计算框架。 2、处理速度不同。因为Hadoop是磁盘读写密集型应用…

代理ip的用途及是否可以降低延迟

在互联网使用中&#xff0c;代理IP是一种被广泛使用的工具&#xff0c;用于隐藏真实IP地址和提供一些额外的功能。人们常常疑惑代理IP是否能够降低延迟&#xff0c;从而提高网络连接的速度和响应时间。下面&#xff0c;就让我们来探讨一下代理ip可以用在那些领域及是不是可以降…

C/S、B/S架构详解,一文带你搞懂

一、CS、BS架构定义 CS架构&#xff08;Client-Server Architecture&#xff09;是一种分布式计算模型&#xff0c;其中客户端和服务器之间通过网络进行通信。在这种架构中&#xff0c;客户端负责向服务器发送请求&#xff0c;并接收服务器返回的响应。服务器则负责处理客户端的…

SpringCloud微服务(二)网关GateWay、Docker、Dockerfile、Linux操作超详细

目录 统一网关GateWay 搭建网关服务的步骤 1、引入依赖 2、编写路由配置及nacos地址 路由断言工厂Route Oredicate Factory 路由过滤器配置 全局过滤器GlobalFilter 过滤器执行顺序 跨域问题处理 Docker ​编辑 Docker与虚拟机 镜像和容器 Docker的安装 启动docke…

原生JS实现图片裁剪功能

功能介绍&#xff1a;图片通过原生input上传&#xff0c;使用canvas进行图片裁剪。 裁剪框限制不允许超出图片范围&#xff0c;图片限制了最大宽高&#xff08;自行修改要的尺寸&#xff09;&#xff0c;点击确认获取新的base64图片数据 效果图&#xff1a; 上代码 <!DOCT…

物种气候生态位动态量化与分布特征模拟----R语言

在全球气候快速变化的背景下&#xff0c;理解并预测生物种群如何应对气候变化&#xff0c;特别是它们的地理分布如何变化&#xff0c;已经变得至关重要。利用R语言进行物种气候生态位动态量化与分布特征模拟&#xff0c;不仅可以量化描述物种对环境的需求和适应性&#xff0c;预…

【断路器型号字母含义解析】- 米思米机械设备知识分享

断路器型号意义含义 目前我国断路器型号根据国家技术标准的规定&#xff0c;一般由文字符号和数字按以下方式组成。其代表意义为&#xff1a; ①;产品字母代号&#xff0c;用下列字母表示&#xff1a; S;少油断路器&#xff1b; D;多油断路器&#xff1b; K;空气断路器&#xf…

听说你还不知道什么是 python?带你深入理解什么是 python

文章目录 前言什么是pythonpython的由来我们为什么要学习python帮助python学习的网站 前言 各位朋友们&#xff0c;大家好。在之后的时间里&#xff0c;我将陆续为大家分享我在python学习过程中学习到的知识点&#xff0c;如果你也对python感兴趣的话&#xff0c;欢迎大家来订…

持 PMP®证书增持 CSPM-2证书,先下手就对了!

2023年6月起&#xff0c;持有PMP证书的朋友可以直接增持一个同等级证书CSPM-2&#xff0c;不用重新考试&#xff0c;不用重新学习&#xff0c;原PMP证书不影响正常使用&#xff0c;相当于多了一个国标项目管理领域的证书。 第一步准备资料 1、填写能力评价表(简历和业绩不用填…

Stateflow状态图

目录 1.Stateflow简介 2.Stateflow编辑 2.1 打开方式 2.2 状态 2.3 状态名称 2.4 迁移 2.4.1 迁移 2.4.2 默认迁移 2.4.3 迁移有效条件 3 数据与事件 3.1 数据 3.2 事件 4 示例 1.Stateflow简介 Stateflow对象可分为图形对象和非图形对象。 图形对象包括&#xff1…

LangChain 介绍及相关组件使用总结

一、langChain LangChain 是一个由语言模型LLMs驱动的应用程序框架&#xff0c;它允许用户围绕大型语言模型快速构建应用程序和管道。 可以直接与 OpenAI 的 ChatGPT 模型以及 Hugging Face 集成。通过 langChain 可快速构建聊天机器人、生成式问答(GQA)、本文摘要等应用场景。…

Nginx做图片服务器

前言&#xff1a; Nginx是一个高性能的HTTP和反向代理web服务器,以及负载均衡器。根据nginx是高性能的http服务器&#xff0c;因此可以用作图片服务器使用。 本案例是在docker安装nginx来操作的。 Nginx安装 1、首先是docker的安装 详情参考&#xff1a;docker安装 2、拉取ng…

倒计时2天,解锁亚马逊云科技中国峰会 Dev Lounge 玩法

2023 亚马逊云科技中国峰会即将重磅登陆上海 主会场与分论坛云集百余位重磅嘉宾 开发者会客厅也已集齐全球优秀开源社区 倒计时2天&#xff0c;赶快报名参与这场顶级盛会&#xff01; 开发者大讲堂&#xff0c;圆桌讨论给你精彩 数据对于企业和个人来说都至关重要&#xff0…

【kubernetes系列】Kubernetes中的重要概念

​ 在学习k8s之前&#xff0c;必须先了解 Kubernetes 的几个重要概念&#xff0c;它们是组成 Kubernetes 集群的基石。&#xff08;参考Kubernetes权威指南&#xff09; 一、Master Kubernetes 里的Master指的是集群的控制节点&#xff0c; 每个Kubernetes 集群里至少需要有一…

大数据应用——hive实验

任务一&#xff1a;完成Hive内嵌模式部署 1.1 Hive部署 官网下载Hive安装包 &#xff08;1&#xff09;官网地址&#xff1a;Apache Hive &#xff08;2&#xff09;文档查看地址&#xff1a; https://cwili.apache.org/confluence/display/Hive/GettingStarted &#xff08;2&…

年轻人存款难吗?探讨现实挑战与如何应对

年轻人存款难吗&#xff1f;探讨现实挑战与如何应对 近日&#xff0c;一项调查显示“大概五分之一的年轻人存款在一万元以内。10万元存款是一个“坎”&#xff0c;存款超过10万就会超过53.7%的人。”这个数据引发了关于“年轻人”和“存款”的广泛关注和讨论。作为社会的未来&…

使用 Maya、ZBrush 和 XGen 创建极其逼真的美女肖像

今天云渲染小编给大家带来的是CG艺术家Hadi Karimi 的朋友 Clara 肖像模型背后的工作流程&#xff0c;展示了头发是如何使用 XGen 完成的&#xff0c;并解释了为什么历史人物很难进行逼真的渲染。 介绍 大家伙&#xff0c;我是 Hadi Karimi&#xff0c;是一名来自伊朗的自由 C…

.net点选验证码实现思路分享

哈哈好久没冒泡了&#xff0c;最进看见点选验证码有点意思&#xff0c;所以想自己写一个。 先上效果图 如果你被这个效果吸引了就请继续看下去。 贴代码前先说点思路&#xff1a; 1.要有一个汉字库,并按字形分类。&#xff08;我在数据库里是安部首分类的&#xff09; 2.获…

力扣题库刷题笔记13--罗马数字转整数

1、题目如下&#xff1a; 2、个人Python代码实现&#xff1a; 虽然前面刚刷了整数转罗马数字&#xff0c;而且本题难度为简单&#xff0c;实际上做出来还是花了很多时间&#xff0c;不亚于前面整数转罗马数字。 以上的思路&#xff0c;主要是声明一个列表temp&#xff0c;然后遍…

【MYSQL】—— MySQL 在 Centos 7环境安装

本期&#xff0c;我将给大家介绍的是如何在【Linux】上安装相应的 mysql。 目录 1. 卸载不要的环境 2. 检查系统安装包 3. 获取mysql官⽅yum源 4. 安装mysql yum 源&#xff0c;对⽐前后yum源 5. 看看能不能正常⼯作 6. 安装mysql服务 7. 启动服务 8. 查看启动服务 9.…