task_struct, 进程描述符, 进程控制块 (PCB)

“task_struct, 进程描述符, 进程控制块 (PCB)” task struct, task_struct, 进程描述符, 进程控制块 (PCB) https://github.com/torvalds/linux/blob/master/include/linux/sched.h 进程是资源分配的基本单位。 进程控制块 (Process Control Block, PCB) 描述进程的基本信息和运行状态,所谓的创建进程和撤销进程,都是指对 PCB 的操作。 进程是处于执行期的程序以及它所管理的资源 (如打开的文件、挂起的信号、进程状态、地址空间等等) 的总称。注意,程序并不是进程,实际上两个或多个进程不仅有可能执行同一程序,而且还有可能共享地址空间等资源。 Linux内核通过一个被称为进程描述符的task_struct结构体来管理进程,这个结构体包含了一个进程所需的所有信息。它定义在include/linux/sched.h文件中。 谈到task_struct结构体,可以说她是linux内核源码中最复杂的一个结构体了,成员之多,占用内存之大。 鉴于她的复杂,我们不能简单的亵渎,而是要深入"窥探". 下面来慢慢介绍这些复杂成员 进程状态 volatile long state; /-1 unrunnable, 0 runnable, >0 stopped/ state成员的可能取值如下 参见http://lxr.free-electrons.com/source/include/linux/sched.h?v=4.5#L207 /* 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) ...

Created 17176-04-17 · Updated 17176-04-17 · 14 min · 2911 words · -

pmod, 实模式和保护模式

“pmod, 实模式和保护模式” 实模式和保护模式都是CPU的工作模式,而CPU的工作模式是指CPU的寻址方式、寄存器大小等用来反应CPU在该环境下如何工作的概念。 实模式 实模式出现于早期 8088CPU时期。当时由于CPU的性能有限,一共只有20位地址线 (所以地址空间只有1MB) ,以及8个16位的通用寄存器,以及4个16位的段寄存器。所以为了能够通过这些16位的寄存器去构成20位的主存地址,必须采取一种特殊的方式。当某个指令想要访问某个内存地址时,它通常需要用下面的这种格式来表示: (段基址: 段偏移量) 其中第一个字段是段基址,它的值是由段寄存器提供的(一般来说,段寄存器有6种,分别为cs,ds,ss,es,fs,gs,这几种段寄存器都有自己的特殊意义,这里不做介绍)。 第二字段是段内偏移量,代表你要访问的这个内存地址距离这个段基址的偏移。它的值就是由通用寄存器来提供的,所以也是16位。那么两个16位的值如何组合成一个20位的地址呢?CPU采用的方式是把段寄存器所提供的段基址先向左移4位。这样就变成了一个20位的值,然后再与段偏移量相加。 即: 物理地址 = 段基址«4 + 段内偏移 所以假设段寄存器中的值是0xff00,段偏移量为0x0110。则这个地址对应的真实物理地址是 0xff00«4 + 0x0110 = 0xff110。 由上面的介绍可见,实模式的"实"更多地体现在其地址是真实的物理地址。 保护模式 随着CPU的发展,CPU的地址线的个数也从原来的20根变为现在的32根,所以可以访问的内存空间也从1MB变为现在4GB,寄存器的位数也变为32位。所以实模式下的内存地址计算方式就已经不再适合了。所以就引入了现在的保护模式,实现更大空间的,更灵活也更安全的内存访问。 在保护模式下,CPU的32条地址线全部有效,可寻址高达4G字节的物理地址空间; 但是我们的内存寻址方式还是得兼容老办法(这也是没办法的,有时候是为了方便,有时候是一种无奈),即(段基址: 段偏移量) 的表示方式。当然此时CPU中的通用寄存器都要换成32位寄存器(除了段寄存器,原因后面再说)来保证寄存器能访问所有的4GB空间。 我们的偏移值和实模式下是一样的,就是变成了32 位而已,而段值仍旧是存放在原来16位的段寄存器中,但是这些段寄存器存放的却不再是段基址了,毕竟之前说过实模式下寻址方式不安全,我们在保护模式下需要加一些限制,而这些限制可不是一个寄存器能够容纳的,于是我们把这些关于内存段的限制信息放在一个叫做全局描述符表(GDT)的结构里。全局描述符表中含有一个个表项,每一个表项称为段描述符。而段寄存器在保护模式下存放的便是相当于一个数组索引的东西,通过这个索引,可以找到对应的表项。段描述符存放了段基址、段界限、内存段类型属性(比如是数据段还是代码段,注意一个段描述符只能用来定义一个内存段)等许多属性,具体信息见下图: 图1 段描述符格式 其中,段界限表示段边界的扩张最值,即最大扩展多少或最小扩展多少,用20位来表示,它的单位可以是字节,也可以是4KB,这是由G位决定的(G为1时表示单位为4KB)。 实际段界限边界值=(描述符中的段界限+1)* (段界限的单位大小(即字节或4KB))-1,如果偏移地址超过了段界限,CPU会抛出异常。 全局描述符表位于内存中,需要用专门的寄存器指向它后, CPU 才知道它在哪里。这个专门的寄存器便是GDTR(一个48位的寄存器),专门用来存储 GDT 的内存地址及大小。 最后我们再介绍一下一个新的概念: 段的选择子。段寄存器 CS、 DS、 ES、 FS、 GS、 SS,在实模式下时,段中存储的是段基地址,即内存段的起始地址。 而在保护模式下时,由于段基址已经存入了段描述符中,所以段寄存器中再存放段基址是没有意义的,在段寄存器中存入的是一个叫作选择子的东西。选择子"基本上"是个索引值,虽然它还有其他内容,不过作为初学者暂时忽略也没太大关系。由于段寄存器是 16 位,所以选择子也是 16 位,在其低 2 位即第 0~1 位, 用来存储 RPL,即请求特权级(有兴趣的可以了解一下,不想了解的忽略即可,跟用户态和内核态相关的),可以表示 0、 1、 2、 3 四种特权级。在选择子的第 2 位是 TI 位,即 Table Indicator,用来指示选择子是在 GDT 中,还是 LDT 中索引描述符。 TI 为 0 表示在 GDT 中索引描述符, TI 为 1 表示在 LDT 中索引描述符。选择子的高 13 位,即第 3~15 位是 描述符的索引值,用此值在 GDT 中索引描述符。前面说过 GDT 相当于一个描述符数组,所以此选择子中的索引值就是 GDT 中的下标。选择子结构如下: ...

Created 17176-04-17 · Updated 17176-04-17 · 2 min · 254 words · -

系统调用, System Call

“系统调用, System Call” 计算机系统的各种硬件资源是有限的,在现代多任务操作系统上同时运行的多个进程都需要访问这些资源,为了更好的管理这些资源进程是不允许直接操作的,所有对这些资源的访问都必须有操作系统控制。也就是说操作系统是使用这些资源的唯一入口,而这个入口就是操作系统提供的系统调用 (System Call) 。在linux中系统调用是用户空间访问内核的唯一手段,除异常和陷入外,他们是内核唯一的合法入口。 一般情况下应用程序通过应用编程接口API,而不是直接通过系统调用来编程。在Unix世界,最流行的API是基于POSIX标准的。 操作系统一般是通过中断从用户态切换到内核态。中断就是一个硬件或软件请求,要求CPU暂停当前的工作,去处理更重要的事情。比如,在x86机器上可以通过int指令进行软件中断,而在磁盘完成读写操作后会向CPU发起硬件中断。 中断有两个重要的属性,中断号和中断处理程序。中断号用来标识不同的中断,不同的中断具有不同的中断处理程序。在操作系统内核中维护着一个中断向量表 (Interrupt Vector Table) ,这个数组存储了所有中断处理程序的地址,而中断号就是相应中断在中断向量表中的偏移量。 一般地,系统调用都是通过软件中断实现的,x86系统上的软件中断由int $0x80指令产生,而128号异常处理程序就是系统调用处理程序system_call(),它与硬件体系有关,在entry.S中用汇编写。接下来就来看一下Linux下系统调用具体的实现过程。 为什么需要系统调用 linux内核中设置了一组用于实现系统功能的子程序,称为系统调用。系统调用和普通库函数调用非常相似,只是系统调用由操作系统核心提供,运行于内核态,而普通的函数调用由函数库或用户自己提供,运行于用户态。 一般的,进程是不能访问内核的。它不能访问内核所占内存空间也不能调用内核函数。CPU硬件决定了这些 (这就是为什么它被称作"保护模式" (详细参见深入理解计算机系统-之-内存寻址 (二) –存储保护机制 (CPU实模式与保护模式) ) ) 。 为了和用户空间上运行的进程进行交互,内核提供了一组接口。透过该接口,应用程序可以访问硬件设备和其他操作系统资源。这组接口在应用程序和内核之间扮演了使者的角色,应用程序发送各种请求,而内核负责满足这些请求(或者让应用程序暂时搁置)。实际上提供这组接口主要是为了保证系统稳定可靠,避免应用程序肆意妄行,惹出大麻烦。 系统调用在用户空间进程和硬件设备之间添加了一个中间层。该层主要作用有三个: 它为用户空间提供了一种统一的硬件的抽象接口。比如当需要读些文件的时候,应用程序就可以不去管磁盘类型和介质,甚至不用去管文件所在的文件系统到底是哪种类型。 系统调用保证了系统的稳定和安全。作为硬件设备和应用程序之间的中间人,内核可以基于权限和其他一些规则对需要进行的访问进行裁决。举例来说,这样可以避免应用程序不正确地使用硬件设备,窃取其他进程的资源,或做出其他什么危害系统的事情。 每个进程都运行在虚拟系统中,而在用户空间和系统的其余部分提供这样一层公共接口,也是出于这种考虑。如果应用程序可以随意访问硬件而内核又对此一无所知的话,几乎就没法实现多任务和虚拟内存,当然也不可能实现良好的稳定性和安全性。在Linux中,系统调用是用户空间访问内核的惟一手段;除异常和中断外,它们是内核惟一的合法入口。 Linux 的系统调用主要有以下这些: Task Commands 进程控制 fork(); exit(); wait(); 进程通信 pipe(); shmget(); mmap(); 文件操作 open(); read(); write(); 设备操作 ioctl(); read(); write(); 信息维护 getpid(); alarm(); sleep(); 安全 chmod(); umask(); chown(); 从"read"看系统调用的耗时 fread和read有何不同 先看两段代码: fread #include<stdio.h> #include<stdlib.h> FILE* pf = fopen("test.txt", "r"); char buf[2] = { 0 }; int ret = 0; do { ret = fread(buf, 1, 1, pf); } while (ret); read #include<stdio.h> #include<stdlib.h> FILE* pf = fopen("test.txt", "r"); char buf[2] = { 0 }; int ret = 0; do { ret = read(buf, 1, 1, pf); } while (ret); 两个文件的功能完全一样,打开同一个名为test.file的文件,并逐字节地读取整个文件。 将它们编译后得到的可执行程序fread和read分别在同一台PC (linux系统) 上执行, fread与read的耗时相差数十倍之多!可见啊~read一个字节这种写法是相当不可取的! ...

Created 15156-04-15 · Updated 15156-04-15 · 8 min · 1685 words · -

ap

“ap” 商用 AP 厂商: aruba/安移通, ruckus/优科 … ruckus 的 unleashed 系列AP, unleashed 系列最大的优势是: Wi-Fi非常稳定,快速漫游、无缝切换、 5G占比调节等都是基本操作 配置界面非常友好,由浅入深、简单易懂,即使是新手也完全可以应付的来 刷机省钱。ruckus的AP对自主刷固件支持,比如R310刷R310 unleashed版本,前者售价850左右,后者950左右?没有商业注册限制,在ruckus官网注册就可以下载固件 闲鱼上很多R系列的再售,价格不高 (本文三台 两个买家购入 带标签的翻车了 且卖家不退换 所以没打码) 本教程用的是 Ruckus R310,三只一共价格在1000元左右,覆盖办公室面积400平+,浏览器为Safari,其他有unleashed固件的AP型号通用,但由于功耗不同有可能需要用到功率更大的802.3at的POE标准的交换机 如果有更高阶的需求,可以考虑R5X0 R6X0 R7X0系列,其中R730 R750 R650是支持Wi-Fi6的 https://zhuanlan.zhihu.com/p/118554342 RUCKUS H320 https://webresources.ruckuswireless.com/datasheets/h320/ds-commscope-h320-zh-cn.html H350 https://support.ruckuswireless.com/products/191-ruckus-h350?open=document#sort=relevancy&f:@source=[Documentation]&f:@commonproducts=[H350]

Created 10106-04-10 · Updated 10106-04-10 · 1 min · 38 words · -

network topology

“network topology” @startuml [光猫] as onu package "J4100 \n 4网口工控机" { interface "ETH1\nenp1s0" as j4100Eth1 interface "ETH2\nenp2s0" as j4100Eth2 interface "ETH2\neno1" as j4100Eth3 interface "ETH3\nenp4s0" as j4100Eth4 agent vmbr0 j4100Eth1 -down- vmbr0 j4100Eth3 -down- vmbr0 j4100Eth4 -down- vmbr0 agent vmbr1 j4100Eth2 -down- vmbr1 [Openwrt] as router router - vmbr0 vmbr1 -down- router } onu -down- j4100Eth2 @enduml

Created 3036-04-03 · Updated 3036-04-03 · 1 min · 57 words · -

dm-crypt, 加密

dm-crypt, 加密 dm-crypt 是整合到 linux 内核中的,而它的命令行前端 cryptsetup, 在大多数主流的 linux 发行版中都会自带 LUKS = Linux Unified Key Setup commands # 将分区设置为加密的 LUKS 分区, 这个时候会对磁盘分区进行全盘覆写,所以速度会比较慢 # luksFormat: 初始化并格式化一个分区以便使用 LUKS 加密。 # luksOpen: 打开一个已加密的 LUKS 分区,使其可用。 # luksClose: 关闭一个已打开的 LUKS 分区。 # status: 查看加密设备的状态。 cryptsetup luksFormat /dev/nvme0n1p1 cryptsetup luksOpen /dev/nvme0n1pX cryptroot # 打开加密的 LUKS 分区, 映射加密分区到 nvme0n1p1_encrypted, # 将加密分区映射到逻辑分区 /dev/mapper/nvme0n1p8_crypt cryptsetup open /dev/nvme0n1p1 nvme0n1p1_encrypted # 重设 PV 上加密层的大小 # https://unix.stackexchange.com/questions/322905/what-does-cryptsetup-resize-do-if-luks-doesnt-store-partition-size sudo cryptsetup resize /dev/mapper/devicemappername 用 cryptsetup 创建 LUKS 的虚拟加密盘 (逻辑卷) 在前一个章节,已经介绍了"对物理分区的加密"。其实 cryptsetup 也可以支持虚拟加密盘 (逻辑加密盘) ——类似于 TrueCrypt 那样。 ...

Created 30306-03-30 · Updated 30306-03-30 · 1 min · 205 words · -

X Server, XServer

“X Server, XServer” 背景 大多数时候我们不希望在服务器上安装图形界面,但有时候有些程序需要图形界面,比如安装Oracle的时候。此时,可以配置让Linux使用远程的X Server进行图形界面显示。 首先要明确的是Linux X Window System的基本原理,X是一个开放的协议规范,当前版本为11,俗称X11。X Window System由客户端和服务端组成,服务端X Server负责图形显示,而客户端库X Client根据系统设置的DISPLAY环境变量,将图形显示请求发送给相应的X Server。 因此,我们只需要在远端开启一个X Server,并在目标机器上相应的设置DISPLAY变量,即可完成图形的远程显示。 command export DISPLAY=192.168.97.183:0 ~/.xinitrc是X的配置文件,在 /etc/skel/.xinitrc 有它的模板,可以把它copy到用户目录下面: $ cp /etc/skel/.xinitrc ~ 以".“开头的文件,通常是隐藏文件,用普通的"ls"是查看不到的,若想查看,需要用"ls -A"命令。 其次,以"rc"结尾的文件代表它是运行的命令行或者是配置文件。又因为它通常控制着程序的运行,所以也通常叫着"run control” https://blog.csdn.net/vic_qxz/article/details/79073558

Created 29296-03-29 · Updated 29296-03-29 · 1 min · 32 words · -

kux

“kux” kux 转 mp4 https://zhuanlan.zhihu.com/p/111764932 安装youku客户端 执行脚本 @echo off setlocal enabledelayedexpansion set ffmpeg="C:\Program Files (x86)\YouKu\YoukuClient\nplayer\ffmpeg.exe" if exist %ffmpeg% ( for /r . %%i in (*.kux) do ( %ffmpeg% -y -i "%%i" -c:a copy -c:v copy -threads 2 "%%~dpni.mp4" ) ) else echo pause

Created 27276-03-27 · Updated 27276-03-27 · 1 min · 43 words · -

arp table, arp 表

“arp table, arp 表” ARP表(Address Resolution Table) ARP协议 首先明确一点,在以太网环境下,同一个网段的主机之间需要知道对方的MAC地址,才能进行通信。 上一节介绍了交换机的工作原理,了解到交换机是根据MAC寻址,查表确认输出端口以完成本节点转发任务的。看到这里其实应该可以抛出从一开始就被我们忽视了的问题: 在初始构造数据包准备发送时,源主机究竟要如何获得目的主机网络设备MAC地址的呢?这时,就需要使用到ARP协议。在网络拓扑中的每个节点或说主机上,实际都维护有一张ARP表,它记录着主机的IP地址(网络地址)到MAC地址(物理地址)的映射关系。 ARP协议,即地址解析协议,它是一个网络层协议,运行在各网络节点上,负责完成主机IP地址到MAC地址的映射。 ip neighbour–neighbour/arp 表管理命令 ip neighbour–neighbour/arp 表管理命令 缩写 neighbour、neighbor、neigh、n 命令 add、change、replace、delete、fulsh、show(或者list) ip neighbour add -----添加一个新的邻接条目 ip neighbour change -----修改一个现有的条目 ip neighbour replace -----替换一个已有的条目 缩写: add、a;change、chg;replace、repl 例: 在设备eth0上,为地址 10.0.0.3 添加一个 permanent ARP条目: ip neigh add 10.0.0.3 lladdr 0:0:0:0:0:1 dev eth0 nud perm 例: 把状态改为 reachable ip neigh chg 10.0.0.3 dev eth0 nud reachable ip neighbour delete ---删除一个邻接条目 例: 删除设备eth0上的一个ARP条目10.0.0.3 ip neigh del 10.0.0.3 dev eth0 ip neighbour show -- 显示网络邻居的信息. 缩写: show、list、sh、ls 例: # ip -s n ls 193.233.7.254 193.233.7.254. dev eth0 lladdr 00:00:0c:76:3f:85 ref 5 used 12/13/20 nud reachable ...

Created 23236-03-23 · Updated 23236-03-23 · 1 min · 116 words · -

vuetify

“vuetify” 安装相应包 yarn add @mdi/font -D # roboto字体其实不要也行,就英文的一套字体而已 yarn add typeface-roboto -D plugins/vuetify.js import Vue from 'vue'; import Vuetify from 'vuetify/lib'; import zhHans from 'vuetify/es5/locale/zh-Hans' // 引入中文语言包 import 'typeface-roboto/index.css' // 引入本地的Roboto字体资源 import '@mdi/font/css/materialdesignicons.css' // 引入本地的Material Design Icons资源 Vue.use(Vuetify); export default new Vuetify({ lang:{ locales: {zhHans}, current: 'zhHans' }, icons:{ iconfont: 'mdi', // 设置使用本地的icon资源 } }); 模板中使用 <template> <v-icon>mdi-account-circle</v-icon> </div> </template> <script> export default { } </script> replace google font,mdi font with local resource 注释掉public/index.html中引用的字体 ...

Created 16166-03-16 · Updated 16166-03-16 · 1 min · 77 words · -

cypress

cypress npm install cypress --save-dev npx cypress open install cypress for project npm install --save-dev cypress # 执行cypress install, 把cypress安装到 ~/.cache/Cypress node_modules/cypress/bin/cypress install install MySQL npm install MySQL --save-dev 配置MySQL连接信息, 修改 cypress.json 成这样 { "pluginsFile": "tests/e2e/plugins/index.js", "env": { "db": { "host": "192.168.1.xxx", "user": "user0", "password": "password0", "database": "database0" } } } 配置 tests/e2e/plugins/index.js const MySQL = require('MySQL') function queryTestDb (query, config) { const connection = MySQL.createConnection(config.env.db) connection.connect() return new Promise((resolve, reject) => { connection.query(query, (error, results) => { if (error) reject(error) else { connection.end() console.log(results) console.log('connected') return resolve(results) } }) }) } module.exports = (on, config) => { on('task', { log (message) { console.log(message) return null } }) on('task', { queryDb: query => { return queryTestDb(query, config) } }) return Object.assign({}, config, { fixturesFolder: 'tests/e2e/fixtures', integrationFolder: 'tests/e2e/specs', screenshotsFolder: 'tests/e2e/screenshots', videosFolder: 'tests/e2e/videos', supportFile: 'tests/e2e/support/index.js' }) } command timeout cy.visit('/', { timeout: 3000 }) type cy.get('[data-cy=user-name]').type('user0') click cy.get('[data-cy=login]').click() contains cy.get('[data-cy=list]').find('tbody>tr').first().contains('td', 'id0') clear cy.get('[data-cy=plate]').clear() 页面元素数量, 3个 text0 文字 cy.contains('span', 'text0').should('have.length', 3) 比较文本 cy.get('[data-cy=foo]').should('have.text',"0") cy.get('[data-cy=foo]').should('not.have.text',"0") sql cy.task('queryDb', 'DELETE FROM `table0`').then(res => { cy.log(res) }) count cy.task('queryDb', 'SELECT COUNT(*) AS count FROM table0 WHERE field0=\'value0\'').then(res => { expect(res[0].count).to.equal(1) }) 配置 NODE_ENV "scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build", "test:unit": "vue-cli-service test:unit", "test:e2e": "NODE_ENV=development vue-cli-service test:e2e", "lint": "vue-cli-service lint" },

Created 16166-03-16 · Updated 16166-03-16 · 1 min · 205 words · -

Ant 风格路径表达式, ant style

Ant 风格路径表达式, ant style ANT通配符有三种: 通配符 说明 ? 匹配任何单字符 * 匹配0或者任意数量的字符 ** 匹配0或者更多的目录 例子: URL路径 说明 /app/*.x 匹配(Matches)所有在app路径下的.x文件 /app/p?ttern 匹配(Matches) /app/pattern 和 /app/pXttern,但是不包括/app/pttern /**/example 匹配(Matches) /app/example, /app/foo/example, 和 /example /app/**/dir/file.* 匹配(Matches) /app/dir/file.jsp, /app/foo/dir/file.html,/app/foo/bar/dir/file.pdf, 和 /app/dir/file.java /**/*.jsp 匹配(Matches)任何的.jsp 文件 最长匹配原则(has more characters) URL请求/app/dir/file.jsp,现在存在两个路径匹配模式/**/.jsp和/app/dir/.jsp,那么会根据模式/app/dir/*.jsp来匹配 作者: 芒果粑粑 链接: https://www.jianshu.com/p/189847a7d1c7 来源: 简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Created 5056-03-05 · Updated 5056-03-05 · 1 min · 49 words · -

challenge response, 挑战应答

challenge response, 挑战应答 挑战应答方式”:challenge-response,是零知识证明的方式。 Challenge/Response认证的过程如下: 客户端向服务器发出认证请求; 认证服务器从用户数据库中查询用户是否是合法的用户,若不是,则不做进一步的处理; 认证服务器内部产生一个随机数,作为 “提问” / Challenge,发送给用户; 客户将口令和随机数合并,使用单向 Hash 函数 ( 例如MD5算法 ) 生成一个字节串作为Response; 认证服务器将 Response 与自己的计算结果比较,如两者相同,则通过一次认证,反之认证失败; 认证服务器通知客户端认证成功或失败。 以后的认证由客户不定时发起,过程中没有了客户认证请求一步。两次认证的时间间隔不能太短,否则就给网络、客户和认证服务器带来太大的开销;但也不能太长,否则不能保证用户不被他人盗用IP地址,一般定为1-2分钟。 密钥的分配和管理 密钥的分配由维护模块负责,当用户进行注册时,自行设定自己的口令。用户的密钥由口令生成。 一个口令必须经过两次口令检查。第一次由注册程序检查,强制口令必须有足够的长度。口令被加密后送入数据库,这个口令标记为“未检查的”。第二次,由离线的口令检查工具进行检查,将弱口令进行标记,当下次用户认证时,认证服务器将强制用户修改口令。 密钥的在线修改由认证服务器完成,其过程与认证过程基本类似。 Challenge/Response认证的安全性分析: 下面就常见的对认证服务器攻击方法来分析其安全性。 网络侦听 ( sniffer ) 认证过程中,密钥和口令不是明文不在网络上传输,所以sniffer很难从听到的报文中得到用户的口令。在密钥在线修改过程中,新口令使用旧密钥加密传送,sniffer 攻击仍然无效。 replay attack, 重放攻击 每次 challenge 不同,所以 replay attack 无效。 password guessing 在知道了认证算法后,侦听者可以对用户的口令进行猜测。这种攻击方法直接有效,特别是当用户的口令有缺陷时。解决方法是使用合适的口令。 跟踪地址攻击 攻击者在看到用户认证后,设法将自己的机器地址改为用户的IP地址,从而冒充用户。但由于攻击者无法完成后续的认证,在1-2分钟内,攻击失效。 https://blog.csdn.net/zy531/article/details/6205306 https://en.wikipedia.org/wiki/Challenge%E2%80%93response_authentication

Created 18186-02-18 · Updated 18186-02-18 · 1 min · 51 words · -

xbox

“xbox” HALO 战争机器 皇牌空战6 Forza4 忍者龙剑传2 荒野大镖客: 救赎 合金装备系列 鬼泣: DMC 给他爱IV;V 寂静岭系列 生化危机系列 刺客信条3、4 (大革命不清楚可不可以) 战地3、4、硬仗 蝙蝠侠阿卡姆系列 极品飞车系列 cod系列 (好像最高能支持12) 火影忍者: 究极忍者风暴 狗1丁丁历险记 (墙裂推荐) 孤岛惊魂3、4孤岛危机3 (不过手柄操作很不舒服,外星人基本只能苟或者开厚皮以老拳挥之) 老滚5尘埃黑魂2 (不清楚3能不能玩) 心灵杀手 (Alan wake) 这个大赞!黑道圣徒死或生忍龙阁门禁锁47 (强烈推荐5) 漫威英雄大战卡普空睡犬 (热血无赖) 古墓丽影9、10ff系列 (好像最高到雷霆归来) 狙击手光环系列 作者: Leo唉趣稀 链接: https://www.zhihu.com/question/299721178/answer/516954491 来源: 知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Created 10106-02-10 · Updated 10106-02-10 · 1 min · 46 words · -

gdb

“gdb” GDB是什么 GDB 全称"GNU symbolic debugger",从名称上不难看出,它诞生于 GNU 计划 (同时诞生的还有 GCC、Emacs 等) ,是 Linux 下常用的程序调试器。发展至今,GDB 已经迭代了诸多个版本,当下的 GDB 支持调试多种编程语言编写的程序,包括 C、C++、Go、Objective-C、OpenCL、Ada 等。实际场景中,GDB 更常用来调试 C 和 C++ 程序。 Windows 操作系统中,人们更习惯使用一些已经集成好的开发环境 (IDE) ,如 VS、VC、Dev-C++ 等,它们的内部已经嵌套了相应的调试器。 GDB的吉祥物: 弓箭鱼 图 1 GDB 的吉祥物: 弓箭鱼 总的来说,借助 GDB 调试器可以实现以下几个功能: 程序启动时,可以按照我们自定义的要求运行程序,例如设置参数和环境变量; 可使被调试程序在指定代码处暂停运行,并查看当前程序的运行状态 (例如当前变量的值,函数的执行结果等) ,即支持断点调试; 程序执行过程中,可以改变某个变量的值,还可以改变代码的执行顺序,从而尝试修改程序中出现的逻辑错误。 GDB (GNU Debugger) 是UNIX及UNIX-like下的强大调试工具,可以调试ada, c, c++, asm, minimal, d, fortran, objective-c, go, java,pascal等语言。 对于C程序来说,需要在编译时加上-g参数,保留调试信息,否则不能使用GDB进行调试。 但如果不是自己编译的程序,并不知道是否带有-g参数,如何判断一个文件是否带有调试信息呢? gdb 文件 例如: $ gdb helloworld Reading symbols from helloWorld…(no debugging symbols found)…done. 如果没有调试信息,会提示no debugging symbols found。 如果是下面的提示: ...

Created 6066-01-06 · Updated 6066-01-06 · 1 min · 124 words · -

ECMAScript, javascript basic

ECMAScript, javascript basic, js basic https://juejin.cn/post/7103511045062590500 JavaScript 是一种轻量级脚本语言, 它本身不提供 I/O 相关的 API, I/O 操作需要宿主环境提供, <!DOCTYPE html> <html> <head> <script src="foo.js"></script> <script type="text/javascript"> console.log('javascript0') var myVar = "hello"; function showAlert() { alert('You triggered an alert!'); } </script> </head> <body> body0 <button> </body> </html> 模板字面量, 多行字符串 let learnCoding = `How to start learning web development? - Learn HTML - Learn CSS - Learn JavaScript Use freeCodeCamp to learn all the above and much, much more ! ` console.log(learnCoding); // 输出 // How to start learning web development? // - Learn HTML // - Learn CSS // - Learn JavaScript // Use freeCodeCamp to learn all the above and much, much more ! 数组 JavaScript 数组是可调整大小的,并且可以包含不同的数据类型。 ...

Created 3036-12-03 · Updated 3036-12-03 · 2 min · 231 words · -

照片管理

“照片管理” golang + vue https://github.com/photoprism/photoprism

Created 2026-12-02 · Updated 2026-12-02 · 1 min · 5 words · -

tcp sack

“tcp sack” https://blog.csdn.net/wdscq1234/article/details/52503315 TCP-IP详解: SACK选项 (Selective Acknowledgment) 引入理由 在文章TCP-IP详解: 超时重传机制中,有介绍到快速重传和超时重传都会面临到一个重传什么包的问题,因为发送端也不清楚丢失包后面传送的数据是否有成功的送到。主要原因还是对于TCP的确认系统,不是特别的好处理这种不连续确认的状况了,只有低于ACK number的片段都被收到才有进行ACK,out-of-order的片段只能是等待,同时,这个时间窗口是无法向右移动的。 举个例子: 服务发送4个片段给客户端,seg1(seq=1,len=80),seg2(seq=81,len=120), seg3(seq=201,len=160),seg4(seq=361,len=140) 服务器收到seg1和seg2的ACK = 201,所以此时seg1 seg2变成发送并已经确认范畴的数据包,被移除滑动窗口,此时服务器又可以多发80+120 byte数据 假设seg3由于某些原因丢失,这个时候服务器仍然可以像客户端发送数据,但是服务器会等待seg3的ACK,否则窗口无法滑动,卡主了 seg3丢失了,即使后面的seg4收到了,客户端也无法告知服务器已经收到了seg4,试想一下,如果窗口也够大,服务器可以继续持续发送更多的片段,那么这些片段被客户端接收,只能存放到队列中,无法进行确认 正式因为后续OUT-OF-ORDER的报文段的发送状况也不清楚,所以Server也不是特别清楚要如何去处理这种状况,不过一般来说只能有2中状况: 只重传超时的数据包,这种方法是最常想到的,比较实用与后面的数据包都能够正常接收的状况,只重传超时的数据包,但是如果比较坏的情况下,丢失了很多封包呢? 那就需要一个一个的等待超时了,很浪费时间。 重传这个片段以及之后的所有包,这种方法在最坏的状况下,看起来效率还是挺高的,但是如果只有一个包丢失,就去重传后面所有接受到的包,流量浪费也是很严重的。 总之对于上面阐述的问题,没有想到一个好的思路来解。但是RFC2018提供了一个SACK的方法,有效的解决这个问题 SACK(Selective Acknowledgment) SACK是一个TCP的选项,来允许TCP单独确认非连续的片段,用于告知真正丢失的包,只重传丢失的片段。要使用SACK,2个设备必须同时支持SACK才可以,建立连接的时候需要使用SACK Permitted的option,如果允许,后续的传输过程中TCP segment中的可以携带SACK option,这个option内容包含一系列的非连续的没有确认的数据的seq range,这些 SYN包中SACK Permitted 选项,双方都支持才对 SACK option格式 Kind 5 Length 剩下的都是没有确认的segment的range了 比如说segment 501-600 没有被确认,那么Left Edge of 1st Block = 501,Right Edge of 1st Block = 600,TCP的选项不能超过40个字节,所以边界不能超过4组。 可以看下实际的tcpdump抓包中的SACK option,如下图,使用tcp.option.sack进行过滤,可以看到这个SACK option只有一个片段,接收并没有进行确认,范围是18761~20101 再来将上面的例子 客户端收到seg4的时候,发送seg3的ACK 会产生一个SACK的option (361~500) ,Server收到这个ACK后,就知道seg3丢失了,但是seg4已经收到了但是并没有确认,所以就只会重传seg3 SACK的产生,RFC2018 SACK通常是由数据接收方产生,如果在connection建立的时候,SYN包中有SACK-Permitted 的选项为true,同时自身也支持SACK,那么可以在接收异常的时候,产生SACK option. 如果要发送,SACK中需要携带接收队列中所有没有被确认的数据段信息。 ...

Created 7076-11-07 · Updated 7076-11-07 · 1 min · 104 words · -

tcp window scaling, 滑动窗口

“tcp window scaling, 滑动窗口” TCP 滑动窗口 与窗口缩放因子(Window Scaling) 说道TCP滑动窗口协议,相信大家都很熟悉,但是说道 Window Scaling参数或许知道的和用过的人却不多,本文我们来谈谈Window Scaling的由来 TCP滑动窗口 众所周知, TCP是一种面向连接可靠消息传输协议;为了保证可靠,连接的两端保持对所有传输数据的严格跟踪,以便在需要时候进行重传或重新排序。另外为了跟踪已经发送了的数据在发送端有TCP发送缓存,在接受端有接受缓存,滑动窗口则是这个缓存的一部分,接收方接受数据后会把ack和当前滑动窗口可用空间告诉发送方,发送方则发送的数据不能超过接收方剩余窗口大小,如果接收方窗口内数据还没来得及由应用程序读取,窗口满了,则发送方会停止发送数据,直到接收方滑动窗口有空间。 假设我们有两个主机A和B,它们建立了一个TCP连接。在连接开始时 (握手时候协商) ,两个主机为传入数据分配32 KB的缓冲区空间,因此每个主机的初始窗口大小为32,768。 image.png 主机A需要向主机B发送数据,一开始则主机B告诉主机A在接受自己确认之前最多可以发送32,768字节的数据 (以最大段大小或MSS的间隔) 。假设MSS为1460字节,主机A可以在耗尽主机B的接收窗口之前发送22个段。 当确认收到主机A发送的数据时,主机B可以调整其窗口大小。例如,如果上层应用程序仅处理了一半缓冲区,则主机B会将其窗口大小降低到16 KB (这时候主机A在接受到B的确认前最多发送16KB数据到B) 。如果缓冲区仍然完全填满,主机B会将其窗口大小设置为零,表明它还不能接受更多数据,这时候主机A则停止发送数据。 image.png 在具有高带宽和极低延迟的LAN上,滑动窗口很少会满。但是,在高带宽,高延迟网络上,会出现一个有趣的现象: 在发送方接受到接收方发出确认之前,并不能最大化利用带宽。 例如,假设在通过专用10 Mbps路径连接的两台主机之间建立TCP连接,单向延迟为80ms。两个主机都约定最大窗口大小为65,535字节 (16位无符号整数的最大值) 。我们可以计算在一个时间点在一个方向上传输的潜在数据量,带宽*延迟: 10,000,000 bps除以每字节8位,乘以0.08秒等于100,000字节。 换句话说,如果主机A开始连续发送给主机B,它将在主机B接收到发送的第一个字节之前发送100,000个字节。但是由于约定的最大接收窗口只有65,535字节,所以主机A必须在发送65,535字节后停止发送,并等待来自主机B的确认。 (为简单起见,我们的示例计算不考虑TCP和低层报头。) 这种延迟浪费了潜在的吞吐量,不必要地增加了通过网络可靠传输数据所需的时间。创建TCP窗口缩放以解决此问题。 三、窗口缩放因子 窗口缩放在RFC 1072中引入并在RFC 1323中进行了改进。实际上,窗口缩放只是将16位窗口字段扩展为32位长度。解决方案是定义TCP选项以指定计数,通过该计数,TCP标头字段应按位移位以产生更大的值。 image.png 如上图 window size设置为5840字节,但是窗口缩放因子为7 (window scale) ,也就是这时候最大实际窗口为 5840*128。window scale为1将字段的二进制值向左移位一位,使其加倍。计数为2将值向左移动两位,使其翻倍。计数为7 (如上例所示) 将该值乘以128. image.png 窗口缩放选项 (window scaling) 可以在tcp握手时候在SYN分组中的连接期间仅发送一次。可以通过修改TCP标头中的窗口字段的值来动态调整窗口大小,但是在TCP连接的持续时间内,标度乘数保持静态。仅当两端都包含选项时,缩放才有效;如果只有连接的一端支持窗口缩放,则不会在任一方向上启用它。最大有效比例值为14 (RFC 1323的2.3节为有兴趣的人提供了一些背景信息) 。 回顾我们之前的示例,我们可以观察窗口缩放如何使我们能够更有效地进行网络传输 (最大化利用网络带宽) 。为了计算我们的理想窗口,我们将端到端延迟加倍以找到往返时间,并将其乘以可用带宽: 2 * 0.08秒* 10,000,000 bps / 8 = 200,000字节。为了支持这种大小的窗口,主机B可以将其窗口大小设置为3,125,其window scaling因子为6 (3,125左移6乘以200,000) 。幸运的是,这些计算都是由现代TCP / IP堆栈实现自动处理,无须应用程序层面干预。 ...

Created 7076-11-07 · Updated 7076-11-07 · 1 min · 90 words · -

tcp dump, wireshark

“tcp dump, wireshark” TCP segment of a reassembled PDU 关于"TCP segment of a reassembled PDU" 标签: TCP segment of a reaPDUreassembled PDU http://blog.csdn.net/dog250/article/details/51809566 版权声明: 本文为博主原创,无版权,未经博主允许可以随意转载,无需注明出处,随意修改或保持可作为原创! 为什么大家看到这个以后总是会往MSS,TSO上联系呢?也许第一个解释这个的人是个高手,而且以MSS/MTU/TSO的观点解释了这个问题,还有一种可能就是TSO等技术让人觉得太牛逼,毕竟是底层硬件机制吧,抓包机制又是作用于网卡层面的,所以很自然会觉得TSO会有关联。 事实上,这个跟TSO没有关系!跟MSS有一定的关系但不是全部因果关系,在阐述"TCP segment of a reassembled PDU"之前,先把TSO理清再说。当有人问题"这个包会不会被TSO分段"这类问题时,只要看该TCP数据包的长度,拿它跟MTU比较,如果数据长度更长,则就是TSO。 那么,“TCP segment of a reassembled PDU"究竟是什么呢?答案是,这要向上看,这个跟应用层有关,而与底层关系不大!我用Wireshark的抓包例子来解释这个问题。首先看一个抓包,我们以网络测试工具baidu为例,抓取一个访问其服务器https://14.215.177.38/的一个HTTPS连接的包: 网上很多人在解释这个"TCP segment of a reassembled PDU"的时候(基本都是转载),都说什么"ACK了同一笔数据就会是reassembled PDU”,“同一个GET请求的response"云云…但是很显然,上述我抓包的截图中,402到405号包都有ACK了同一个序列号,但是为什么只有一个"TCP segment of a reassembled PDU"呢??在没有标识reassembled PDU的数据包中,另外标识了TLSv1.2的协议原语。此时,我来做一个动作,按下"Ctrl-Shift-E"组合键,事实上就是点击"分析"菜单,进入"已启用的协议"界面: 反选SSL协议,不再识别SSL协议之后,我们再看402到405号数据包: 没有了"TCP segment of a reassembled PDU"这些,除了没有这些"修饰语"之外,其它的协议层面的数据完全和之前识别SSL协议的时候相符合。我们的结论是,关掉了对SSL协议的识别,就没有了reassembled PDU的修饰,这恰恰是因为SSL协议让Wireshark知道403号包是一个reassembled PDU!如果你不知道这是个SSL协议,你就无法判断出这是不是一个reassembled PDU! 是的,这就是原因。接下来,为什么SSL协议就能识别这是一个reassembled PDU呢?这就要看你对SSL协议是否理解了,起码我是懂的,在握手阶段,Server Hello和Server的Certificate是背靠背发送的,也就是说它们是连着发给Client的,一个Server Hello,外加一个证书,一起发给Client,接下来就是不那么根本但很显然的事情了,如果这些包的总和足够小或者链路的MTU足够大,能够一次性发送过去的话,那当然好,如果不能,很显然要拆成几个分段发送了,如果中间的那个分段不能被SSL协议的原语识别,那么就会被标识成reassembled PDU,这就是为什么404,405号数据包都是连续发送的,但是却未被识别为reassembled PDU,因为SSL协议知道它们是Certificate消息和Server Key Exchange消息。 现在明白了吗?我特意没有用HTTP协议去解释这个而是选择了用SSL协议,目的就是想让大家明白,并不是针对同一个GET请求的同一笔回应会被标识为reassembled PDU!而是完全靠着应用层协议原语来识别协议消息。如果你的Wireshark被配置成不识别任何协议,比如不识别HTTP协议,SSL协议,那也就不会出现reassembled PDU了,因为Wireshark不知道到底是不是!实际上Wireshark支持你去自定义你自己的协议插件,你可以试一下,自己开发一个简单的协议,就算你的TCP数据段总和没有超过一个MSS,比如你的socket每发100字节就sleep 10秒,并且TCP socket没有设置Nagle算法,那么虽然每个段只有100字节,远没有到一个MSS,也会有reassembled PDU的标识! ...

Created 6066-11-06 · Updated 6066-11-06 · 1 min · 195 words · -