failover, failfast, failback, failsafe

“failover, failfast, failback, failsafe” failover: 失效转移/故障转移 故障转移(fail-over) Fail-Over 的含义为“失效转移”,是一种备份操作模式,当主要组件异常时,其功能转移到备份组件。其要点在于有主有备,且主故障时备可启用,并设置为主。如MySQL的双Master模式,当正在使用的Master出现故障时,可以拿备Master做主使用 通俗地说,即当A无法为客户服务时,系统能够自动地切换,使B能够及时地顶上继续为客户提供服务,且客户感觉不到这个为他提供服务的对象已经更换。 这里的A和B可以存在于各种领域,但一般fail-over特指计算机领域的数据库、应用服务、硬件设备等的失效转移。 failfast: 快速失败 从字面含义看就是“快速失败”,尽可能的发现系统中的错误,使系统能够按照事先设定好的错误的流程执行,对应的方式是“fault-tolerant (错误容忍) ”。以JAVA集合 (Collection) 的快速失败为例,当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件。例如: 当某一个线程A通过iterator去遍历某集合的过程中,若该集合的内容被其他线程所改变了;那么线程A访问集合时,就会抛出ConcurrentModificationException异常 (发现错误执行设定好的错误的流程) ,产生fail-fast事件。 failback: 失效自动恢复 Fail-over 之后的自动恢复,在簇网络系统 (有两台或多台服务器互联的网络) 中,由于要某台服务器进行维修,需要网络资源和服务暂时重定向到备用系统。在此之后将网络资源和服务器恢复为由原始主机提供的过程,称为自动恢复 failsafe: 失效安全 Fail-Safe的含义为“失效安全”,即使在故障的情况下也不会造成伤害或者尽量减少伤害。维基百科上一个形象的例子是红绿灯的“冲突监测模块”当监测到错误或者冲突的信号时会将十字路口的红绿灯变为闪烁错误模式,而不是全部显示为绿灯。 ———————————————— 版权声明: 本文为CSDN博主「青鱼入云」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接: https://blog.csdn.net/u011305680/article/details/79730646 https://blog.csdn.net/u013699827/article/details/73251649

2021-07-06 · 1 min · 38 words · -

taskset

“taskset” 一、在Linux上修改进程的“CPU亲和力” 在Linux上,可以通过 taskset 命令进行修改。以Ubuntu为例,运行如下命令可以安装taskset工具。 apt-get install schedutils 对运行中的进程,文档上说可以用下面的命令,把CPU#1 #2 #3分配给PID为2345的进程: taskset -cp 1,2,3 2345 但我尝试没奏效,于是我关掉了MySQL,并用taskset将它启动: taskset -c 1,2,3 /etc/init.d/MySQL start 对于其他进程,也可如此处理 (nginx除外,详见下文) 。之后用top查看CPU的使用情况,原来空闲的#1 #2 #3,已经在辛勤工作了。 二、配置nginx绑定CPU 刚才说nginx除外,是因为nginx提供了更精确的控制。 在conf/nginx.conf中,有如下一行: worker_processes 1; 这是用来配置nginx启动几个工作进程的,默认为1。而nginx还支持一个名为worker_cpu_affinity的配置项,也就是说,nginx可以为每个工作进程绑定CPU。我做了如下配置: worker_processes 3; worker_cpu_affinity 0010 0100 1000; 这里0010 0100 1000是掩码,分别代表第2、3、4颗cpu核心。 重启nginx后,3个工作进程就可以各自用各自的CPU了。 三、刨根问底 如果自己写代码,要把进程绑定到CPU,该怎么做?可以用sched_setaffinity函数。在Linux上,这会触发一次系统调用。 如果父进程设置了affinity,之后其创建的子进程是否会有同样的属性?我发现子进程确实继承了父进程的affinity属性。 四、Windows? 在Windows上修改“CPU亲和力”,可以通过任务管理器搞定。 个人感觉,Windows系统中翻译的“处理器关系”比“CPU亲和力”容易理解点儿 —————– 进行了这样的修改后,即使系统负载达到3以上,不带缓存打开blogkid.net首页 (有40多次查询) 依然顺畅;以前一旦负载超过了1.5,响应就很慢了。效果很明显。 linux taskset命令详解 SYNOPSIS taskset [options] [mask | list ] [pid | command [arg]…] OPTIONS -p, –pid operate on an existing PID and not launch a new task -c, –cpu-list specifiy a numerical list of processors instead of a bitmask. The list may contain multiple items, separated by comma, and ranges. For example, 0,5,7,9-11. -h, –help display usage information and exit -V, –version output version information and exit

2021-07-06 · 1 min · 119 words · -

HyperLogLog

“HyperLogLog” HyperLogLog HyperLogLog,下面简称为HLL,它是 LogLog 算法的升级版,作用是能够提供不精确的去重计数。 127.0.0.1:6379> PFADD language "PHP" "Python" "Perl" "Ruby" (integer) 1 127.0.0.1:6379> PFCOUNT language (integer) 4 127.0.0.1:6379> PFADD language "PHP" # Redis 已经存在,不必对估计数量进行更新 (integer) 0 127.0.0.1:6379> PFCOUNT language # 元素估计数量没有变化 (integer) 4 127.0.0.1:6379> PFADD language "JAVA" # 添加一个不存在的元素 (integer) 1 127.0.0.1:6379> PFCOUNT language # 估计数量增一 5 https://juejin.cn/post/6844903785744056333 https://www.cnblogs.com/wmyskxz/p/12396393.html http://content.research.neustar.biz/blog/hll.html 存在以下的特点: 代码实现较难。 能够使用极少的内存来统计巨量的数据,在 Redis 中实现的 HyperLogLog,只需要12K内存就能统计2^64个数据。 计数存在一定的误差,误差率整体较低。标准误差为 0.81% 。 误差可以被设置辅助计算因子进行降低。 稍微对编程中的基础数据类型内存占用有了解的同学,应该会对其只需要12K内存就能统计2^64个数据而感到惊讶。为什么这样说呢,下面我们举下例子: 取 Java 语言来说,一般long占用8字节,而一字节有8位,即: 1 byte = 8 bit,即long数据类型最大可以表示的数是: 2^63-1。对应上面的2^64个数,假设此时有2^63-1这么多个数,从 0 ~ 2^63-1,按照long以及1k = 1024字节的规则来计算内存总数,就是: ((2^63-1) * 8/1024)K,这是很庞大的一个数,存储空间远远超过12K。而 HyperLogLog 却可以用 12K 就能统计完。 伯努利试验 在认识为什么HyperLogLog能够使用极少的内存来统计巨量的数据之前,要先认识下伯努利试验。 ...

2021-07-06 · 1 min · 134 words · -

redis bitmap

“redis bitmap” BitMap https://www.cnblogs.com/54chensongxia/p/13794391.html BitMap# BitMap 原本的含义是用一个比特位来映射某个元素的状态。由于一个比特位只能表示 0 和 1 两种状态,所以 BitMap 能映射的状态有限,但是使用比特位的优势是能大量的节省内存空间。 在 Redis 中,可以把 Bitmaps 想象成一个以比特位为单位的数组,数组的每个单元只能存储0和1,数组的下标在 Bitmaps 中叫做偏移量。 需要注意的是: BitMap 在 Redis 中并不是一个新的数据类型,其底层是 Redis 实现。 BitMap 相关命令# 设置值,其中value只能是 0 和 1 setbit key offset value 获取值 getbit key offset 获取指定范围内值为 1 的个数 start 和 end 以字节为单位 bitcount key start end BitMap间的运算 operations 位移操作符,枚举值 AND 与运算 & OR 或运算 | XOR 异或 ^ NOT 取反 ~ result 计算的结果,会存储在该key中 key1 … keyn 参与运算的key,可以有多个,空格分割,not运算只能一个key 当 BITOP 处理不同长度的字符串时,较短的那个字符串所缺少的部分会被看作 0。返回值是保存到 destkey 的字符串的长度 (以字节byte为单位) ,和输入 key 中最长的字符串长度相等。 bitop [operations] [result] [key1] [keyn…] ...

2021-07-06 · 2 min · 257 words · -

28

“28” 0%的汽车狂人,制造了80%以上的交通事故;世界上不足20%的富人拥有80%以上的财富;企业中80%的销售额是由20%的产品或客户贡献的。 这些现象暗合帕累托法则,即在任何一组事物中,最重要的只占其中一小部分,约20%,其余80%尽管是多数,却是次要的,这一法则又被称为二八定律或20/80定律。 二八定律可以解决企业管理方面的许多问题: 如资源分配,核心产品,关键人才,核心利润,财富分配等。若公司80%的销售额由20%产品贡献,那么就应该将更多的资源投入到这少数的20%产品上。 二八定律不仅在经济学、企业管理领域广泛应用,它对我们的自身发展也具有重要的现实意义: 要避免将时间和精力花费在琐事上,学会抓主要矛盾。 一个人的时间和精力都是非常有限的,要想真正“做好每一件事情”几乎是不可能的,应该学会合理分配时间和精力。想面面俱到还不如重点突破,把80%的资源花在能出关键效益的20%的方面,这20%的方面又能带动其余80%的发展。 https://zhuanlan.zhihu.com/p/28480261

2021-07-04 · 1 min · 9 words · -

热数据, 温数据, 冷数据

“热数据, 温数据, 冷数据” 热数据 热数据是需要被计算节点频繁访问的在线类数据,比如可以是半年以内的数据,用户经常会查询它们,适合放在数据库中存储,比如MySQL、MongoDB和HBase。 温数据 温数据是非即时的状态和行为数据,也可以简单理解为把热数据和冷数据混在一起就成了温数据。如果整体数据量不大,也可以不区分温数据和热数据。 冷数据 冷数据是指离线类不经常访问的数据,用于灾难恢复的备份或者因为要遵守法律规定必须保留一段时间,比如企业备份数据、业务与操作日志数据、话单与统计数据。通常会存储在性能较低、价格较便宜的文件系统里,适用于离线分析,比如机器学习中的模型训练或者大数据分析。

2021-07-04 · 1 min · 9 words · -

redis ziplist

“redis list” linkedlist 每个node包含了三个部分,指向前一个节点和后一个节点的指针,以及一个数据值。而一个list包含了指向首尾的指针、整个list的长度,以及三个函数指针,用来复制节点的值、释放节点的值,以及比较节点内容。 ziplist 压缩列表 ziplist是一种特殊编码的节省内存空间的双链表,能以O(1)的时间复杂度在两端push和pop数据 ziplist是redis中实现的一个地址连续的链表。 每次操作都需要重新分配内存 先看下官方对ziplist的整体描述 /* The ziplist is a specially encoded dually linked list that is designed to be very memory efficient. It stores both strings and integer values, where integers are encoded as actual integers instead of a series of characters. It allows push and pop operations on either side of the list in O(1) time. However, because every operation requires a reallocation of ...

2021-07-04 · 2 min · 398 words · -

dpdk

“dpdk” dpdk Intel DPDK全称Intel Data Plane Development Kit,是intel提供的数据平面开发工具集,为Intel architecture (IA) 处理器架构下用户空间高效的数据包处理提供库函数和驱动的支持,它不同于Linux系统以通用性设计为目的,而是专注于网络应用中数据包的高性能处理。DPDK应用程序是运行在用户空间上利用自身提供的数据平面库来收发数据包,绕过了Linux内核协议栈对数据包处理过程。Linux内核将DPDK应用程序看作是一个普通的用户态进程,包括它的编译、连接和加载方式和普通程序没有什么两样。DPDK程序启动后只能有一个主线程,然后创建一些子线程并绑定到指定CPU核心上运行。 https://cloud.tencent.com/developer/article/1198333 https://tonydeng.github.io/sdn-handbook/dpdk/ https://github.com/google/cpu_features

2021-06-30 · 1 min · 14 words · -

c, file, open, fopen

“c, file, open, fopen” "" fopen 是 C 标准库函数,用于处理作为流对象的文件的打开。与本质上是系统调用的 open 函数不同,fopen 将 FILE 指针对象与给定的文件相关联。它需要两个参数;第一个参数代表要打开的文件的路径名,第二个参数是打开文件的模式。 open 函数本质上是一个低级的系统服务,即使使用 fopen 也会被调用。需要注意的是,系统调用通常是用 C 库的封装函数提供给最终用户的,但其特点和性能用例与 C stio 库中的函数不同。如: open 在创建新文件时,第二个参数取类型为 int,第三个参数可选,指定文件模式位。 https://www.delftstack.com/zh/howto/c/open-vs-fopen-in-c/

2021-06-29 · 1 min · 27 words · -

win11

“win11” https://github.com/rcmaehl/WhyNotWin11

2021-06-29 · 1 min · 2 words · -

UDP

“UDP” UDP UDP 协议全称是用户数据报协议,在网络中它与 TCP 协议一样用于处理数据包,是一种无连接的协议.在 OSI 中,第四层传输层,处于 IP 协议的上一层 UDP 有不提供数据包分组,组装和不能对数据包进行排序的缺点,也就是说,当报文发送后,无法监控其是否完整安全到达的,就想一个坏掉了的水龙头,你不论怎么让他停止他都只会输出,也不管你的桶满没满,就像爱一样 文章相关视频讲解: C/C++ Linux 服务器开发高级架构师学习视频点击: C/C++Linux服务器开发高级架构/Linux后台架构师-学习视频 底层原理到徒手实现 TCP/IP网络协议栈 tcpip协议栈与网络API的关联,udp的并发性比tcp强? 2|1 特点 面向无连接: 首先 UDP 是不需要和 TCP 一样在发送数据前进行三次握手建立连接的,想发数据就可以开始发送了.并且也只是主句报文的搬运工,不会对数据报文进行任何拆分和拼接操作 具体来说: 在发送端,应用层将数据传递给 UDP 协议,UDP 只会给数据增加一个 UDP 头标识下 UDP,然后就传递给网络层了 在接收端,网络层将数据传递给传输层,UDP 只去除 IP 报头就传递给应用层,不会任何拼接操作 有单播,多播,广播的功能 UDP 不止支持一对一的传输方式,同样支持一对多,多对多,多对一的方式,也就是说 UDP 提供了单播,多播和广播的功能. UDP 是面向报文的 发送方的 UDP 读应用程序交下来的报文,在添加首部后就向下交付 IP 层.UDP 对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界.因此,应用程序必须选择合适大小的报文 不可靠性 首先不可靠性体现在无连接上,通信不需要建立连接,想发就发,这样的情况肯定不可靠 并且受到什么数据就传递什么数据,并且也不会备份数据,发送数据也不会关心对方是否已经正确接收到数据了 再者网络环境时好时坏,但是 UDP 因为没有拥塞控制,一直会以恒定的速度发送数据,即使网络条件不好,也不会对发送数据进行调整.这样实现的弊端就是在网络条件不好的情况下会导致丢包,但是有点也很明显,比如电话会议等等最好就是 UDP 头部开销小,传输数据报文是很高效的. 因此 UDP 的头部开销小,只有八字节,相比 TCP 的至少二十字节要少得多,在传输数据报文时是很高效的 Linux网络编程-UDP和TCP协议详解 原文链接: https://xie.infoq.cn/article/760f379a3e3f2694b5e994ffd?utm_source=rss&utm_medium=article

2021-06-22 · 1 min · 69 words · W10N

Ruckus R310, 优科

“Ruckus R310, 优科” 默认用户名密码 super/sp-admin 软件升级 [https://support.ruckuswireless.com/software?filter=88#sort=relevancy&f:@source=Software%20Downloads]&f:@commonproducts=[R310] https://support.ruckuswireless.com/software/2791-ruckus-solo-access-point-110-0-0-0-2014-ga-refresh2-software-release-r310 Ruckus Solo Access Point 110.0.0.0.2014 (GA Refresh2) Software Release (R310) 操作前的准备 认识硬件 LED状态灯 我们拿一台 Ruckus 2942 AP 来讲解。这个型号已经停产,而且是单频 2.4GHz AP,但是 LED 灯的状态和含义都是相同的。真正的原因是我不想重新做图,懒。 OPT- 没用,永远不亮。有些新的型号已经取消了OPT灯 WLAN- 现在基本上都是双频AP,所以不再有WLAN灯,取而代之的是2.4G和5G灯。有以下几种状态 (胖AP只会出现前3种) : 灭- 表示WLAN服务没有启用 (默认情况下WLAN服务是关闭的) 橙色长亮- 表示WLAN服务已经开启,但是没有客户端连接到Radio 绿色长亮- 表示WLAN服务已经开启,并且已经有客户端连接到Radio 绿色慢闪- 表示AP是Mesh AP,WLAN服务已经开启,但是没有客户端连接到Radio 绿色快闪- 表示AP是Mesh AP,WLAN服务已经开启,并且已经有客户端连接到Radio DIR- 控制器管理状态灯,有以下几种状态: 灭- AP是胖AP,没有被控制器管理 绿色长亮- AP是瘦AP,并且已经和控制器同步 绿色快闪 AP是瘦AP,正在和控制器同步,或者正在更新固件 绿色慢闪 AP是瘦AP,正在寻找控制器 (如果一直处于这种状态, 就要检查网络连通性) AIR- Mesh上行链路状态灯,有些型号的双频AP没有AIR灯,用5G灯来充当AIR灯的功能: 灭- AP是Root AP,或者Mesh被禁用 绿色长亮- Mesh上行链路良好 绿色快闪- Mesh上行链路不佳 (此时需要检查干扰情况,或者调整AP的位置和间距) 绿色慢闪- Mesh上行链路不存在,AP没有找到Root AP 红色 AP硬件损坏 NOTE1: Mesh技术介绍 http://baike.baidu.com/view/1215700.htm NOTE2: AP都会有一个Reset按键,是一个凹陷的孔。先把AP加电,2-3秒钟之后,用曲别针之类的东西按住Reset键 6 秒钟再松手,AP就可以恢复出厂设置。为了避免Reset失败,最好按8秒再松手。 NOTE3: 有些型号的AP还会有一个soft reset,作用是重启AP。 ...

2021-06-20 · 2 min · 335 words · -

Redis Replication, sentinel

“Redis Replication, sentinel” Redis 主从 Replication 的配置 beanlam 发布于 2015-04-20 本专栏与Redis相关的文章 Redis Sentinel机制与用法 (一) Redis Sentinel机制与用法 (二) Jedis的JedisSentinelPool源代码分析 Jedis的Sharded源代码分析 Redis 主从 Replication 的配置 详解Redis SORT命令 JedisCommand接口说明 本文参考翻译自《Redis Replication documentation》 概述 Redis的replication机制允许slave从master那里通过网络传输拷贝到完整的数据备份。具有以下特点: 异步复制。从2.8版本开始,slave能不时地从master那里获取到数据。 允许单个master配置多个slave slave允许其它slave连接到自己。一个slave除了可以连接master外,它还可以连接其它的slave。形成一个图状的架构。 master在进行replication时是非阻塞的,这意味着在replication期间,master依然能够处理客户端的请求。 slave在replication期间也是非阻塞的,也可以接受来自客户端的请求,但是它用的是之前的旧数据。可以通过配置来决定slave是否在进行replication时用旧数据响应客户端的请求,如果配置为否,那么slave将会返回一个错误消息给客户端。不过当新的数据接收完全后,必须将新数据与旧数据替换,即删除旧数据,在替换数据的这个时间窗口内,slave将会拒绝客户端的请求和连接。 一般使用replication来可以实现扩展性,例如说,可以将多个slave配置为“只读”,或者是纯粹的数据冗余备份。 能够通过replication来避免master每次持久化时都将整个数据集持久化到硬盘中。只需把master配置为不进行save操作(把配置文件中save相关的配置项注释掉即可),然后连接上一个slave,这个slave则被配置为不时地进行save操作的。不过需要注意的是,在这个用例中,必须确保master不会自动启动。更多详情请继续往下读。 Master持久化功能关闭时Replication的安全性 当有需要使用到replication机制时,一般都会强烈建议把master的持久化开关打开。即使为了避免持久化带来的延迟影响,不把持久化开关打开,那么也应该把master配置为不会自动启动的。 为了更好地理解当一个不进行持久化的master如果允许自动启动所带来的危险性。可以看看下面这种失败情形: 假设我们有一个redis节点A,设置为master,并且关闭持久化功能,另外两个节点B和C是它的slave,并从A复制数据。 如果A节点崩溃了导致所有的数据都丢失了,它会有重启系统来重启进程。但是由于持久化功能被关闭了,所以即使它重启了,它的数据集是空的。 而B和C依然会通过replication机制从A复制数据,所以B和C会从A那里复制到一份空的数据集,并用这份空的数据集将自己本身的非空的数据集替换掉。于是就相当于丢失了所有的数据。 即使使用一些HA工具,比如说sentinel来监控master-slaves集群,也会发生上述的情形,因为master可能崩溃后迅速恢复。速度太快而导致sentinel无法察觉到一个failure的发生。 当数据的安全很重要、持久化开关被关闭并且有replication发生的时候,那么应该禁止实例的自启动。 replication工作原理 如果你为master配置了一个slave,不管这个slave是否是第一次连接上Master,它都会发送一个SYNC命令给master请求复制数据。 master收到SYNC命令后,会在后台进行数据持久化,持久化期间,master会继续接收客户端的请求,它会把这些可能修改数据集的请求缓存在内存中。当持久化进行完毕以后,master会把这份数据集发送给slave,slave会把接收到的数据进行持久化,然后再加载到内存中。然后,master再将之前缓存在内存中的命令发送给slave。 当master与slave之间的连接由于某些原因而断开时,slave能够自动重连Master,如果master收到了多个slave并发连接请求,它只会进行一次持久化,而不是一个连接一次,然后再把这一份持久化的数据发送给多个并发连接的slave。 当master和slave断开重连后,一般都会对整份数据进行复制。但从redis2.8版本开始,支持部分复制。 数据部分复制 从2.8版本开始,slave与master能够在网络连接断开重连后只进行部分数据复制。 master会在其内存中创建一个复制流的等待队列,master和它所有的slave都维护了复制的数据下标和master的进程id,因此,当网络连接断开后,slave会请求master继续进行未完成的复制,从所记录的数据下标开始。如果进程id变化了,或者数据下标不可用,那么将会进行一次全部数据的复制。 支持部分数据复制的命令是PSYNC 不需硬盘参与的Replication 一般情况下,一次复制需要将内存的数据写到硬盘中,再将数据从硬盘读进内存,再发送给slave。 对于速度比较慢的硬盘,这个操作会给master带来性能上的损失。Redis2.8版本开始,实验性地加上了无硬盘复制的功能。这个功能能将数据从内存中直接发送到slave,而不用经过硬盘的存储。 不过这个功能目前处于实验阶段,还未正式发布。 相关配置 与replication相关的配置比较简单,只需要把下面一行加到slave的配置文件中: slaveof 192.168.1.1 6379 你只需要把ip地址和端口号改一下。当然,你也可以通过客户端发送SLAVEOF命令给slave。 部分数据复制有一些可调的配置参数,请参考redis.conf文件。 无硬盘复制功能可以通过repl-diskless-sync来配置,另外一个配置项repl-diskless-sync-delay用来配置当收到第一个请求时,等待多个slave一起来请求之间的间隔时间。 只读的slave 从redis2.6版本开始,slave支持只读模式,而且是默认的。可以通过配置项slave-read-only来进行配置,并且支持客户端使用CONFIG SET命令来动态修改配置。 ...

2021-06-18 · 1 min · 111 words · -

valgrind

“valgrind” Valgrind是用于构建动态分析工具的探测框架。它包括一个工具集,每个工具执行某种类型的调试、分析或类似的任务,以帮助完善你的程序。Valgrind的架构是模块化的,所以可以容易地创建新的工具而又不会扰乱现有的结构。 Valgrind中许多有用的工具被作为标准而提供。 Memcheck是一个内存错误检测器。它有助于使你的程序,尤其是那些用C和C++写的程序,更加准确。 Cachegrind是一个缓存和分支预测分析器。它有助于使你的程序运行更快。 Callgrind是一个调用图缓存生成分析器。它与Cachegrind的功能有重叠,但也收集Cachegrind不收集的一些信息。 Helgrind是一个线程错误检测器。它有助于使你的多线程程序更加准确。 DRD也是一个线程错误检测器。它和Helgrind相似,但使用不同的分析技术,所以可能找到不同的问题。 Massif是一个堆分析器。它有助于使你的程序使用更少的内存。 DHAT是另一种不同的堆分析器。它有助于理解块的生命期、块的使用和布局的低效等问题。 SGcheck是一个实验工具,用来检测堆和全局数组的溢出。它的功能和Memcheck互补: SGcheck找到Memcheck无法找到的问题,反之亦然。 BBV是个实验性质的SimPoint基本块矢量生成器。它对于进行计算机架构的研究和开发很有用处。 也有一些对大多数用户没有用的小工具: Lackey是演示仪器基础的示例工具;Nulgrind是一个最小化的Valgrind工具,不做分析或者操作,仅用于测试目的。 https://yuanfentiank789.github.io/2018/11/01/%E7%94%A8Valgrind%E6%A3%80%E6%B5%8B%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F/

2021-06-15 · 1 min · 16 words · -

进程状态

“进程状态” 进程的状态 linux (本文使用linux4.8.4) 下,进程状态大致有7种。 进程状态 说明 TASK_RUNNING 可运行状态。未必正在使用CPU,也许是在等待调度 TASK_INTERRUPTIBLE 可中断的睡眠状态。正在等待某个条件满足 TASK_UNINTERRUPTIBLE 不可中断的睡眠状态。不会被信号中断 __TASK_STOPPED 暂停状态。收到某种信号,运行被停止 __TASK_TRACED 被跟踪状态。进程停止,被另一个进程跟踪 EXIT_ZOMBIE 僵尸状态。进程已经退出,但尚未被父进程或者init进程收尸 EXIT_DEAD 真正的死亡状态 在include/linux/sched.h中,进程状态的定义并没有那么少: /* Task state bitmask. NOTE! These bits are also encoded in fs/proc/array.c: get_task_state(). We have two separate sets of flags: task->state is about runnability, while task->exit_state are about the task exiting. Confusing, but this way modifying one set can’t modify the other one by mistake. / #define TASK_RUNNING 0 #define TASK_INTERRUPTIBLE 1 #define TASK_UNINTERRUPTIBLE 2 #define __TASK_STOPPED 4 #define __TASK_TRACED 8 / in tsk->exit_state / #define EXIT_DEAD 16 #define EXIT_ZOMBIE 32 #define EXIT_TRACE (EXIT_ZOMBIE | EXIT_DEAD) / in tsk->state again */ #define TASK_DEAD 64 #define TASK_WAKEKILL 128 #define TASK_WAKING 256 #define TASK_PARKED 512 #define TASK_NOLOAD 1024 #define TASK_NEW 2048 #define TASK_STATE_MAX 4096 #define TASK_STATE_TO_CHAR_STR “RSDTtXZxKWPNn” ...

2021-06-14 · 5 min · 880 words · -

寄存器, Register

“寄存器, Register” 寄存器 自1946年冯·诺伊曼领导下诞生的世界上第一台通用电子计算机ENIAC至今,计算机技术已经发展了七十多载。 从当初专用于数学计算的庞然大物,到后来大型机服务器时代,从个人微机技术蓬勃发展,到互联网浪潮席卷全球,再到移动互联网、云计算日新月异的当下,计算机变的形态各异,无处不在。 这七十多年中,出现了数不清的编程语言,通过这些编程语言,又开发了无数的应用程序。 可无论什么样的应用程序,什么样的编程语言,最终的程序逻辑都是要交付给CPU去执行实现的 (当然这里有些不严谨,除了CPU,还有协处理器、GPU等等) 。所以了解和学习CPU的原理都是对计算机基础知识的夯实大有裨益。 在七十多年的漫长历程中,也涌现了不少架构的CPU。 MIPS PowerPC x86/x64 IA64 ARM 这篇文章就以市场应用最为广泛的x86-x64架构为目标,通过学习了解它内部的100个寄存器功能作用,来串联阐述CPU底层工作原理。 通过这篇文章,你将了解到: CPU指令执行原理 内存寻址技术 软件调试技术原理 中断与异常处理 系统调用 CPU多任务技术 什么是寄存器 寄存器是CPU内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果以及一些CPU运行需要的信息。 x86架构CPU走的是复杂指令集 (CISC) 路线,提供了丰富的指令来实现强大的功能,与此同时也提供了大量寄存器来辅助功能实现。这篇文章将覆盖下面这些寄存器: 通用寄存器 标志寄存器 指令寄存器 段寄存器 控制寄存器 调试寄存器 描述符寄存器 任务寄存器 MSR寄存器 通用寄存器 首当其冲的是通用寄存器,这些的寄存器是程序执行代码最最常用,也最最基础的寄存器,程序执行过程中,绝大部分时间都是在操作这些寄存器来实现指令功能。 所谓通用,即这些寄存器CPU没有特殊的用途,交给应用程序"随意"使用。注意,这个随意,我打了引号,对于有些寄存器,CPU有一些潜规则,用的时候要注意。 eax: 通常用来执行加法,函数调用的返回值一般也放在这里面 ebx: 数据存取 ecx: 通常用来作为计数器,比如for循环 edx: 读写I/O端口时,edx用来存放端口号 esp: 栈顶指针,指向栈的顶部, Stack Pointer, SP, 堆栈指针 ebp: 栈底指针,指向栈的底部,通常用ebp+偏移量的形式来定位函数存放在栈中的局部变量 esi: 字符串操作时,用于存放数据源的地址 edi: 字符串操作时,用于存放目的地址的,和esi两个经常搭配一起使用,执行字符串的复制等操作 在x64架构中,上面的通用寄存器都扩展成为64位版本,名字也进行了升级。当然,为了兼容32位模式程序,使用上面的名字仍然是可以访问的,相当于访问64位寄存器的低32位。 rax rbx rcx rdx rsp rbp rsi rdi 除了扩展原来存在的通用寄存器,x64架构还引入了8个新的通用寄存器: ...

2021-05-08 · 2 min · 282 words · -

fork vfork clone pthread_create

“fork vfork clone pthread_create” Linux通过clone系统调用实现fork.调用通过一系列的参数标志来指明父、子进程需要共享的资源。fork、vfork、和__clone的库函数都根据各自需要的参数标志去调用clone,然后由clone()去调用do_fork()。 arch(X86)架构的是: fork、vfork、和__clone的库函数最终调用的都是clone系统调用。 至于其它的架构的,可能是通过fork和vfork系统调用。这和本身的实现有关。当然在现在的大多数Linux内核中,就算调用的是fork,在底层基本上传递给do_fork的参数都带有能实现写时复制的一些标志。 fork和 pthread_create,然后利用strace跟踪两者的调用过程, 都是调用的clone。 在Linux中主要提供了fork、vfork、clone三个进程创建方法。 在linux源码中这三个调用的执行过程是执行fork(),vfork(),clone()时,通过一个系统调用表映射到sys_fork(),sys_vfork(),sys_clone(),再在这三个函数中去调用do_fork()去做具体的创建进程工作。 fork fork创建一个进程时,子进程只是完全复制父进程的资源,复制出来的子进程有自己的task_struct结构和pid,但却复制父进程其它所有的资源。例如,要是父进程打开了五个文件,那么子进程也有五个打开的文件,而且这些文件的当前读写指针也停在相同的地方。所以,这一步所做的是复制。这样得到的子进程独立于父进程, 具有良好的并发性,但是二者之间的通讯需要通过专门的通讯机制,如: pipe,共享内存等机制, 另外通过fork创建子进程,需要将上面描述的每种资源都复制一个副本。这样看来,fork是一个开销十分大的系统调用,这些开销并不是所有的情况下都是必须的,比如某进程fork出一个子进程后,其子进程仅仅是为了调用exec执行另一个可执行文件,那么在fork过程中对于虚存空间的复制将是一个多余的过程。但由于现在Linux中是采取了copy-on-write(COW写时复制)技术,为了降低开销,fork最初并不会真的产生两个不同的拷贝,因为在那个时候,大量的数据其实完全是一样的。写时复制是在推迟真正的数据拷贝。若后来确实发生了写入,那意味着parent和child的数据不一致了,于是产生复制动作,每个进程拿到属于自己的那一份,这样就可以降低系统调用的开销。所以有了写时复制后呢,vfork其实现意义就不大了。 fork()调用执行一次返回两个值,对于父进程,fork函数返回子程序的进程号,而对于子程序,fork函数则返回零,这就是一个函数返回两次的本质。 在fork之后,子进程和父进程都会继续执行fork调用之后的指令。子进程是父进程的副本。它将获得父进程的数据空间,堆和栈的副本,这些都是副本,父子进程并不共享这部分的内存。也就是说,子进程对父进程中的同名变量进行修改并不会影响其在父进程中的值。但是父子进程又共享一些东西,简单说来就是程序的正文段。正文段存放着由cpu执行的机器指令,通常是read-only的。下面是一个验证的例子: //例1: fork.c #include<stdio.h> #include<sys/types.h> #include<unistd.h> #include<errno.h> int main() { int a = 5; int b = 2; pid_t pid; pid = fork(); if(pid == 0) { a = a-4; printf("I'm a child process with PID [%d],the value of a: %d,the value of b:%d.\n",pid,a,b); }else if(pid < 0) { perror("fork"); }else { printf("I'm a parent process, with PID [%d], the value of a: %d, the value of b:%d.\n", pid, a, b); } return 0; } #gcc –o fork fork.c #./fork //运行结果: I’m a child process with PID[0],the value of a:1,the value of b:2. I’m a parent process with PID[19824],the value of a:5,the value of b:2. //例1: fork.c #include<stdio.h> #include<sys/types.h> #include<unistd.h> #include<errno.h> int main() { int a = 5; int b = 2; pid_t pid; pid = fork(); if(pid == 0) { a = a-4; printf("I'm a child process with PID [%d],the value of a: %d,the value of b:%d.\n",pid,a,b); }else if(pid < 0) { perror("fork"); }else { printf("I'm a parent process, with PID [%d], the value of a: %d, the value of b:%d.\n", pid, a, b); } return 0; } #gcc –o fork fork.c #./fork ...

2021-05-06 · 12 min · 2459 words · -

workqueue

“workqueue” 转自: http://bgutech.blog.163.com/blog/static/18261124320116181119889/ 什么是workqueue Linux中的Workqueue机制就是为了简化内核线程的创建。通过调用workqueue的接口就能创建内核线程。并且可以根据当前系统CPU的个 数创建线程的数量,使得线程处理的事务能够并行化。workqueue是内核中实现简单而有效的机制,他显然简化了内核daemon的创建,方便了用户的 编程. 工作队列 (workqueue) 是另外一种将工作推后执行的形式.工作队列可以把工作推后,交由一个内核线程去执行,也就是说,这个下半部分可以在进程上下文中执行。最重要的就是工作队列允许被重新调度甚至是睡眠。 那么,什么情况下使用工作队列,什么情况下使用tasklet。如果推后执行的任务需要睡眠,那么就选择工作队列。如果推后执行的任务不需要睡眠,那么就 选择tasklet。另外,如果需要用一个可以重新调度的实体来执行你的下半部处理,也应该使用工作队列。它是唯一能在进程上下文运行的下半部实现的机 制,也只有它才可以睡眠。这意味着在需要获得大量的内存时、在需要获取信号量时,在需要执行阻塞式的I/O操作时,它都会非常有用。如果不需要用一个内核 线程来推后执行工作,那么就考虑使用tasklet。

2021-05-05 · 1 min · 14 words · -

上下文切换

“上下文切换” 操作系统上线程的切换也不是免费的,线程切换其实会带来额外的开销,其中包括: 保存线程 1 的执行上下文; 加载线程 2 的执行上下文; 频繁的对线程的上下文进行切换可能还会导致性能地急剧下降,这可能会导致我们不仅没有提升请求处理的平均速度,反而进行了负优化,所以这也是为什么 Redis 对于使用多线程技术非常谨慎。 我们都知道,Linux 是一个多任务操作系统,它支持远大于 CPU 数量的任务同时运行。当然,这些任务实际上并不是真的在同时运行,而是因为系统在很短的时间内,将 CPU 轮流分配给它们,造成多任务同时运行的错觉。 而在每个任务运行前,CPU 都需要知道任务从哪里加载、又从哪里开始运行,也就是说,需要系统事先帮它设置好CPU 寄存器和程序计数器 什么是 CPU 上下文 CPU 寄存器和程序计数器就是 CPU 上下文,因为它们都是 CPU 在运行任何任务前,必须的依赖环境。 CPU 寄存器是 CPU 内置的容量小、但速度极快的内存。 程序计数器则是用来存储 CPU 正在执行的指令位置、或者即将执行的下一条指令位置。 什么是 CPU 上下文切换 就是先把前一个任务的 CPU 上下文 (也就是 CPU 寄存器和程序计数器) 保存起来,然后加载新任务的上下文到这些寄存器和程序计数器,最后再跳转到程序计数器所指的新位置,运行新任务。 而这些保存下来的上下文,会存储在系统内核中,并在任务重新调度执行时再次加载进来。这样就能保证任务原来的状态不受影响,让任务看起来还是连续运行。 CPU 上下文切换的类型 根据任务的不同,可以分为以下三种类型 - 进程上下文切换 - 线程上下文切换 - 中断上下文切换 进程上下文切换 Linux 按照特权等级,把进程的运行空间分为内核空间和用户空间,分别对应着下图中, CPU 特权等级的 Ring 0 和 Ring 3。 内核空间 (Ring 0) 具有最高权限,可以直接访问所有资源; 用户空间 (Ring 3) 只能访问受限资源,不能直接访问内存等硬件设备,必须通过系统调用陷入到内核中,才能访问这些特权资源。 ...

2021-05-05 · 1 min · 178 words · -

neofetch, linux logo ascii

“neofetch, linux logo ascii” neofetch, linux logo ascii neofetch 是一个跨平台的易于使用的 系统信息显示命令行脚本,它收集你的系统信息,并在终端中和图像一起显示出来,这个图像可能是你的发行版的 logo 也可能是你选择的一幅 ascii 艺术字。 Neofetch 和 ScreenFetch 或者 Linux_Logo 很像,但是它可以高度定制,并且还有一些额外的我们要在下面讨论的特点。 它的主要特点有: 运行速度快,可以显示全色图像 —— 用 ASCII 字符显示的发行版 logo ,旁边显示系统信息,可以高度定制,可以随时随地显示系统信息,并且在脚本结束的时候还可以通过一个特殊的参数来启用桌面截图。 系统要求: Bash 3.0+ 带 ncurses 支持。 w3m-img (有时候会打包成 w3m) 或者 iTerm2 或者 Terminology,用于显示图像。 imagemagick,用于创建缩略图。 支持 [\033[14t 的 Linux 终端模拟器 或者 xdotool 或者 xwininfo + xprop 或者 xwininfo + xdpyinfo 。 Linux 系统中还需要 feh、nitrogen 或者 gsettings 来提供对墙纸的支持。 注意: 你可以从 Neofetch 的 Github 页面了解更多关于可选依赖的信息,以检查你的 Linux 终端模拟器 是不是真的支持 \033[14t 或者是否需要一些额外的依赖来使这个脚本在你的发行版上工作得更好。 ...

2021-04-30 · 1 min · 166 words · -