<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[vanileo的专栏]]></title><description><![CDATA[学习是一个漫长的过程，从此我开始习惯用这种方式来记忆。。。]]></description><link>https://blog.csdn.net/vanquishedzxl</link><language>zh-cn</language><generator>https://blog.csdn.net/</generator><copyright><![CDATA[Copyright &copy; vanquishedzxl]]></copyright><item><title><![CDATA[leet code之Surrounded Regions]]></title><link>https://blog.csdn.net/vanquishedzxl/article/details/52074676</link><guid>https://blog.csdn.net/vanquishedzxl/article/details/52074676</guid><author>vanquishedzxl</author><pubDate>Sat, 30 Jul 2016 20:10:44 +0800</pubDate><description><![CDATA[class Solution 
{
public:
	int dfs(int x,int y,int dirx[],int diry[],int lenx,int leny,vector>& board)
	{
		for(int i = 0; i< 4; i++)
		{
			int dxx = x+ dirx[i];
			int dyy = y+ diry[i];

			if(dxx =]]></description><category></category></item><item><title><![CDATA[最短路径：Shortest Reach]]></title><link>https://blog.csdn.net/vanquishedzxl/article/details/51707730</link><guid>https://blog.csdn.net/vanquishedzxl/article/details/51707730</guid><author>vanquishedzxl</author><pubDate>Sat, 18 Jun 2016 23:22:19 +0800</pubDate><description><![CDATA[Given an undirected graph consisting of  nodes
 (labelled 1 to N) where a specific given node  represents
 the start position and an edge between any two nodes is of length  units
 in the graph.]]></description><category></category></item><item><title><![CDATA[深度优先搜索算法]]></title><link>https://blog.csdn.net/vanquishedzxl/article/details/51526384</link><guid>https://blog.csdn.net/vanquishedzxl/article/details/51526384</guid><author>vanquishedzxl</author><pubDate>Sat, 28 May 2016 19:42:55 +0800</pubDate><description><![CDATA[今天我们来复习一下万能的搜索算法之深度优先搜索算法。
深度优先搜索算法顾名思义就是按照树的延伸不停的往下搜索，直到树的尽头之后再一步一步的回溯回来。
好吧，我们直接问你一个问题，给你一个数N，让你输出从1到这个树的全排列，你会怎么写，会不会想到去用若干个for循环？
好吧，你肯定错了，其实他考的就是我们的深度优先搜索算法：
#include
using namespace std;
#]]></description><category></category></item><item><title><![CDATA[Linux kernel 分析之二十三：文件系统]]></title><link>https://blog.csdn.net/vanquishedzxl/article/details/47030479</link><guid>https://blog.csdn.net/vanquishedzxl/article/details/47030479</guid><author>vanquishedzxl</author><pubDate>Thu, 23 Jul 2015 23:06:36 +0800</pubDate><description><![CDATA[对于linux 0.11内核的文件系统的开发，Linus主要参考了Andrew S.Tanenbaum所写的《MINIX操作系统设计与实现》，使用的是其中的1.0版本的MINIX文件系统。而高速缓冲区的工作原理参见M.J.Bach的《UNIX操作系统设计》第三章内容。
通过对源代码的分析，我们可以将minix文件系统分为四个部分，如下如1-1。
l 高速缓冲区的管理程序。主要实现了对硬盘等块设]]></description><category></category></item><item><title><![CDATA[Linux kernel 分析之二十二：内存管理-page fault处理流程]]></title><link>https://blog.csdn.net/vanquishedzxl/article/details/47029805</link><guid>https://blog.csdn.net/vanquishedzxl/article/details/47029805</guid><author>vanquishedzxl</author><pubDate>Thu, 23 Jul 2015 22:20:08 +0800</pubDate><description><![CDATA[page fault是Linux内存管理中比较关键的部分。理解了page fault的处理流程，有助于对Linux内核的内存管理机制的全面理解。因为要考虑到各种异常情况，并且为了使内核健壮高效，所以page fault的处理流程是比较复杂的。我把这个繁琐的处理流程放在最后。在page fault处理函数中使用了很多lazy algorithm。它的核心思想是，由于磁盘IO非常耗时，所以把这些操作尽]]></description><category></category></item><item><title><![CDATA[Linux kernel 分析之二十一：定时器-巧妙的定时器算法]]></title><link>https://blog.csdn.net/vanquishedzxl/article/details/47029753</link><guid>https://blog.csdn.net/vanquishedzxl/article/details/47029753</guid><author>vanquishedzxl</author><pubDate>Thu, 23 Jul 2015 22:16:15 +0800</pubDate><description><![CDATA[内核中经常要用到各种定时器。比如nanosleep()系统调用，让当前进程睡眠一段时间，再把它唤醒。即在expires时刻（以时钟滴答为单位），自动调用wake_up_process。最直接的思路是定义一个定时器，里面有function（函数指针），data（函数参数），expires（调用时刻）。然后排成一个链表。每次时钟中断发生时，扫描整个链表，发现有触发的定时器，就调用function(da]]></description><category></category></item><item><title><![CDATA[Linux kernel 分析之二十：内存管理-内核中的页表映射总结]]></title><link>https://blog.csdn.net/vanquishedzxl/article/details/47029689</link><guid>https://blog.csdn.net/vanquishedzxl/article/details/47029689</guid><author>vanquishedzxl</author><pubDate>Thu, 23 Jul 2015 22:12:07 +0800</pubDate><description><![CDATA[从线性地址到物理地址的转换，实际上是一种映射。所有进程的3~4G的线性地址实际上是映射到相同的物理地址的。这一点不多说了。为了方便起见，3~4G的线性地址与对应的物理地址基本上是呈线性关系的。即线性地址=物理地址+3G。但是如果把这1G的线性地址都简单地处理为对应物理地址+3G，就会有新的问题产生。例如，如果物理地址大于4G，那么内核就没法访问这些地址了。所以，内核必须要从这1G的线
性空间中预]]></description><category></category></item><item><title><![CDATA[Linux kernel 分析之十九：阅读源代码技巧-变量命名规则]]></title><link>https://blog.csdn.net/vanquishedzxl/article/details/47029621</link><guid>https://blog.csdn.net/vanquishedzxl/article/details/47029621</guid><author>vanquishedzxl</author><pubDate>Thu, 23 Jul 2015 22:08:21 +0800</pubDate><description><![CDATA[在阅读源代码的时候，经常会发现在跟踪函数调用时跟踪不下去了，如result = dir->i_op->lookup(parent_inode, child_dentry, nd);
这类似于C++中的多态。inode_operations中的lookup函数指针具体指向哪个函数，不是在编译时确定的，而是在运行期确定的。具体地说，就是在从磁盘上读入inode时才对对应inode的inode_ope]]></description><category></category></item><item><title><![CDATA[Linux kernel 分析之十八：设计模式-文件系统与抽象工厂]]></title><link>https://blog.csdn.net/vanquishedzxl/article/details/47029511</link><guid>https://blog.csdn.net/vanquishedzxl/article/details/47029511</guid><author>vanquishedzxl</author><pubDate>Thu, 23 Jul 2015 22:01:38 +0800</pubDate><description><![CDATA[抽象工厂的典型应用是在gui设计中。为了在运行时方便地替换不同风格的gui设计，我们需要在上层把每种不同风格的gui的实现细节隐藏起来。我们不再显式地调用gui中的某个组件的构造函数，因为这样暴露了组件的实现。相反，我们为每一个风格提供一个“工厂”来生产该风格的“产品”。
抽象工厂可以看作是面向对象设计中常用的多态思想的扩展。普通的多态只是针对一个“产品”，如shape抽象类。而抽象工厂是针对一]]></description><category></category></item><item><title><![CDATA[Linux kernel 分析之十七：设计模式-用C来实现继承和模板]]></title><link>https://blog.csdn.net/vanquishedzxl/article/details/47011663</link><guid>https://blog.csdn.net/vanquishedzxl/article/details/47011663</guid><author>vanquishedzxl</author><pubDate>Wed, 22 Jul 2015 23:00:20 +0800</pubDate><description><![CDATA[多态实现了，封装呢？基本上，C的结构体是不设防的，谁都可以访问。从这一点来看，C很难实现封装。尽管C中有static关键字，可以保证函数和变量的作用仅限于本文件，尽管内核可以通过控制导出符号表（EXPORT_SYMBOL）来控制提供给下层模块的函数和变量，但这些与C++中的封装相去甚远。好在内核的原则是“相信内核不会自己伤害自己”。所以就不苛求啦。
那么继承呢？这个也基本上很难。不过我们可以通过]]></description><category></category></item><item><title><![CDATA[Linux kernel 分析之十六：文件系统-用C来实现面向对象]]></title><link>https://blog.csdn.net/vanquishedzxl/article/details/47011625</link><guid>https://blog.csdn.net/vanquishedzxl/article/details/47011625</guid><author>vanquishedzxl</author><pubDate>Wed, 22 Jul 2015 22:55:55 +0800</pubDate><description><![CDATA[电脑用户跟文件系统打交道是非常频繁的。不过文件系统在结构上应该属于哪一层呢？它和设备驱动的关系如何？不同的系统有不同的理解。Linux把文件系统放在设备驱动之上，访问普通文件时，系统先执行文件系统的代码，把文件指针的偏移量映射为块设备的偏移量，然后调用驱动程序的代码。另一方面，Linux把设备也看作是一种特殊的文件。这有助于简化接口，对程序员来说是很方便的。
        我们可以把接口的观点]]></description><category></category></item><item><title><![CDATA[Linux kernel 分析之十五：kbuild系统-make menuconfig]]></title><link>https://blog.csdn.net/vanquishedzxl/article/details/47011533</link><guid>https://blog.csdn.net/vanquishedzxl/article/details/47011533</guid><author>vanquishedzxl</author><pubDate>Wed, 22 Jul 2015 22:51:31 +0800</pubDate><description><![CDATA[理解了make bzImage的过程，理解了整个kbuild的结构和运行机制，make menuconfig的过程就很容易理解了。
先看/usr/src/linux/Makefile。可以找到：452 %config: scripts_basic outputmakefile FORCE453         $(Q)$(MAKE) $(build)=scripts/kconfig $@
%c]]></description><category></category></item><item><title><![CDATA[Linux kernel 分析之十四：kbuild系统-make bzImage的过程]]></title><link>https://blog.csdn.net/vanquishedzxl/article/details/47011501</link><guid>https://blog.csdn.net/vanquishedzxl/article/details/47011501</guid><author>vanquishedzxl</author><pubDate>Wed, 22 Jul 2015 22:49:11 +0800</pubDate><description><![CDATA[从以上例子中可以看到，内核的编译系统kbuild是个很庞大的系统。但是，它所使用的make和我们平时用的make是一模一样的。kbuild只是通过预定义一些变量（obj-m,obj-y等等）和目标(bzImage ,menuconfig等等)，使内核的编译和扩展变得十分方便。我们不妨yy一下kbuild的一些功能：
1.考虑到Linux能够方便地移植到各个硬件平台，kbuild也必须很容易添加对]]></description><category></category></item><item><title><![CDATA[Linux kernel 分析之十三：kbuild系统-编译到内核和编译成模块的区别]]></title><link>https://blog.csdn.net/vanquishedzxl/article/details/47011437</link><guid>https://blog.csdn.net/vanquishedzxl/article/details/47011437</guid><author>vanquishedzxl</author><pubDate>Wed, 22 Jul 2015 22:44:15 +0800</pubDate><description><![CDATA[代码编译到内核和编译成模块在代码中有什么区别呢？
从模块的代码中看是一样的。入口函数都是module_init(fun)，但是代码中的条件编译会使宏module_init()在编译到内核和编译成模块的情况下替换成不同的代码。
include/linux/init.h中可知#ifndef MODULE...
#define module_init(x)  __initcall(x);...
]]></description><category></category></item><item><title><![CDATA[Linux kernel 分析之十二：kbuild系统-内核模块的编译]]></title><link>https://blog.csdn.net/vanquishedzxl/article/details/47011315</link><guid>https://blog.csdn.net/vanquishedzxl/article/details/47011315</guid><author>vanquishedzxl</author><pubDate>Wed, 22 Jul 2015 22:39:11 +0800</pubDate><description><![CDATA[段错误么？
这里涉及到PIII中用sysenter来代替系统调用的int 0x80的问题。大概就是内核允许一部分代码给用户态进程访问。例如：
cat /proc/$pid/maps可以看到：
ffffe000-fffff000 ---p 00000000 00:00 0          [vdso]ldd 一个应用程序也可以看到：linux-gate.so.1 =>  (0xffffe00]]></description><category></category></item><item><title><![CDATA[Linux kernel 分析之十一：信号通信]]></title><link>https://blog.csdn.net/vanquishedzxl/article/details/47011173</link><guid>https://blog.csdn.net/vanquishedzxl/article/details/47011173</guid><author>vanquishedzxl</author><pubDate>Wed, 22 Jul 2015 22:33:42 +0800</pubDate><description><![CDATA[信号是进程之间通信的一种方式。它包括3部分操作：
1.设置信号处理函数。系统调用signal。内核调用sys_signal()，设置当前进程对某信号的处理函数。
2.发送信号.系统调用kill。内核调用sys_kill()。向目标进程发送信号。3.接收并处理信号。目标进程调用do_signal()处理信号。
从用户态的角度看，目标进程在执行用户态的代码时突然“中断”，转而去执行对应的信号处理]]></description><category></category></item><item><title><![CDATA[Linux kernel 分析之十：内核线程]]></title><link>https://blog.csdn.net/vanquishedzxl/article/details/47010127</link><guid>https://blog.csdn.net/vanquishedzxl/article/details/47010127</guid><author>vanquishedzxl</author><pubDate>Wed, 22 Jul 2015 21:36:08 +0800</pubDate><description><![CDATA[众所周知，内核中创建一个内核线程是通过kernel_thread实现的。声明如下：
        int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
      我们知道，用户态创建线程调用clone()，如果要在内核态创建线程，首先想到的是在内核态调用clone()。这是可以的。比如在init内核线程]]></description><category></category></item><item><title><![CDATA[Linux kernel 分析之九：fork()系统调用]]></title><link>https://blog.csdn.net/vanquishedzxl/article/details/47010021</link><guid>https://blog.csdn.net/vanquishedzxl/article/details/47010021</guid><author>vanquishedzxl</author><pubDate>Wed, 22 Jul 2015 21:28:00 +0800</pubDate><description><![CDATA[不仅进入系统调用时要伪装现场，fork系统调用时返回时也需要伪装现场。因为是“无中生有”。
例如在fork创建新进程时，系统要保证新进程与旧进程一样，从相同的代码开始执行。比如：
#include
#include
int main()
{
        pid_t pid;
        if((pid=fork())>0)        {]]></description><category></category></item><item><title><![CDATA[Linux kernel 分析之八：系统调用参数]]></title><link>https://blog.csdn.net/vanquishedzxl/article/details/46993163</link><guid>https://blog.csdn.net/vanquishedzxl/article/details/46993163</guid><author>vanquishedzxl</author><pubDate>Tue, 21 Jul 2015 22:23:32 +0800</pubDate><description><![CDATA[内核支配了整个计算机的硬件资源，好像一位独裁者，高高在上。他有时候必须像法官一样公正，有时候则必须像狐狸一样狡猾。伪装现场就是他的拿手好戏。
系统调用是很特别的函数，因为它里面实现了用户态到内核态的转换。应用程序要创建新进程，不可能在用户态直接调用sys_fork()。这就需要内核为sys_fork()伪装一下调用现场。
比如fork()系统调用，它有一个简洁得不能再简洁的接口。不过它在内核中]]></description><category></category></item><item><title><![CDATA[Linux kernel 分析之七：内核启动-链接脚本]]></title><link>https://blog.csdn.net/vanquishedzxl/article/details/46993113</link><guid>https://blog.csdn.net/vanquishedzxl/article/details/46993113</guid><author>vanquishedzxl</author><pubDate>Tue, 21 Jul 2015 22:20:18 +0800</pubDate><description><![CDATA[一般来说，用户是不需要关心section的具体位置的。在用户态，内核会解析elf可执行文件的各个section，然后把它映射到虚拟地址空间。然而，在内核启动时，一切得从 
零开始。很多在用户态下应用程序不需要操心的东西，例如映射section的任务不得不由内核自己来完成。上一篇感悟揭示了内核如何建立页表，并且把自身的一部分映射到虚拟地址。内核还要负责对BSS段（所有在代码中未定义的全局变量）的初]]></description><category></category></item></channel></rss>