offset

virtio前端驱动详解

喜欢而已 提交于 2020-02-17 14:18:03
前段时间大致整理了下virtIO后端驱动的工作模式以及原理,今天就从前端驱动的角度描述下目前Linux内核代码中的virtIO驱动是如何配合后端进行工作的。 注:本节代码参考Linux 内核3.11.1代码 virtIO驱动从架构上来讲可以分为两部分,一个是其作为PCI设备本身的驱动,此驱动需要提供一些基本的操作PCI设备本身的函数比如PCI设备的探测、删除、配置空间的设置和寄存器空间的读写等。而另一个就是其virtIO设备本身实现的功能驱动例如网络驱动、块设备驱动、console驱动等。所以我们要看还是分两部分,先介绍PCI设备本身的驱动,然后在介绍实际功能驱动。 一、PCI设备本身驱动 在前面的PCI系列文章中对Linux内核中PCI设备驱动做了分析,所以这里我们只分析和virtIO相关的部分。 二、功能驱动部分 其实大部分的功能在后端驱动已经介绍,只是有些功能是在前端实现的,比如说virtqueue的初始化、avail buffer的添加以及used buffer的消费,还有比较很重要的是前后端vring的同步。 鉴于前面已经有了基本的概念基础,那么我们直接从网络驱动下手,分析驱动从注册到接受数据的整个流程。(参考代码virtio-net.c) 看下网络驱动注册的操作函数: 1 static const struct net_device_ops virtnet_netdev

(转)再过半小时,你就能明白kafka的工作原理了

戏子无情 提交于 2020-02-16 09:52:19
为什么需要消息队列   周末无聊刷着手机,某宝网APP突然蹦出来一条消息“为了回馈老客户,女朋友买一送一,活动仅限今天!”。买一送一还有这种好事,那我可不能错过!忍不住立马点了去。于是选了两个最新款,下单、支付一气呵成!满足的躺在床上,想着马上有女朋友了,竟然幸福的失眠了……   第二天正常上着班,突然接到快递小哥的电话:   小哥:“你是xx吗?你的女朋友到了,我现在在你楼下,你来拿一下吧!”。   我:“这……我在上班呢,可以晚上送过来吗?“。   小哥:“晚上可不行哦,晚上我也下班了呢!”。   于是两个人僵持了很久……   最后小哥说,要不我帮你放到楼下小芳便利店吧,你晚上下班了过来拿,尴尬的局面这才得以缓解!   回到正题,如果没有小芳便利店,那快递小哥和我的交互图就应该如下:         会出现什么情况呢?   1、为了这个女朋友,我请假回去拿(老板不批)。   2、小哥一直在你楼下等(小哥还有其他的快递要送)。   3、周末再送(显然等不及)。   4、这个女朋友我不要了(绝对不可能)!   小芳便利店出现后,交互图就应如下:         在上面例子中,“快递小哥”和“买女朋友的我”就是需要交互的两个系统,小芳便利店就是我们本文要讲的-“消息中间件”。总结下来小芳便利店(消息中间件)出现后有如下好处:    1、 解耦   快递小哥手上有很多快递需要送

Flink Connectors 介绍与 Kafka Connector

时间秒杀一切 提交于 2020-02-15 08:45:32
文章目录 1. Streaming Connectors 预定义的 source 和 sink Boundled connectors Apache Bahir 中的连接器 异步 IO 2. Flink Kafka Connector 2.1 Flink Kafka Consumer 1)反序列化 2)消费起始位置设置 3)topic 和 partition 动态发现 4)commit offset 方式 5)Timestamp Extraction/Watermark 生成 2.2 Flink Kafka Producer 1)Producer 写出时的 Partition 分区 2)Producer 容错 3. Q&A 1. Streaming Connectors Connector 的作用就相当于一个连接器,连接 Flink 计算引擎跟外界存储系统。 目前常用的 Connector 有以下几种: 预定义的 source 和 sink 基于文件的 source 和 sink // 从文本文件中读取数据 env . readTextFile ( path ) ; // 以文本的形式读取该文件中的内容 env . readFile ( fileInputFormat , path ) ; // 将结果已文本格式写出到文件中 DataStream . writeAsText (

Linux内存管理-高端内存(一)

江枫思渺然 提交于 2020-02-15 00:58:06
高端内存是指物理地址大于 896M 的内存。对于这样的内存,无法在“内核直接映射空间”进行映射。 为什么?   因为 “内核直接映射空间”最多只能从 3G 到 4G,只能直接映射 1G 物理内存,对于大于 1G 的物理内存,无能为力 。   实际上,“内核直接映射空间”也达不到 1G, 还得留点线性空间给“内核动态映射空间” 呢。   因此,Linux 规定 “内核直接映射空间” 最多映射 896M 物理内存 。   对于高端内存,可以通过 alloc_page() 或者其它函数获得对应的 page,但是要想访问实际物理内存,还得把 page 转为线性地址才行(为什么?想想 MMU 是如何访问物理内存的),也就是说,我们需要 为高端内存对应的 page 找一个线性空间,这个过程称为高端内存映射。 高端内存映射有三种方式: 1、 映射到“内核动态映射空间”   这种方式很简单,因为通过 vmalloc() ,在“内核动态映射空间”申请内存的时候,就可能从高端内存获得页面(参看 vmalloc 的实现),因此说 高端内存有可能映射到“内核动态映射空间” 中 。 2、 永久内核映射   如果是通过 alloc_page() 获得了高端内存对应的 page,如何给它找个线性空间?    内核专门为此留出一块线性空间,从 PKMAP_BASE 到 FIXADDR_START

Java中StringBuffer类的常用方法

孤街醉人 提交于 2020-02-14 17:49:36
StringBuffer:StringBuffer类型 描述:在实际应用中,经常回遇到对字符串进行动态修改。这时候,String类的功能受到限制,而StringBuffer类可以完成字符串的动态添加、插入和替换等操作。 1、构造函数。 StringBuffer() :构造一个没有任何字符的StringBuffer类。 StringBuffer(int length) ::构造一个没有任何字符的StringBuffer类,并且,其长度为length。 StringBuffer(String str) :以str为初始值构造一个StringBuffer类。 2、方法。 说明: 所有方法均为public; 书写格式:[修饰符] <返回类型> <方法名([参数列表])> 如: static int parseInt(String s) 表示:此方法(parseInt)为类方法(static),返回类型为(int),方法所需参数为String类型。 1. StringBuffer append(boolean b) 2. StringBuffer append(char c) 3. StringBuffer append(char[] str) 4. StringBuffer append(char[] str, int offset, int len) 5. StringBuffer

RocketMQ入门及部署

扶醉桌前 提交于 2020-02-12 22:49:07
RocketMQ入门及部署 RocketMQ整体架构 如上图所示,整体可以分成4个角色,分别是:Producer,Consumer,Broker以及NameServer; 1.NameServer 可以理解为是消息队列的协调者,Broker向它注册路由信息,同时Client向其获取路由信息,如果使用过Zookeeper,就比较容易理解了,但是功能比Zookeeper弱; NameServer本身是没有状态的,并且多个NameServer直接并没有通信,可以横向扩展多台,Broker会和每一台NameServer建立长连接; 2.Broker Broker是RocketMQ的核心,提供了消息的接收,存储,拉取等功能,一般都需要保证Broker的高可用,所以会配置Broker Slave,当Master挂掉之后,Consumer然后可以消费Slave; Broker分为Master和Slave,一个Master可以对应多个Slave,Master与Slave的对应关系通过指定相同的BrokerName,不同的BrokerId来定义,BrokerId为0表示Master,非0表示Slave; 3.Producer 消息队列的生产者,需要与NameServer建立连接,从NameServer获取Topic路由信息,并向提供Topic服务的Broker Master建立连接

App(2)

点点圈 提交于 2020-02-11 22:34:51
@Entity public class BBill{ @Id(autoincrement = true) private Long id; //本地id private String rid; //服务器端id private float cost; //金额 private String content; //内容 private String userid; //用户id private String payName; //支付方式 private String payImg; // private String sortName; //账单分类 private String sortImg; // private long crdate; //创建时间 private boolean income; //收入支出 private int version; //版本 @Generated(hash = 124482664) public BBill() { } @Generated(hash = 634586034) public BBill(Long id, String rid, float cost, String content, String userid, String payName, String payImg, String sortName, String

RocketMQ学习笔记(11)----RocketMQ的PushConsumer和PullConsumer

大城市里の小女人 提交于 2020-02-10 02:13:16
1. PushConsumer   推,Broker主动向Consumer推消息,它Consumer的一种,应用通常向对象注册一个Listener接口,一旦接收到消息,Consumer对象立刻回调Linstener接口方法。Push方式里,consumer把轮询过程封装了,并注册MessageListener监听器,取到消息后,唤醒MessageListener的consumeMessage()来消费,对用户而言,感觉消息是被推送过来的。   缺点:   慢消费无疑是Push模式最大的致命伤,如果消费者的速度比发送者的速度慢很多,势必造成消息在broker的堆积。假设这些消息都是有用的无法丢弃的,消息就要一直在broker端保存。当然这还不是最致命的,最致命的是broker给consumer推送一堆consumer无法处理的消息,consumer不是reject就是error,然后来回踢皮球。所以push适合于没有慢消费情况的场景下   前面使用的所有示例中的Consuemr都是采用的push方式,所以这里就不在具体写示例代码了。 2. PullConsumer   拉,Consumer主动的从Broker拉取消息,主动权由应用控制,可以实现批量的消费消息。Pull方式里,取消息的过程需要用户自己写,首先通过打算消费的Topic拿到MessageQueue的集合

antd源码分析之——标签页(tabs 3.Tabs的滚动效果)

邮差的信 提交于 2020-02-09 19:07:30
由于ant Tabs组件结构较复杂,共分三部分叙述,本文为目录中第三部分(高亮) 目录 一、组件结构 antd代码结构 rc-ant代码结构 1、组件树状结构 2、Context使用说明 3、rc-tabs中只在example、test中使用的组件说明 二、Tabs关键组件功能实现 1、Tabs(antd) 2、RcTabs 3、Sentinel哨兵 4、InkTabBarNode 三、Tabs的滚动效果 ScrollableTabBarNode 二、Tabs的滚动效果 ScrollableTabBarNode ScrollableTabBarNode内容太多,使用多个思维导图分别展示,内容较多总结的比较粗糙,部分细节还有疑问 首先,整体结构图,将ScrollableTabBarNode的方法进行归类(个人看法) 然后,根据方法内容从基础到复杂的层次来看,首先看【state方法】和【计算宽度位置的基础方法】 再次,是主要【功能方法】,tab标签的滚动效果逻辑大多在这部分 最后,看【事件回调】和【生命周期方法】 在给出整体结构图之前,先给出tab中组件结构示意图,其中由nav包裹多个tab,使用左侧或顶部偏移控制滚动位置。 滚动状态下,上一页、下一页按钮在navWrap外的左右或上下两侧 (1)整体结构 (2)state方法 this.state中next与prev两个值,布尔型

django学习记录,动态url,另外发现django的时区问题

为君一笑 提交于 2020-02-09 07:47:27
按上次的经验,现在要想实现动态url,肯定先需要修改urls.py。 使用一个数字来显示为了几小时的日期和时间 如/now/plus1hour/显示未来1小时的时间,/now/plus3hour/显示未来3小时的时间 那么就是 1 urlpatterns = patterns('', 2 (r'^now/$', current_datetime), 3 (r'^now/plus1hour/$', one_hour_ahead), 4 (r'^now/plus2hour/$', two_hours_ahead), 5 (r'^now/plus3hour/$', three_hours_ahead), 6 {r'^now/plus4hour/$', four_hours_ahead), 7 ) 但是这样的方法显得很笨拙。不仅会产生大量的视图方法,还将程序局限在预先定义的小时范围内 ,如果我们想显示5小时后的时间,我们还得再添加一行 ,所以我们应该在这里做出一点抽象 。 关于良好的URL 如果你使用过PHP或Java,你可能会说“让我们使用一个查询参数”,类似于像/now/plus?hours=3 你也可以使用Django这样做,但是Django的一个核心哲学是,URL应该是优雅的 /now/plus3hours/更干净、更简单、更可读、更朗朗上口 良好的URL是Web程序质量的一个显示