python 的 __name__

这篇文章The Reason Behind if name == ‘main’ in Python 是出自medium 作者 Jordan Williams __name__ 本文通过两个例子讲解了`if` name `== "`main":,在多文件项目中的作用,主要从两个 current_script.py import other_script print('current_script __name__ is set to {} '.format(__name__)) other_script.py print('other_script __name__ is set to {} '.format(__name__)) 输出: # python3 current_script.py other_script __name__ is set to other_script current_script __name__ is set to __main__ # python3 other_script.py other_script __name__ is set to __main__ name代表当前正在运行的模块/文件名称,直接运行的模块/文件该值为main, 对于导入模块,其值为模块名 java中的main方法 Java中每个类可以main方法如下 public class Application { public static void main(String[] args) { //construct objects here } } main方法是一个静态方法,常用对类进行单元测试。 ...

2021-02-08 · 5 min · 901 words

可逆计算 reversible computing

本周在学习Trie数据结构的时候,看到了他的发明者 Edward Fredkin,他也在研究reversible computing 弗雷德金(Fredkin)对计算,硬件和软件一直很感兴趣。 在1960年代初期,他在BBN编写了第一台PDP-1汇编程序。 他是trie数据结构,Fredkin gate和Billiard-Ball计算机模型的可逆计算的发明者。 他的主要贡献包括他在可逆计算和元胞自动机方面的工作。 他还研究领域还包括计算机视觉,人工智能研究和计算机象棋。 ...

2021-01-17 · 1 min · 70 words

Ext4 布局及inode,block信息统计

inode定义 node The inode (index node) is a data structure in a Unix-style file system that describes a file-system object such as a file or a directory. Each inode stores the attributes and disk block locations of the object's data. File-system object attributes may include metadata (times of last change,[2] access, modification), as well as owner and permission data.[3] from inode wiki inode数据结构用于描述文件系统中的文件、目录等, 每一个inode保存了文件系统系统对象memdata如修改时间,访问时间以及权限等。Dennis Ritchie对于inode中i可能代表index,而被访问的文件列表,被组织为存放存放在磁盘上的一维数组。 block ext4文件系统以block为单位分配存储空间。 环境准备 Linux Distributions: CentOS 7 通过fdisk划出一个10M分区, 格式化为ext4 ...

2020-09-16 · 10 min · 1951 words

close-on-exec

简介 Donald E. Porter 教授的 CSE 506: Operating Systems 教材 VFS 部分中提到Linux文件操作使用的一个标识 CLOSE_ON_EXEC – a bit that prevents file inheritance if a new binary is exec’ed (set by open or fcntl) 这个标识位支持exec执行前关闭其从父进程继承来的文件描述符 使用 设置方法: 通过fcntl 设置FD_CLOEXEC int flags = fcntl(connfd, F_GETFD); flags |= FD_CLOEXEC; fcntl(connfd, F_SETFD, flags); 通过O_CLOEXEC open(path, O_CLOEXEC | flags) socket(DOMAIN, SOCK_CLOEXEC | type, PROTOCOL) accept4(int sockfd, struct sockaddr *addr, \ socklen_t *addrlen, SOCK_CLOEXEC | flags); fopen(path, "re") 可以在以下这种模式下使用, fork后还是dup了父进程的文件描述符,exec后将自动关闭. pid_t pid; pid = fork(); if (pid == 0) { exec(...) }; 验证 代码 server.c ...

2020-09-09 · 3 min · 526 words

MezzFS文件系统

这篇文章MezzFS — Mounting object storage in Netflix’s media processing platfor 是出自medium Netflix Technology Blog,作者 Barak Alon MezzFS: Mezzanine文件系统的缩写, 是Netflix使用Python开发的一个工具,可通过FUSE将云对象作为本地文件挂载。 FUSE支持用户态空间的文件系统, 文件操作命令通过VFS->FUSE->glibc->libfuse->用户自定义文件系统实现, 从而可以在用户态重新定义文件操作. Netflix处理视频编码主要涉及以下几个方面问题: 针对不同编码器分辨率进行多次编码,如果编码技术更新调整 可能需要全部重新编码 文件拆分并加密为单独的块,并将这些块存储在Amazon S3中。另外需要处理内容安全性,审核,灾难恢复等 视频编码器都是处理本地文件系统上的文件,不会去调用API去处理云上文件。视频文件非常大,需要避免为了处理一小块而下载整个视频文件 MezzFS的一些特点; Stream objects: 流对象不要外设存储 Assemble and decrypt parts: MezzFS知道如何组装和解密 Mount multiple objects: 挂载多个对象 Disk Caching: 支持本地磁盘缓冲 Mount ranges of objects: 可以将云对象指定范围对象挂载到本地 Regional caching: 一个区域的缓冲信息可以被另一个区域使用 关键特征replay; 支持配置MezzFS为记录replay文件。 该文件包括: 元数据, 文件操作, 缓存的内容, 统计信息。有这些信息可以实现可视化的功能, 可以用来调试错误,进行性能分析. 关键特征Adaptive Buffer; 由于使用FUSE系统, 内核将分块读入, 这意味这1G 的挂载文件, MezzFS可能要针对64KB块进行16384次读取。 因此最好可以预先读取一大块进行缓存。但是由于涉及离散和连续数据, 因此出现了Adaptive Buffer 具体公式数据来源于最近的读取的信息. ...

2020-09-02 · 1 min · 136 words

Tiny Core Linux 安装配置

简介 Tiny Core Linux是一个mini Linux操作系统,基于 BusyBox和FLTK提供基本功能。 其发行版本在11M-16M 官网上也提供Plus版本也只有106M。它很精致。 安装 操作系统安装 镜像下载 下载页面 http://tinycorelinux.net/downloads.html 我下载了两个版本镜像: x86版本: TinyCore-11.1.iso x86_64位版本:TinyCorePure64-11.1.iso 环境准备 我们使用的vmware 首先新建一个linux虚拟机, 我选的版本是其他Linux5.x或更高版本内核64位, 并添加了两块SATA的硬盘(默认的SCSI硬盘识别似乎有些问题) 开始安装 安装过程主要下面三个步骤 : 光盘启动操作系统; 配置网络 下载安装脚本安装; 1 . 选择镜像: 光盘镜像选择 x86版本:TinyCore-11.1.iso (不影响安装) 2 . 启动系统: 启动后会出现四个选项, 选择第三项 Boot TinyCore Boot TinyCore (on slow devices, waitusb=5) Boot Core (command line only) Boot Core (command line only on slow devices, waitusb=5) 可以看到系统后进入命令行窗口,但是这种模式下进行操作重启将全部丢失。要保留我们相关配置,需要挂载硬盘。 3 . 配置网络: 配置网卡地址路由及域名服务器。 sudo ifconfig eth0 192.168.xxx.202 netmask 255.255.255.0 sudo route add default gw 192.168.xxx.1 dev eth0 sudo echo nameserver 192.168.xxx.1 >> /etc/resolv.conf 4 . 下载安装脚本: 会联机下载相关安装包 ...

2020-09-01 · 4 min · 738 words

伙伴系统分配物理页后如何转换成为虚拟地址

概述 极客时间 26 | 内核态内存映射:如何找到正确的会议室? 一道课后问题 伙伴内存分配技术是一种内存分配算法,它将内存划分为多个分区,以尝试尽可能适当地满足内存请求。 该系统利用将内存分成两半来尝试提供最佳匹配。 当Linux内核态和用户态进程申请内存时, 分配的物理页面需要转化为虚拟地址供上层访问。 下面通过内核代码看下Linux内核态的kmalloc和vmalloc和用户态的mmap和malloc地址转换的时机。 内核态-kmalloc kmalloc 伙伴系统地址转换时机: __kmalloc申请空间小于2个页面大小时,申请发起后通过SLAB分配器进行分配, 依次检查 per cpu freelist per cpu partial per node partial链表是否有满足的的缓冲,没有就通过伙伴系统重新申请, 在申请的时候完成后page_address进行地址转换。 过程如下: 申请空间大于两个页面大小内存直接通过伙伴系统申请,小于这个值使用SLUB分配器(当然最终还是从伙伴系统申请内存) /include/linux/slab.h static __always_inline void *kmalloc(size_t size, gfp_t flags) { ... if (size > KMALLOC_MAX_CACHE_SIZE) return kmalloc_large(size, flags); ... return __kmalloc(size, flags); } ... #define KMALLOC_MAX_CACHE_SIZE (1UL << KMALLOC_SHIFT_HIGH) /* * SLUB directly allocates requests fitting in to an order-1 page * (PAGE_SIZE*2). Larger requests are passed to the page allocator. */ #define KMALLOC_SHIFT_HIGH (PAGE_SHIFT + 1) 通过slab_alloc进入具体的内存申请流程. void *__kmalloc(size_t size, gfp_t flags) { struct kmem_cache *s; void *ret; if (unlikely(size > KMALLOC_MAX_CACHE_SIZE)) return kmalloc_large(size, flags); s = kmalloc_slab(size, flags); if (unlikely(ZERO_OR_NULL_PTR(s))) return s; ret = slab_alloc(s, flags, _RET_IP_); trace_kmalloc(_RET_IP_, ret, size, s->size, flags); ret = kasan_kmalloc(s, ret, size, flags); return ret; } 之后就从 <1> . per cpu freelist查找 static __always_inline void *slab_alloc_node(struct kmem_cache *s, gfp_t gfpflags, int node, unsigned long addr) { ... redo: ... do { tid = this_cpu_read(s->cpu_slab->tid); c = raw_cpu_ptr(s->cpu_slab); } while (IS_ENABLED(CONFIG_PREEMPTION) && unlikely(tid != READ_ONCE(c->tid))); ... object = c->freelist; page = c->page; ... if (unlikely(!object || !node_match(page, node))) { object = __slab_alloc(s, gfpflags, node, addr, c); stat(s, ALLOC_SLOWPATH); } else { ... } ... return object; } 然后从 <2> . per cpu partial查找 static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, unsigned long addr, struct kmem_cache_cpu *c) { ... new_slab: if (slub_percpu_partial(c)) { page = c->page = slub_percpu_partial(c); slub_set_percpu_partial(c, page); ... } ... } 然后从 <3> . per node partial查找 static inline void *new_slab_objects(struct kmem_cache *s, gfp_t flags, int node, struct kmem_cache_cpu **pc) { void *freelist; struct kmem_cache_cpu *c = *pc; struct page *page; WARN_ON_ONCE(s->ctor && (flags & __GFP_ZERO)); freelist = get_partial(s, flags, node, c); ... } /* * Get a partial page, lock it and return it. */ static void *get_partial(struct kmem_cache *s, gfp_t flags, int node, struct kmem_cache_cpu *c) { void *object; int searchnode = node; if (node == NUMA_NO_NODE) searchnode = numa_mem_id(); object = get_partial_node(s, get_node(s, searchnode), c, flags); if (object || node != NUMA_NO_NODE) return object; return get_any_partial(s, flags, c); } 上面的经历了本地缓存池分配per cpu freelist,per cpu partial, 其他节点缓冲 per node partial, 逐一查找,但是一开始肯定要从伙伴系统分配的,下面看下伙伴系统分配,关注地址转换部分, 可以看到在申请slab时,通过page_address进行了物理地址到虚拟地址转换。 > 如果支持CONFIG_SLAB_FREELIST_RANDOM打乱了free_list中object顺序,减少堆栈溢出可预测性, 并有利于改善缓冲冲突 (Randomize free memory),对应 shuffle_freelist函数里也可看到相关地址映射的操作。 static inline void *new_slab_objects(struct kmem_cache *s, gfp_t flags, int node, struct kmem_cache_cpu **pc) { ... page = new_slab(s, flags, node); if (page) { ... } return freelist; } static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node) { ... return allocate_slab(s, flags & (GFP_RECLAIM_MASK | GFP_CONSTRAINT_MASK), node); } static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) { page = alloc_slab_page(s, alloc_gfp, node, oo); start = page_address(page); shuffle = shuffle_freelist(s, page); if (!shuffle) { ... page->freelist = start; ... } ... return page; } static bool shuffle_freelist(struct kmem_cache *s, struct page *page) { ... start = fixup_red_left(s, page_address(page)); ... cur = next_freelist_entry(s, page, &pos, start, page_limit, freelist_count); cur = setup_object(s, page, cur); page->freelist = cur; ... return true; } __kmalloc申请空间大于2个页面大小时,申请发起后, 直接就通过伙伴系统申请页了, 这里看到了熟悉的order ...

2020-08-11 · 12 min · 2346 words

mmap相关API

概述 mmap()调用进程的虚拟进程空间中一段新的内存映射。 #include <sys/mman.h> void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); mmap(2) — Linux manual page 用途 变更的可见性 映射类型 文件 匿名 私有 根据文件内容初始化内存 内存分配 共享 内存映射I/O,进程间共享内存(IPC) 进程间共享内存(IPC) 文件映射 创建步骤 //1. 打开使用的文件 fd = open(argv[1], O_RDONLY); //2.获取文件信息,文件大小 fstat(fd, &sb); //3. 生成内存映射 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 相关议题 文件权限与内存保护位prot fd = open(argv[1], O_RDONLY); ... addr = mmap(NULL, sb.st_size, PROT_WRITE, MAP_SHARED, fd, 0); mmap抛出 errno=13 Permission denied错误 边界情况 增加一个异常捕获的处理 void signal_handler(int no){ switch(no){ case 11: printf("get SIGSEGV\n"); break; case 7: printf("get SIGBUS\n"); break; default: printf("get %d\n", no); break; } exit(-1); } # ls -l dax.file -rw-r--r--. 1 root root 7 Jul 18 17:51 dax.file SIGSEGV 访问超过mmap映射范围 ...

2020-07-22 · 4 min · 732 words

Linux slob/slab/slub

概述 Linux初始化通过bootmem/memblock引导内存分配进行内存管理,支持buddy system完成相关初始化后,将物理内存分配的功能转交给buddy system,buddy system是以page为单位分配方式。 对于内核要经常创建的对象, 如task_struct,fs_struct, mm_struct 通常会放到高速缓存中,保留基本结构,从而可以重复使用他们, 这里需要用到slab分配器。 slab分配器 通过 buddy system 申请空闲页 将申请到页处理为更小的分配单元,为其他子系统提供缓冲区存放内核对象 缓存经常使用的对象,释放后保存器初始状态,再次分配对象速度会很快 充分利用硬件高速缓存 历史发展 1991 Initial K&R allocator 1996 SLAB allocator 2003 SLOB allocator 2004 NUMA SLAB 2007 SLUB allocator 2008 SLOB mulitlist 2011 SLUB fastpath rework 2013 Common slab code 2014 SLUBification of SLAB … 常用的分配器 SLOB: K&R allocator (1991-1999) SLAB: Solaris type allocator (1999-2008) SLUB: Unqueued allocator (2008-today SLOB 简单的空闲对象列表管理 遍历列表查找合适的空间,没有的话申请向伙伴系统申请page增加堆栈大小. 碎片化严重 优化: 按照不同大小多个链表,减少碎片。 原理图 ...

2020-07-11 · 6 min · 1207 words

The XY Problem

The XY Problem 原文链接 The XY Problem 什么是XY问题 XY问题是在询问您尝试的解决方案,而不是您的实际问题。 这导致提问者和回答者大量的时间和精力浪费。 用户想做X。 用户不知道如何做X,但认为只要能够做Y,他们就可以找到解决方案。 用户也不知道该怎么做Y。 用户请求有关Y的帮助。 其他人试图用Y帮助用户,但感到困惑,因为Y似乎是一个很想解决的问题。 经过大量的交互和浪费的时间之后,终于可以清楚地知道用户确实需要X的帮助,而Y甚至不是X的合适解决方案。 当人们陷于他们所认为的相关解决方案无法及进行,停下来并完整地解释问题时,就会出现问题。 如何解决 始终包括有关更广泛情况的信息以及任何尝试的解决方案。 如果有人要求提供更多信息,请提供详细信息。 如果您已经排除了其他解决方案,请分享您排除它们的原因。 这将提供有关您的问题的更多信息。 记住,如果您的诊断理论是正确的,您就不会寻求帮助了 例子 Example 1 n00b实际上并不需要文件名中的最后3个字符,而是想要文件扩展名,那么为什么要问最后3个字符呢? <n00b>如何回显文件名中的最后三个字符? <feline>如果它们在变量中:echo $ {foo:-3} <feline>为什么要输入3个字符? 你真正想要的是什么? <feline>您是否需要扩展名? <n00b>是。 <feline>不能保证每个文件名都具有三个字母的扩展名, <feline>所以盲目地抓三个字符并不能解决问题。 <feline> echo $ {foo ## *。} Example 2 如果Angela刚开始解释说她想防止其他人检测到她的操作系统,那本来可以是简短得多且更有成果的讨论。 Angela:'nmap -O -A 127.0.0.1'返回以'OS:'开头的某些行。 怎么改变呢? Obama:在nmap的源代码中查找,找到如何找到Linux部分,然后重写TCP / IP堆栈以使nmap无法检测到它。 Angela:是的,但是我完全不了解linux系统api。 Obama:好吧,nmap基于TCP / IP堆栈的工作方式,除了重写该堆栈的适当部分外,没有真正的方法。 Angela:我真的需要避免这些信息。 iptables可以完成这项工作吗? Obama:好吧,不要使用操作系统检测或版本扫描 Angela:我想防止其他人知道我的操作系统类型

2020-06-21 · 1 min · 62 words