博文

目前显示的是标签为“技术”的博文

linux 页表

简单来说,讨论linux页表就是讨论linux进程的的页表:linux页表的创建与更新都包含于进程的创建与更新中。当前的linux内核采用的是写时复制方法,在创建一个linux进程时,完全复制父进程的页表,并且将父子进程的页表均置为写保护(即写地址的时候会产生缺页异常等)。那么父子进程谁向地址空间写数据时,产生缺页异常,分配新的页,并将两个页均置为可写,按照这种方式父子进程的地址空间渐渐变得不同(也即页表变得不同)。 按照上面的分析, 只需要讨论第一个进程页表初始化,进程创建时页表的拷贝,以及缺页异常时页表的更新即可。 1.init_task进程页表的初始化 init_task的地址空间是init_mm, init_mm在内核初始化的时候就赋值给了current->active_mm. init_mm的初始化页表是swapper_pg_dir,在mips架构中swapper_pg_dir初始化在函数pagetable_init中,初始化关系是 swapper_pg_dir -> invalide_pmd_table -> invalide_pte_table 或 swapper_pg_dir -> invalide_pte_table. 即在init_mm中,页表指向的全部是invalide_pte_table。 2.创建进程时页表的拷贝 进程创建一般调用的是do_fork函数,按照如下调用关系: do_fork->copy_process->copy_mm->dup_mm->dup_mmap->copy_page_range 找到copy_page_range函数,这个函数便是负责页表的拷贝,函数核心代码如下: 874 do { 875 next = pgd_addr_end(addr, end); 876 if (pgd_none_or_clear_bad(src_pgd)) 877 continue; 878 if (unlikely(copy_pud_range(dst_mm, src_mm, dst_pgd, src_pgd, 879 vma, addr, next))) { 880 ret = -ENOMEM; 881 br...

armlink 用法详解

在介绍armlink 的使用方法之前,先介绍要涉及到的一些术语。 映像文件(image):是指一个可执行文件,在执行的时候被加载到处理器中。 一个映像文件有多个线程。它是ELF(Executable and linking format)格式的。 段(Section):描述映像文件的代码或数据块。 RO:是Read-only 的简写形式。 RW:是Read-write.的简写形式。 ZI:是Zero-initialized 的简写形式。 输入段(input section):它包含着代码,初始化数据或描述了在应用程序运行 之前必须要初始化为0 的一段内存。 输出段(output section):它包含了一系列具有相同的RO,RW 或ZI 属性的 输入段。 域(Regions):在一个映像文件中,一个域包含了1 至3 个输出段。多个域组 织在一起,就构成了最终的映像文件。 Read Only Position Independent(ROPI):它是指一个段,在这个段中代码和只 读数据的地址在运行时候可以改变。 Read Write Position Independent(RWPI):它是指一个段,在该段中的可读/写 的数据地址在运行期间可以改变。 加载时地址:是指映像文件位于存储器(在该映像文件没有运行时)中的地 址。 运行时地址:是指映像文件在运行时的地址。 下面介绍一下armlink 命令的语法 完整的连接器命令语法如下: armlink [-help] [-vsn] [-partial] [-output file] [-elf] [-reloc][-ro-base address] [-ropi] [-rw-base address] [-rwpi] [-split] [-scatter file][-debug|-nodebug][-remove?RO/RW/ZI/DBG]|-noremove] [-entry location ] [-keep section-id] [-first section-id] [-last section-id] [-libpath pathlist] [-scanlib|-noscanlib] [-loc...

libvirt event 处理

一、初始化时的函数栈 virNetSocketAddIOCallback()(当然这是以virNetSocket类型的数据结构为例,所谓virNetSocket类型的数据结构是指这类数据结构都是以virNetSocket开头,表现为virNetSocket*形式,例如:virNetSocketPtr) virEventAddHandle() addHandleImpl() <==================> virEventPollAddHandle()(通过virEventRegisterImpl函数来实现对应) 在virEventPollAddHandle()函数中将数据填充到eventLoop.handles[]数组中,下面我们就关注怎么用eventLoop.handles[]数组的。 备注: virNetServerNew 用来建立virNetServerPtr数据结构的同时(这数据结构用来描述remote模式下的server),还调用virEventRegisterDefaultImpl()函数,virEventRegisterDefaultImpl()函数调用virEventRegisterImpl函数来填充addHandleImpl()。 二、event的处理 main() (daemon/libvirtd.c) virNetServerRun() virEventRunDefaultImpl() (在一个while循环中,循环的判断条件是 !srv->quit,srv->quit默认是0,表示server一直在运行,当收到一些信号是该变量才会变成1,表示server退出了,循环也跟着退出) virEventPollRunOnce() 在virEventPollRunOnce()函数中,调用poll函数,来循环struct pollfd* fds(表示fd的数组),fds的初始化函数是virEventPollMakePollFDs(),在该函数中用eventLoop.handles[]数组来初始化fds。 当poll监视的fds数组中有事件发生,poll退出,返回值>0,virEventPollRunOnce()继续,其接着调用virEventPo...

qemu 迁移使用方法

迁移是qemu中支持的,libvirt只是封装好命令并传递给qemu的监控模块。 1、qemu中使用方法: 在server端,在启动qemu的命令行中加入-incoming tcp:0:4444(4444为端口)参数,启动后可以应用netstat -apn 命令查看,4444端口是不是在监听。 在client端,启动qemu后(sdl模式下), 使用ctrl+alt+2切换到监视端口,输入命令:migrate -d tcp:10.10.10.1:4444。(可以使用info migrate 查看migrate状态) 2、virsh中使用实例: migrate 待迁移域名 qemu://10.10.10.1/system (tls 模式) migrate 待迁移域名 qmeu+ssh://10.10.10.1/system (ssh 模式) migrate 待迁移域名 qmeu+tcp://10.10.10.1/system (tcp 模式) 上面是静态迁移,其中tls模式需要加密和鉴权文件,详细操作见下面网址: http://wiki.libvirt.org/page/TLSSetup#Full_list_of_steps migrate --live 待迁移域名 qemu+ssh://10.10.10.1/system(动态迁移) 3、在virt-manager中,在虚拟机名字上右击鼠标右键,弹出的对话框中,有迁移一项,选上offline为静态迁移,不选为动态迁移。 参考文献: http://www.ibm.com/developerworks/cn/linux/l-cn-mgrtvm2/index.html http://blog.chinaunix.net/space.php?uid=1838361&do=blog&id=1694488