Browsed by
Author: VOID001

Eudyptula Challenge 1 — 8 总结

Eudyptula Challenge 1 — 8 总结

TL;DR (PS: 昨天竟然在一个非计算机领域的朋友口中听到TLNR好神奇) 从开始做eudyptula-challenge已经有一个多月了,也从原来的连第一关都会卡关好久到现在第八关只用了不到四十分钟的时间就写好了(虽然第八关的coding要求很简单,主要是要练习git send-mail的使用方法)随着Challenge的进行,之前关卡学到的一些东西难免会遗忘,因此在继续进行之前,现将前面学到的知识进行总结。注意: 本文不是Eudyptula Challenge的攻略,Eudyptula Challenge明确禁止了对答案代码的公布和分享,个人也赞同这种做法,毕竟是Challenge,需要你自己研究,而不是直接上网就能搜到答案(尽管现在的确能搜到答案了,比如某章鱼猫(( Intro What is Eudyptula Challenge? 这里就引用官网的介绍了 The Eudyptula Challenge is a series of programming exercises for the Linux kernel, that start from a very basic “Hello world” kernel module, moving on up in complexity to getting patches accepted into the main Linux kernel source tree. How does it work? 官网上也给了相应的介绍,不过窝认为从一个例子来介绍更为形象: Eudyptula-Challenge的评判系统是由”A set of convoluted shell scripts that are slow to anger and impossible to debug.”(摘自官网)来进行的,也就是全部自动评测(不过有的时候它的只能程度让我猜想后面有人在操作*****(大雾 以一个Task为例, 当你注册成功Eudyptula Challenge之后,会收到一封说明邮件以及你的第一个任务,之后你所有的任务提交都将通过在第一个任务里给你分配的ID以plain-text mail的形式进行。 当你收到一个Task的时候,根据相应的知识完成任务要求的代码之后,你需要通过纯文本邮件客户端(如mutt)将proof运行结果的输出作为正文,将写好的代码作为附件(这里不能用gmail的plain-text模式,因为它会把邮件附件转为base64格式)通过客户端发送给[email protected],之后你会收到一封通知邮件,表示系统已经成功收到你的提交(有可能收不到,因为脚本也许会卡住,这时候你如果等了一天还没收到,那你可以再次发送一封,不要频繁重发,小企鹅会生气的(不要问我怎么知道的Orz)) 通知邮件的格式是这样的 blabla,…

Read More Read More

Gmail + Mutt 报错 no authenticators found 解决办法

Gmail + Mutt 报错 no authenticators found 解决办法

初步测试是配置文件错误导致的,这里要注意几个配置不要填错 下面是一个可用的配置 set imap_user = ‘[email protected]’ set imap_pass = ‘************’ set folder = ‘imaps://imap.gmail.com/’ set spoolfile = +INBOX set record = “+[Gmail]/Sent Mail” set postponed = “+[Gmail]/Drafts” set smtp_url = ‘smtps://[email protected]’ set smtp_pass = ‘***************’ 注意: smtp_url 要填写 smtps://[email protected] 而不是下面的其中一种 smtps://[email protected]@smtp.gmail.com:465 smtps://[email protected]:587 。。。 填写正确之后, 可以使用mutt进行邮件的发送  

IO 多路复用 — select 和 poll

IO 多路复用 — select 和 poll

本文为 高性能网络编程学习 系列文章的第2篇 下面我们使用select, poll, epoll来进行IO multiplexing 本文我们演示 select 和 poll做IO多路复用 select的用法查看man page就可以得到,这里只列出遇到的问题 nfds参数,表明要watch的最大fd的数字 举例说明,如果你要watch的文件描述符为24 — 31,那么你应该将nfds设置为32 为了防止SIGPIPE信号终止程序运行,要讲SIGPIPE信号忽略掉 代码如下 /************************************************************************* > File Name: server.c > Author: VOID_133 > Mail: ################### > Created Time: Wed 21 Dec 2016 04:03:25 PM HKT ************************************************************************/ #define _GNU_SOURCE #include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<fcntl.h> #include<pthread.h> #include<arpa/inet.h> #include<sys/socket.h> #include<sys/select.h> #include<string.h> #include<sys/errno.h> #define MAX_BUF_SIZE 1000 void usage(char *proc_name) { printf(“%s [port]\n”, proc_name); exit(1); } void setnonblock(int fd) { int old_flag = fcntl(fd, F_GETFL); fcntl(fd, F_SETFL, old_flag | O_NONBLOCK); return ; }…

Read More Read More

Linux Kernel Development Resources

Linux Kernel Development Resources

Here are some resources for digging into linux kernel development (Keep updating) Books Understanding Linux Kernel [ULK] Linux Kernel Development [LKD] Linux Driver Development [LDD] Linux Kernel Module Programming Guide [LKMPG] Linux in a Nutshell   Sites Eudyptula Challenges: A step-by-step challenge for kernel newbies to get familiar with kernel. it promise you can get into kernel development after finish all tasks http://eudyptula-challenge.org/ The Linux Documentation Project: Website provide useful resources for linux & kernel http://www.tldp.org/ The Linux Kernel Archives: Official Kernel…

Read More Read More

ULK Chapter2 总结

ULK Chapter2 总结

本章的知识结构如下 地址转换过程 –Logical Address–> [Segment Unit] –Linear Address–> [Paging Unit] –Physical Address–> 谈到内存地址,具体来讲有三种不同类型的地址,逻辑地址,线性地址,物理地址。 逻辑地址对应内存的分段 线性地址对应分页 物理地址对应到硬件芯片上的内存单元的地址 MMU通过Segment Unit与Paging Unit两个硬件电路将一个逻辑地址转为物理地址, 具体转换过程如上代码段所示 下面对整个转换过程进行概述 段选择符 15 0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +T+ R + + index +I+ P + + + + L + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ [0-1]RPL: 请求者特权级 [2]TI: Table Indicator, 指明是从GDT还是LDT中取出段描述符(Segment Descriptor) [3-15]index:用来指定从GDT中第index项取出Segment Descriptor 段描述符 对段描述符的解释参考 [不是科普向?] RE: 从零开始的操作系统开发 第二集 中相应内容即可 Logical Addr ===> Linear Addr 逻辑地址的高16位为段选择符(Segment Selector)其余32位(或者64位)为偏移量(Offset) 流程如下 检查TI确定是从GDT(TI=0)还是从LDT(TI =1)中选择段描述符 从Segment Selector的index字段计算出段描述符的地址,计算方法 index * 8 (一个Segment Descriptor大小为8) 并与gdtr/ldtr中的内容相加得到Segment Descriptor 把逻辑地址的offset字段与Segment Descriptor中的Base字段相加,得到Linear Address   而Linux中的分段只是一个兼容性考虑,分段和分页的作用是重复的,分页能以更精细的粒度对内存进行管理,因而在Linux中分页是主要的手段,Linux分段中的用户代码段,数据段,内核代码段,数据段,都是以Base = 0…

Read More Read More

将内核编译到自定义的目录下

将内核编译到自定义的目录下

参考wiki: https://wiki.archlinux.org/index.php/Kernels/Traditional_compilation 使用ArchLinux作为构建Linux的环境 方法如下 假设我们的customized directory为kernel-build 我们必须在kernel-tree目录结构下对内核进行编译,假设kernel-tree目录名为linux-kernel 下面是具体的操作: make menuconfig # Change the local version in General Settings make -j8 make modules -j8 sudo make modules_install 在 make menuconfig 的时候,最好对内核版本进行修改,使之不会在make modules_install的时候覆盖掉现有内核的modules 修改途径为General Setup里的Local Version项 这样执行之后,应该在arch/ARCH/boot/下面存在bzImage内核镜像,并且modules应该被安装在了/lib/modules/<linux-version>-<localversion> 下 下一步操作, 修改linux.preset文件,并创建initrd文件 ## Change to kernel-build directory cp ../arch/<arch>/boot/bzImage [image-name] cp /etc/mkinitcpio.d/linux.preset . 修改linux.preset文件, 修改完毕后的内容类似下面 # mkinitcpio preset file for the ‘linux’ package ALL_config=”/etc/mkinitcpio.conf” ALL_kver=”/home/void001/linux-kernel/kernel-build/vmlinuz” PRESETS=(‘default’ ‘fallback’) #default_config=”/etc/mkinitcpio.conf” default_image=”/home/void001/linux-kernel/kernel-build/initramfs-linux.img” #default_options=”” #fallback_config=”/etc/mkinitcpio.conf” fallback_image=”/home/void001/linux-kernel/kernel-build/initramfs-linux-fallback.img” fallback_options=”-S autodetect” 我们需要修改ALL_kver, default_image, fallback_image三个选项,使其将image保存到指定的目录下 然后使用 mkinitcpio -p ./linux.preset 创建initrd, initrd-fallback,目前kernel-build目录应该有如下文件: ╰─➤ ls…

Read More Read More

多进程&多线程 echo server实现

多进程&多线程 echo server实现

本文为 高性能网络编程学习 系列文章的第1篇   多进程版本 本文承接上文的单进程 echo server 建立一个多进程的echo server。代码的改动不多,下面贴一下完整的代码 /************************************************************************* > File Name: server.c > Author: VOID_133 > A very simple tcp echo server illustrate use of socket > Ver1 only accept single connection, no multiple connection allowed > Mail: ################### > Created Time: Wed 21 Dec 2016 04:03:25 PM HKT ************************************************************************/ #include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<arpa/inet.h> #include<sys/socket.h> #include<string.h> #include<sys/errno.h> #define MAX_BUF_SIZE 1000 void usage(char *proc_name) { printf(“%s [port]\n”, proc_name); exit(1); } int main(int argc, char** argv) { int sockfd, clifd; //sockaddr_in…

Read More Read More

Linux 下C语言简单echo server的实现

Linux 下C语言简单echo server的实现

本文为 高性能网络编程学习 系列文章的第0篇 本文目的为讲述简单的echo server的实现, echo server的含义如字面意思, 客户端发送什么数据,服务器就返回什么数据作为响应,本系列文章的目的不在于实现复杂的服务器端业务逻辑,在于学习如何开发出高性能的网络通信程序,因而所有的代码均为echo server的实现 Linux下用C进行网络通信的话, 需要使用socket, 即Linux socket interface, socket是一种IPC(Inter Process Communication进程间交互)的方式,同时socket还可以允许跨host,即在不同的主机上的进程之间进行通信,在Linux上,所有的IO操作都是通过对文件的写入读出实现的,socket也作为一种文件存在,可以通过read, write进行IO 客户端我们采用的是一个benchmark程序,即1000个client,每一个client发送1000个请求,客户端为了简洁和快速编写,使用golang开发,之后所有的server都使用这个benchmark进行测试,代码如下 package main import ( “flag” “fmt” “io” “net” “sync” “time” ) var wg sync.WaitGroup var okCliCnt = 0 var okIPCCnt = 0 var mu sync.Mutex var ( ConnType = “tcp” ConnAddr = “” ClientCnt = 1000 RequestCnt = 1000 ) func init() { flag.StringVar(&ConnAddr, “S”, “127.0.0.1:5210”, “specify the address to connect”) flag.IntVar(&ClientCnt, “cno”, 1000, “number of clients to request”) flag.IntVar(&RequestCnt, “rno”, 1000, “number…

Read More Read More

My Yearly Goals

My Yearly Goals

—–BEGIN PGP MESSAGE—– Version: GnuPG v2 hQIOA2jnx9T3JM9SEAf/VSB3nCEOzyJEf9RRSI76xw4kv9VS7IJmeg80fNAcViYQ sn2PaRSYMC1X0nqOzpqOzYW5LIArSEehrr/Z085gOjNi/2rkDwSD3WGGXgUdSZRZ 10gRLoRE/CZw212CNZi0AV0GT7Zw5jizpJt4kh5Zn/RnrdxHCtSMaTJpIbOYhmca FQJfcLRp5unSUooOY1PREESA4tpaUy9kz4dgttnCPnq8DLeshkD5xMAloAFR13li TBeG/tqHKjNUZT5oLUSLxs9EXnG9LTLB+lJ4C0sdY6KW7Ad7SMzymTWSnjeYHxp+ 4FDhqGhrJwrBC3Gh63YLTLXALc2NBQ5s32trpSPV5wgAj2LKcSiiBxXh8LgjT+Em mGYIgs6drCwowBi/A6RDxA7kdnMVT9cSk6XjMIQjb0mG3JGnNYWEjRHx+5P4ZlsM tfv153RAbRaGCOSoJ8pm2NOmaGs7wgTv9yKRUGIFzROWsPOTx+Q1UGnurIFFa9LG lU42EXsIa7lzxsCgNx8vXqonTwRPinspfRUea/URgbCkIpnyVSIkFXujY+HAdRRo V8WRxq6Rm78YNMigt3lim7NLmYIk8K3CAz92+q5oRolIgCbqwN6dGHpJSDLBoKX8 7nFQQsrFOh5lSv/ZO0upjuye0JJTwU1yzcYRH7B0r2aMzxxMWu0ZB6kilq/RaDp9 nNLpAVHBo6oXX5j8+2k22F2vZVSTUl1SJgKahHOzTUQTK+rIESX5XTwJctJ0Eb/c jjaHV3GDZSGZBK6Ib+Ez+4SIqXZg26d5bnXbBS/iHL2baErZE4sFzEf8JsYbq3ZO 5Xk3eBURiLwwrl3ftu2O7/Mv6AUFyYSaWJWanYPMGm0I3NDYmaMWWIRPRD6wE32R bklG/xvktnLkp75nk0FKqVPXlci0aeAzxVYvsvd9CnkcDxeEi3WdLRlyhE5xsLRv CL4KpQzw7d6Rg2TZ0kn7gHYmS0HJHLDf7VrUndLcDMjiF/wrBfxH/ZsfIKxmfzMd LgIWYefwVWndpejO5FMlzl+7NFFy+Uc036iWUXcfScbyChujdYRGyyJy8B9zJmhf pBescXTzjpCp7yySmz11FpBUNpfA6Bg44T8t2ERlNMae4ZuL+U25y8E0QgiUJTHe guDWpdhxLESXRi7TF9D0k0DWWguUAsJlioQJZDRMZze+pLOwMa0bdgqbJFMexQQk IKs9rzobcM1a0aeIEyytCiVdDiEmcc/PEwJ7yDaZ7aQvknP92p9xDZl0flzlLbbp 6bjxHySKV13QKoE1ymmsZjqLqqLlHLDz3lOs2gb0ZEG64N/8grRimGCOhNj+U7pH rvuBR3lJMFyjI8MKmEPViupXXoYr8tDQC+f11CccT5IS65gqJ5pwNDBRU4BMkg6A 7Z7wnNvZzt5aNKW+tYYqknR//qTpEYgFCxoEp24n =CB7d —–END PGP MESSAGE—–  

[DFS #0] HDFS论文解读

[DFS #0] HDFS论文解读

参考论文: The Hadoop Distributed File System 分布式文件系统HDFS作为HBase的下层服务,以及众多存储服务的支持项目,已经被广泛使用,下面通过解读上述论文来记录并介绍一下HDFS的架构,以及功能,还有设计 整体架构 Overview 如图所示     每一个HDFS集群由一个NameNode,多个DataNode,以及BackupNode, CheckpointNode组成,上图中的三角形为使用HDFS的客户端,客户端和DataNode之间的线表示客户端到DataNode的物理距离,对于这个架构,有下面几点要说的 一个集群的NameNode只有一个,客户端想要使用这个HDFS的时候,一定是先和NameNode进行交流,获得需要的DataNode信息之后,才能和DataNode进行通信 因为NameNode只有一个,所以NameNode如果出现单点故障可就不好玩惹,而且对于存储这种要求数据一致性很高的系统,也不能容忍NameNode出故障系统就瘫痪这种情况,因而使用CheckpointNode和BackupNode对NameNode进行备份,他们的区别和备份方式下文会详细说 NameNode不会主动去和DataNode通信,他们之间的通信是这样的: DataNode每隔一定时间发送heartbeat到NameNode(默认3s)(通知NameNode他还活着可以干活=w=(划掉 ,然后NameNode在这个时候会将要发送到DataNode的指令通过Response的形式发送到DataNode Client对数据的操作精简来看,无非是读写两种,当Client想要读取HDFS的数据的时候,首先Client先去询问NameNode,哪些DataNode有他要的数据,并且选择距离他最近的DataNode,然后Client直接连接距离最近的DataNode并获取数据 e.g: 如上图的ClientA想要获取一个数据,且数据在DataNode A B C内都有存放,那么ClientA首先要和NameNode进行通信,获得DataNode列表(ordered by distance to the client)然后选择距离它最近的DataNode B进行通信获取数据 当Client想要向一个文件写入数据的时候(无论文件存不存在),其他的Client会无法对此文件进行写入操作(以此来保证文件不会因为同时写而corrupt data)写入完毕之后,会将Block进行Replica复制到不同的DataNode上(默认为复制3份),具体会在下面介绍   模块 & 术语 NameNode HDFS Namespace ,是存储着所有DataNode以及每一个DataNode上的文件的元信息的一个目录结构,NameNode通过inode的方式来表示每一个文件和文件夹。Namespace 就可以理解为Linux的目录树的inode list,每一个inode指向一个datablock,datablock存在datanode上 HDFS将整个Namespace放在RAM内,完整的文件系统信息(包含inode信息,以及每一个inode对应的Datablock list 元信息)称为Image, Image持久存储在NameNode本地存储里,称为一个Checkpoint, NameNode同时维护了数据操作的日志journal DataNode 显然,这就是数据真正存放的地方,每一个Datablock由两个文件组成,该Block的数据,和该Block的[checksum,创建时间]信息组成的元数据 如下图 一个占3个Block的文件存放在DataNode里的情况简图,该文件有三个block,每一个block的信息含有Data & MetaData,三个Block组成了整个文件file1, 然后在NameNode的某一个inode存储着信息对应着文件名file1,block数3,物理位置在该DataNode上 DataNode的Startup   当DataNode Startup时,会和NameNode进行handshake,进行namespaceID(每一个HDFS都有一个唯一的NamespaceID,在创建HDFS的时候就确定了)&version的认证,二者必须均与NameNode完全一致,如果不一致的话,该DataNode就会停止工作。保证了不会因为错误的NameNode或者软件版本不兼容而导致数据出问题, 如果这个DataNode没有保存任何Namespace信息,说明这是一个新的DataNode,没有任何Block数据,因而允许加入此HDFS cluster。 当DataNode握手成功之后,会register自己到该NameNode,如果为第一次加入该NameNode,则会被NameNode分配一个唯一的StorageID,并且永远不会改变,DataNode会将此ID持久存在自己的storage中,这个StorageID保证了就算IP变动或者端口变动,NameNode仍然可以识别该DataNode的身份 DataNode与NameNode的通信 Block Report: Block Report是DataNode用于通知NameNode自己所持有的Block的信息(如blockid,block大小,generation stamp)的一种数据,因为这个数据是会随时改变的,所以需要定期发送Block Report给NameNode,使得NameNode能得到整个Block分布的信息。当DataNode注册到NameNode时,会立即发送一个Block Report,之后会每隔一段时间(1h)发送一次BlockReport HeartBeat:  DataNode通过定期的心跳与NameNode进行通信,使NameNode确认DataNode存活,并且同时carry其他信息,如存储可用量,目前正在传输的数据量等信息,用于NameNode进行负载均衡。 NameNode则在收到DataNode心跳,对DataNode进行Response的时候进行通信,可以发送的指令有: 将自己持有的数据块复制到其他DataNode 移除该DataNode上的数据块 重新注册、或者停止该DataNode 使DataNode立即发送一个Block Report Block Scanner 每一个DataNode都有一个BlockScanner,周期性地对Block的完整性进行认证 当Block…

Read More Read More