Linux 设备驱动程序(四)

在这里插入图片描述

系列文章目录


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.hqwc.cn/news/694.html

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

相关文章

IntelliJ IDEA如何自动生成serialVersionUID

IntelliJ IDEA如何自动生成serialVersionUID&#xff1f; 实体对象在流中传输时&#xff0c;需要将其序列化。 对象的类型实现Serializable接口public class ClassName implements java.io.Serializable { } 生成版本号serialVersionUID单击类名&#xff0c;按Alt Enter,在出…

【单目标优化算法】杂草优化算法(Matlab代码实现)

&#x1f4a5; &#x1f4a5; &#x1f49e; &#x1f49e; 欢迎来到本博客 ❤️ ❤️ &#x1f4a5; &#x1f4a5; &#x1f3c6; 博主优势&#xff1a; &#x1f31e; &#x1f31e; &#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 …

DragGAN开源:生成图像流形上的基于点的交互式操作

文旨在解决生成对抗网络&#xff08;GAN&#xff09;中控制生成图像的问题。通过“拖动”图像中的任意点&#xff0c;实现用户交互式精确控制生成图像的姿态、形状、表情和布局。 这个名叫DragGAN的模型&#xff0c;本质上是为各种GAN开发的一种交互式图像操作方法。论文以Sty…

软件外包开发在线监控工具

软件系统上线后需要实时监控&#xff0c;这样在系统出现问题后可以及时发现问题并解决问题。今天和大家分享常见的软件系统监控工具&#xff0c;这些工具功能强大且成熟稳定&#xff0c;熟练的应用可以帮助运维人员解决很多项目中的实际问题。北京木奇移动技术有限公司&#xf…

java面试高频面试题

文章目录 面向对象 什么是面向对象&#xff1f;封装继承多态 和equals比较hashCode与equals重载和重写的区别Final类加载器spring是什么AOP的理解谈谈你对IOC的理解零拷贝RocketMQ 架构设计RocketMq 事务消息原理RockeMq顺序消息消费原理简述RockerMQ持久化机制RocketMQ如何保…

Redis的简单使用 (实现Session持久化)

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 一、Redis数据类型的使用 1. 字符串&#xff…

“前端已死”

一、一些迹象 逛社区&#xff0c;偶然看到了这张图片&#xff1a; 嗯……我眉头一皱&#xff0c;久久不语&#xff0c;心想&#xff0c;有这么夸张吗&#xff0c;假的吧&#xff1f; 突然想到&#xff0c;最近我在社区发了个前端招聘的信息&#xff0c;结果简历漫天纷飞&…

并发-JMM-CPU缓存一致性协议MESI

回顾 指令重排 第一V读&#xff0c;都不能指令重排&#xff1b;第二个V写&#xff0c;都不能指令重排 普通读写&#xff0c;写读都会发生指令重排&#xff0c;V写普通读写会发生指令重排&#xff0c;普通读写V读会发生指令重排 CPU缓存一致性协议MESI java—》cpu的执行过程…

kafka基础

文章目录 1、什么是消息队列&#xff1f;2、基础架构3、Kafka为什么快4、零拷贝5、Rebalance机制6、kafka如何避免重复消费7、避免消息丢失8、Kafka怎么实现消息的顺序消费9、什么是ISR10、Kafka文件存储机制 1、什么是消息队列&#xff1f; kafka是一个消息队列的中间件&…

MySQL - 数据库级别的外键

1. 外键 FOREIGN KEY (了解) 测试数据 &#xff1a; 学生表 CREATE TABLE IF NOT EXISTS student (id INT(4) NOT NULL AUTO_INCREMENT COMMENT 学号,name VARCHAR(30) NOT NULL DEFAULT 匿名 COMMENT 姓名,pwd VARCHAR(20) NOT NULL DEFAULT 123456 COMMENT 密码,sex VARC…

FastDFS单机部署及SpringBoot整合

前言 FastDFS是一个开源的高性能分布式文件系统。它的主要功能包括&#xff1a;文件存储、文件同步和文件访问&#xff08;文件上传和文件下载&#xff09;&#xff0c;可以解决高容量和负载平衡问题。FastDFS应满足其服务基于文件的网站的要求&#xff0c;如照片共享网站和视…

卷积基础知识总结

卷积层是卷积神经网络中的核心模块&#xff0c;**卷积层的目的是提取输入特征图的特征&#xff0c;**如下图所示&#xff0c;卷积核可以提取图像中的边缘信息。卷积也成为过滤器&#xff0c;即Filter 1 卷积的计算方法 卷积运算本质上就是在滤波器和输入数据的局部区域间做点…