一、地址空间

进程地址空间由进程可寻址的虚拟内存组成,内核允许进程使用这种虚拟内存中的地址。

每个进程都有一个32位或64位的平坦地址空间,空间的具体大小取决于体系结构。“平坦”指的是地址空间范围是一个独立的连续区间。

现代采用虚拟内存的操作系统通常都使用平坦地址空间而不是分段式的内存模式。

一个进程的地址空间与另一个进程的地址空间即使有相同的内存地址,实际上也彼此互不相干。这样的进程为线程。

一个进程可以寻址4GB虚拟内存(32位地址空间中),但这不代表能访问所有虚拟地址。可以被合法访问的地址空间称为内存区域。

进程只能访问有效内存区域内的内存地址,每个内存区域也具有相关权限如对相关进程有可读、可写、可执行属性。

如果一个进程访问了不在有效范围中的内粗你去与,或以不正确的方式访问了有效地址,那么内核就会终止该进程,并返回“段错误”信息。

  • 可执行文件代码的内存映射称为代码段。(text section)
  • 可执行文件的已初始化全局变量的内存映射,称为数据段。(data section)
  • 包含未初始化全局变量,也就是bss段的零页的内存映射。
  • 用于进程用户空间栈的零页的内存映射
  • 每一个诸如C库或动态连接程序等共享库的代码段、数据段和bss也会被载入进程的地址空间
  • 任何内存映射文件
  • 任何共享内存段
  • 任何匿名的内存映射,比如由malloc()分配的内存

二、内存描述符

内存描述符结构体表示进程的地址空间,该结构包含了和进程地址空间有关的全部信息。

内存描述符由mm_struct结构体表示,定义在文件<linux/sched.h>中。

struct mm_struct {
struct vm_area_struct *mmap; /* list of VMAs 内存区域链表 */
struct rb_root mm_rb; /* VMA形成的红黑树 */
u32 vmacache_seqnum; /* per-thread vmacache */
#ifdef CONFIG_MMU
unsigned long (*get_unmapped_area) (struct file *filp,
unsigned long addr, unsigned long len,
unsigned long pgoff, unsigned long flags);
#endif
unsigned long mmap_base; /* base of mmap area */
unsigned long mmap_legacy_base; /* base of mmap area in bottom-up allocations */
unsigned long task_size; /* size of task vm space */
unsigned long highest_vm_end; /* highest vma end address */
pgd_t * pgd; /* 页全局目录 */
atomic_t mm_users; /* How many users with user space? 使用地址空间的用户数*/
atomic_t mm_count; /* How many references to "struct mm_struct" (users count as 1) 主使用计数器*/
atomic_long_t nr_ptes; /* PTE page table pages */
#if CONFIG_PGTABLE_LEVELS > 2
atomic_long_t nr_pmds; /* PMD page table pages */
#endif
int map_count; /* number of VMAs 内存区域的个数*/ spinlock_t page_table_lock; /* Protects page tables and some counters 页表锁*/
struct rw_semaphore mmap_sem; /* 内存区域信号量 */ struct list_head mmlist; /* List of maybe swapped mm's. These are globally strung
* together off init_mm.mmlist, and are protected
* by mmlist_lock 所有mm_struct形成的链表
*/ unsigned long hiwater_rss; /* High-watermark of RSS usage */
unsigned long hiwater_vm; /* High-water virtual memory usage */ unsigned long total_vm; /* Total pages mapped 全部页面数目*/
unsigned long locked_vm; /* Pages that have PG_mlocked set 上锁的页面数目*/
unsigned long pinned_vm; /* Refcount permanently increased */
unsigned long shared_vm; /* Shared pages (files) */
unsigned long exec_vm; /* VM_EXEC & ~VM_WRITE */
unsigned long stack_vm; /* VM_GROWSUP/DOWN */
unsigned long def_flags;
unsigned long start_code, end_code, start_data, end_data; /* 代码段开始和停止,数据段开始和停止 */
unsigned long start_brk, brk, start_stack; /* 堆首地址,堆尾,进程栈地址 */
unsigned long arg_start, arg_end, env_start, env_end; unsigned long saved_auxv[AT_VECTOR_SIZE]; /* for /proc/PID/auxv 保存的auxv*/ /*
* Special counters, in some configurations protected by the
* page_table_lock, in other configurations by being atomic.
*/
struct mm_rss_stat rss_stat; struct linux_binfmt *binfmt; cpumask_var_t cpu_vm_mask_var; /* 懒惰(Lazy)TLB交换掩码 */ /* Architecture-specific MM context 体系结构特殊数据*/
mm_context_t context; unsigned long flags; /* Must use atomic bitops to access the bits 状态标志*/ struct core_state *core_state; /* coredumping support */
#ifdef CONFIG_AIO
spinlock_t ioctx_lock;
struct kioctx_table __rcu *ioctx_table;
#endif
#ifdef CONFIG_MEMCG
/*
* "owner" points to a task that is regarded as the canonical
* user/owner of this mm. All of the following must be true in
* order for it to be changed:
*
* current == mm->owner
* current->mm != mm
* new_owner->mm == mm
* new_owner->alloc_lock is held
*/
struct task_struct __rcu *owner;
#endif
struct user_namespace *user_ns; /* store ref to file /proc/<pid>/exe symlink points to */
struct file __rcu *exe_file;
#ifdef CONFIG_MMU_NOTIFIER
struct mmu_notifier_mm *mmu_notifier_mm;
#endif
#if defined(CONFIG_TRANSPARENT_HUGEPAGE) && !USE_SPLIT_PMD_PTLOCKS
pgtable_t pmd_huge_pte; /* protected by page_table_lock */
#endif
#ifdef CONFIG_CPUMASK_OFFSTACK
struct cpumask cpumask_allocation;
#endif
#ifdef CONFIG_NUMA_BALANCING
/*
* numa_next_scan is the next time that the PTEs will be marked
* pte_numa. NUMA hinting faults will gather statistics and migrate
* pages to new nodes if necessary.
*/
unsigned long numa_next_scan; /* Restart point for scanning and setting pte_numa */
unsigned long numa_scan_offset; /* numa_scan_seq prevents two threads setting pte_numa */
int numa_scan_seq;
#endif
#if defined(CONFIG_NUMA_BALANCING) || defined(CONFIG_COMPACTION)
/*
* An operation with batched TLB flushing is going on. Anything that
* can move process memory needs to flush the TLB when moving a
* PROT_NONE or PROT_NUMA mapped page.
*/
bool tlb_flush_pending;
#endif
#ifdef CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH
/* See flush_tlb_batched_pending() */
bool tlb_flush_batched;
#endif
struct uprobes_state uprobes_state;
#ifdef CONFIG_X86_INTEL_MPX
/* address of the bounds directory */
void __user *bd_addr;
#endif
#ifdef CONFIG_HUGETLB_PAGE
atomic_long_t hugetlb_usage;
#endif
struct work_struct async_put_work;
};

mm_struct

mm_users域记录正在使用该地址的进程数目。mm_count域是mm_struct结构体的主引用计数。

mmap和mm_rb这两个不同数据结构体描述的对象是相同的:该地址空间中的全部内存区域。前者以链表形式存放而后者以红-黑树形式存放。

mmap结构体作为链表,利于简单、高效地遍历所有元素。而mm_rb结构体作为红-黑树,更适合搜索指定元素。

所有mm_struct结构体都通过自身的mmlist域连接在一个双向链表中,该链表的首元素是init_mm内存描述符,代表init进程地址空间

操作该链表的时候需要使用mmlist_lock锁来防止并发访问,在<kernel/fork.c>中。

2.1 分配内存描述符

在进程描述符<linux/sched.h>中,mm域存放着该进程使用的内存描述符,所以current->mm便指向当前进程的内存描述符。

2.2 撤销内存描述符

当进程退出时,内核会调用定义在kernel/exit.c中的exit_mm()函数,该函数执行一些常规的撤销工作,同时更新一些统计量。

该函数调用mmput()函数减少内存描述符中的mm_users用户计数,如果降到0。调用mmdrop函数,减少mm_count使用计数。

2.3 mm_struct与内核线程

内核线程没有进程地址空间,也没有相关的内存描述符。

三、虚拟内存区域

vm_area_struct结构体,定义在文件<linux/mm_types.h>中。它描述了指定地址空间内连续区域间上的一个独立内存范围。

内核将每个内存区域作为一个单独的内存对象管理,每个内存区域都拥有一致的属性。

/*
* This struct defines a memory VMM memory area. There is one of these
* per VM-area/task. A VM area is any part of the process virtual memory
* space that has a special rule for the page-fault handlers (ie a shared
* library, the executable area etc).
*/
struct vm_area_struct {
/* The first cache line has the info for VMA tree walking. */ unsigned long vm_start; /* Our start address within vm_mm. 区间的首地址*/
unsigned long vm_end; /* The first byte after our end address
within vm_mm. 区间的尾地址*/ /* linked list of VM areas per task, sorted by address */
struct vm_area_struct *vm_next, *vm_prev; /* VMA链表 */ struct rb_node vm_rb; /* 树上该VMA的节点 */ /*
* Largest free memory gap in bytes to the left of this VMA.
* Either between this VMA and vma->vm_prev, or between one of the
* VMAs below us in the VMA rbtree and its ->vm_prev. This helps
* get_unmapped_area find a free area of the right size.
*/
unsigned long rb_subtree_gap; /* Second cache line starts here. */ struct mm_struct *vm_mm; /* The address space we belong to. 相关的mm_struct结构体*/
pgprot_t vm_page_prot; /* Access permissions of this VMA. */
unsigned long vm_flags; /* Flags, see mm.h. 标志位*/ /*
* For areas with an address space and backing store,
* linkage into the address_space->i_mmap interval tree.
*
* For private anonymous mappings, a pointer to a null terminated string
* in the user process containing the name given to the vma, or NULL
* if unnamed.
*/
union {
struct {
struct rb_node rb;
unsigned long rb_subtree_last;
} shared;
const char __user *anon_name;
}; /*
* A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma
* list, after a COW of one of the file pages. A MAP_SHARED vma
* can only be in the i_mmap tree. An anonymous MAP_PRIVATE, stack
* or brk vma (with NULL file) can only be in an anon_vma list.
*/
struct list_head anon_vma_chain; /* Serialized by mmap_sem &
* page_table_lock */
struct anon_vma *anon_vma; /* Serialized by page_table_lock 匿名VMA对象*/ /* Function pointers to deal with this struct. 相关的操作表*/
const struct vm_operations_struct *vm_ops; /* Information about our backing store: */
unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE
units, *not* PAGE_CACHE_SIZE 文件中的偏移量*/
struct file * vm_file; /* File we map to (can be NULL). 被映射的文件(如果存在)*/
void * vm_private_data; /* was vm_pte (shared mem) 私有数据*/ #ifndef CONFIG_MMU
struct vm_region *vm_region; /* NOMMU mapping region */
#endif
#ifdef CONFIG_NUMA
struct mempolicy *vm_policy; /* NUMA policy for the VMA */
#endif
struct vm_userfaultfd_ctx vm_userfaultfd_ctx;
};

vm_area_struct

每个内存描述符都对应于进程地址空间中的唯一区间。vm_start域指向区间的首地址,vm_end域指向区间的尾地址之后的第一个字节。vm_end-vm_start就是区间的长度。

vm_mm域指向和VMA相关的mm_struct结构体,VMA对其香瓜你的mm_struct。

3.1 VMA标志

VMA标志是一种标志位,定义在<linux/mm.h>。在vm_flags域内,包含了域所包含的页面的行为和信息。

/*
* vm_flags in vm_area_struct, see mm_types.h.
*/
#define VM_NONE 0x00000000 #define VM_READ 0x00000001 /* currently active flags 页面可读*/
#define VM_WRITE 0x00000002 /* 页面可写 */
#define VM_EXEC 0x00000004 /* 页面可执行 */
#define VM_SHARED 0x00000008 /* 页面可共享 */ /* mprotect() hardcodes VM_MAYREAD >> 4 == VM_READ, and so for r/w/x bits. */
#define VM_MAYREAD 0x00000010 /* limits for mprotect() etc VM_READ标志可被设置*/
#define VM_MAYWRITE 0x00000020
#define VM_MAYEXEC 0x00000040
#define VM_MAYSHARE 0x00000080 #define VM_GROWSDOWN 0x00000100 /* general info on the segment 区域可向下增长*/
#define VM_UFFD_MISSING 0x00000200 /* missing pages tracking 区域可向上增长*/
#define VM_PFNMAP 0x00000400 /* Page-ranges managed without "struct page", just pure PFN */
#define VM_DENYWRITE 0x00000800 /* ETXTBSY on write attempts.. 区域映射一个不可写文件*/
#define VM_UFFD_WP 0x00001000 /* wrprotect pages tracking */ #define VM_LOCKED 0x00002000 /* 区域中的页面被锁定 */
#define VM_IO 0x00004000 /* Memory mapped I/O or similar 区域映射设备I/O控件*/ /* Used by sys_madvise() */
#define VM_SEQ_READ 0x00008000 /* App will access data sequentially 页面可能会被连续访问*/
#define VM_RAND_READ 0x00010000 /* App will not benefit from clustered reads 页面可能会被随机访问*/ #define VM_DONTCOPY 0x00020000 /* Do not copy this vma on fork 区域不能在fork时被拷贝*/
#define VM_DONTEXPAND 0x00040000 /* Cannot expand with mremap() 区域不能通过mremap()增加*/
#define VM_LOCKONFAULT 0x00080000 /* Lock the pages covered when they are faulted in */
#define VM_ACCOUNT 0x00100000 /* Is a VM accounted object 该区域是一个记账VM对象*/
#define VM_NORESERVE 0x00200000 /* should the VM suppress accounting */
#define VM_HUGETLB 0x00400000 /* Huge TLB Page VM 区域使用了hugetlb页面*/
#define VM_ARCH_1 0x01000000 /* Architecture-specific flag */
#define VM_ARCH_2 0x02000000
#define VM_DONTDUMP 0x04000000 /* Do not include in the core dump */ #ifdef CONFIG_MEM_SOFT_DIRTY
# define VM_SOFTDIRTY 0x08000000 /* Not soft dirty clean area */
#else
# define VM_SOFTDIRTY
#endif #define VM_MIXEDMAP 0x10000000 /* Can contain "struct page" and pure PFN pages */
#define VM_HUGEPAGE 0x20000000 /* MADV_HUGEPAGE marked this vma */
#define VM_NOHUGEPAGE 0x40000000 /* MADV_NOHUGEPAGE marked this vma */
#define VM_MERGEABLE 0x80000000 /* KSM may merge identical pages */ #if defined(CONFIG_X86)
# define VM_PAT VM_ARCH_1 /* PAT reserves whole VMA at once (x86) */
#elif defined(CONFIG_PPC)
# define VM_SAO VM_ARCH_1 /* Strong Access Ordering (powerpc) */
#elif defined(CONFIG_PARISC)
# define VM_GROWSUP VM_ARCH_1
#elif defined(CONFIG_METAG)
# define VM_GROWSUP VM_ARCH_1
#elif defined(CONFIG_IA64)
# define VM_GROWSUP VM_ARCH_1
#elif !defined(CONFIG_MMU)
# define VM_MAPPED_COPY VM_ARCH_1 /* T if mapped copy of data (nommu mmap) */
#endif

VMA标志

3.2 VMA操作

vm_area_struct结构体中的vm_ops域指向与指定内存区域相关的操作函数表,内核使用表中的方法操作VMA。

操作函数表由vm_operations_struct结构体表示,定义在文件<linux/mm.h>中:

/*
* These are the virtual MM functions - opening of an area, closing and
* unmapping it (needed to keep files on disk up-to-date etc), pointer
* to the functions called when a no-page or a wp-page exception occurs.
*/
struct vm_operations_struct {
void (*open)(struct vm_area_struct * area);
void (*close)(struct vm_area_struct * area);
int (*mremap)(struct vm_area_struct * area);
int (*fault)(struct vm_area_struct *vma, struct vm_fault *vmf);
int (*pmd_fault)(struct vm_area_struct *, unsigned long address,
pmd_t *, unsigned int flags);
void (*map_pages)(struct vm_area_struct *vma, struct vm_fault *vmf); /* notification that a previously read-only page is about to become
* writable, if an error is returned it will cause a SIGBUS */
int (*page_mkwrite)(struct vm_area_struct *vma, struct vm_fault *vmf); /* same as page_mkwrite when using VM_PFNMAP|VM_MIXEDMAP */
int (*pfn_mkwrite)(struct vm_area_struct *vma, struct vm_fault *vmf); /* called by access_process_vm when get_user_pages() fails, typically
* for use by special VMAs that can switch between memory and hardware
*/
int (*access)(struct vm_area_struct *vma, unsigned long addr,
void *buf, int len, int write); /* Called by the /proc/PID/maps code to ask the vma whether it
* has a special name. Returning non-NULL will also cause this
* vma to be dumped unconditionally. */
const char *(*name)(struct vm_area_struct *vma); #ifdef CONFIG_NUMA
/*
* set_policy() op must add a reference to any non-NULL @new mempolicy
* to hold the policy upon return. Caller should pass NULL @new to
* remove a policy and fall back to surrounding context--i.e. do not
* install a MPOL_DEFAULT policy, nor the task or system default
* mempolicy.
*/
int (*set_policy)(struct vm_area_struct *vma, struct mempolicy *new); /*
* get_policy() op must add reference [mpol_get()] to any policy at
* (vma,addr) marked as MPOL_SHARED. The shared policy infrastructure
* in mm/mempolicy.c will do this automatically.
* get_policy() must NOT add a ref if the policy at (vma,addr) is not
* marked as MPOL_SHARED. vma policies are protected by the mmap_sem.
* If no [shared/vma] mempolicy exists at the addr, get_policy() op
* must return NULL--i.e., do not "fallback" to task or system default
* policy.
*/
struct mempolicy *(*get_policy)(struct vm_area_struct *vma,
unsigned long addr);
#endif
/*
* Called by vm_normal_page() for special PTEs to find the
* page for @addr. This is useful if the default behavior
* (using pte_page()) would not find the correct page.
*/
struct page *(*find_special_page)(struct vm_area_struct *vma,
unsigned long addr);
}; void (*open)(struct vm_area_struct * area);
当制定的内存区域被加入到一个地址空间时,改函数被调用
void (*close)(struct vm_area_struct * area);
当制定的内存区域从地址空间删除时,该函数被调用
int (*fault)(struct vm_area_struct *vma, struct vm_fault *vmf);
当没有出现在物理内存中的页面被访问时,改函数被页面故障处理调用
int (*page_mkwrite)(struct vm_area_struct *vma, struct vm_fault *vmf);
当某个页面为只读页面时,该函数被页面故障处理调用
int (*access)(struct vm_area_struct *vma, unsigned long addr,
void *buf, int len, int write);
当get_user_pages()函数调用失败时,该函数被access_process_vm()函数调用

VMA操作

3.3 内存区域的树型结构和内存区域的链表结构

vm_area_struct结构体通过自身的vm_next域连入链表,所有区域按地址增长方向排序,mmap域指向链表中第一个内存区域,链中最后一个结构体指向空。

3.4 实际使用中的内存区域

可以使用/proc文件系统和pmap工具查看给定进程的内存空间和其中所含的内存区域。

四、操作内存区域

内核市场需要在某个内存区域上执行一些操作,他们都声明在<linux/mm.h>中。

4.1 find_vma()

为了找到给定的内存地址属于哪个内存区域,内核提供了find_vma()函数。函数定义在<mm/mmap.c>中。

struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr);
在指定的地址空间中搜索第一个vm_end大于addr的内存区域。
如果没有发现这样的区域,该函数返回NULL。否则返回指向匹配的内存区域的vm_area_struct结构体指针。

find_vma

4.2 find_vma_prev()

与find_vma工作方式相同,返回第一个小于addr的VMA,该函数定义和声明分别在文件mm/mmap.c中和文件<linux/mm.h>中

struct vm_area_struct *find_vma_prev(struct mm_struct *mm, unsigned long addr, struct vm_area_struct **pprev)
pprev参数存放指向先于addr的VMA指针

find_vma_prev

4.3 find_vma_intersection()

返回第一个指定地址区间相交的VMA,内联函数,在<linux/mm.h>中

stati inline struct vm_area_struct *find_vma_intersection(struct mm_struct *mm, unsigned long start_addr, unsigned long end_addr) {
struct vm_area_struct *vma;
vma = find_vma(mm, start_addr);
if(vma && end_addr <= vma->vm_start)
vma = NULL;
return vma;
}
第一个参数mm是要搜索的地址空间,start_addr是区间开始首地址,end_addr是区间的尾位置。
如果返回NULL,没有发现这样的区域。如果返回有效VMA,则只有在该VMA起始位置于给定的地址区间结束位置之前,才将其返回。如果VMA起始位置大于指定地址范围的结束位置,则该函数返回NULL。

find_vma_intersection

五、mmap()和do_mmap():创建地址区间

内核使用do_mmap()函数创建一个新的线性地址区间。定义在文件<linux/mm.h>中。

unsigned long do_mmap(struct file *file, unsigned long addr, unsigned long len, unsigned long prot, unsigned long flag, unsigned long offset)
file:指定的文件,offset:偏移量,len:长度

do_mmap

如果file参数是NULL,offset也为0,代表这次映射没有文件相关,是匿名映射。

addr是可选参数,指定搜索空闲区域的起始位置。

prot参数指定内存区域中页面的访问权限,标志位在<asm/mman.h>中,不同体系结构有所不同。

PROT_READ:对应于VM_READ
PROT_WRITE:对应于VM_WRITE
PROT_EXEC:对应于VM_EXEC
PROT_NONE:不可被访问

页保护标志

flag参数指定了VMA标志,这些标志指定类型并该表映射的行为,也在文件<asm/mman.h>中定义。

MAP_SHARED:映射可以被共享
MAP_PRIVATE:映射不能被共享
MAP_FIXED:新区间必须开始于指定地址addr
MAP_ANONYMOUS:映射不是file-backed,而是匿名的
MAP_GROWSDOWN:对应于VM_GROWSDOWN
MAP_DENYWRITE:对应于VM_DENYWRITE
MAP_EXECUTABLE:对应于VM_EXECUTABLE
MAP_LOCKED:对应于VM_LOCKED
MAP_NORESERVE:不需要为映射保留空间
MAP_POPULATE:填充页表
MAP_NONBLOCK:在I/O操作上不堵塞

页保护标志

空户空间可以通过mmap()系统调用获取内核函数do_mmap()功能,mmap调用定义如下:

void *mmap2(void *start, size_t length, int prot, int flags, int fd, off_t pgoff)

mmap2

六、munmap()和do_menmap():删除地址区间

do_munmap()函数从特定的进程地址空间中删除指定地址区间,该函数定义在文件<linux/mm.h>

int do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
mm:要删除区域所在的地址空间
start:要删除的开始地址
len:地址长度
成功:,否则负的错误码

do_munmap

系统调用munmap()给用户提供了删除指定地址的方法,和mmap相反。

int munmap(void *start, size_t length)

munmap

七、页表

地址转换需要将虚拟地址分段,使每段虚拟地址都作为一个索引指向页表,而页表项则指向下一级别的页表或指向最终的物理页面。

Linux使用三级页表完成地址转换。使用三级页表结构可以利用“最大公约数”的思想,一种简单的体系结构。

顶级页表是全局目录(PGD)

二级页表是中间页目录(PMD)

最后一级页表指向物理页面。

页表队以ing的结构体依赖于具体的体系结构,所以定义在文件<asm/page.h>中。

Linux内核设计与实现 总结笔记(第十五章)进程地址空间的更多相关文章

  1. Linux内核设计与实现 总结笔记(第五章)系统调用

    系统调用 内核提供了用户进程和内核交互的接口,使得应用程序可以受限制的访问硬件设备. 提供这些接口主要是为了保证系统稳定可靠,避免应用程序恣意妄行. 一.内核通信 系统调用在用户空间进程和硬件设备之间 ...

  2. 《Linux内核设计与实现》读书笔记(十五)- 进程地址空间(kernel 2.6.32.60)

    进程地址空间也就是每个进程所使用的内存,内核对进程地址空间的管理,也就是对用户态程序的内存管理. 主要内容: 地址空间(mm_struct) 虚拟内存区域(VMA) 地址空间和页表 1. 地址空间(m ...

  3. Linux内核设计与实现 总结笔记(第七章)中断和中断处理

    中断和中断处理 处理器的速度跟外围硬件设备的速度往往不再一个数量级上,因此,如果内核采取让处理器向硬件发出一个请求. 然后专门等待回应的办法,如果专门等待回应,明显太慢.所以等待期间可以处理其他事务, ...

  4. Linux内核设计与实现 总结笔记(第六章)内核数据结构

    内核数据结构 Linux内核实现了这些通用数据结构,而且提倡大家在开发时重用. 内核开发者应该尽可能地使用这些数据结构,而不要自作主张的山寨方法. 通用的数据结构有以下几种:链表.队列.映射和二叉树 ...

  5. Linux内核设计与实现 总结笔记(第四章)进程调度

    进程调度 调度程序负责决定将哪个进程投入运行,何时运行以及运行多长时间. 调度程序没有太复杂的原理,最大限度地利用处理器时间的原则是,只要有可以执行的进程,那么就总会有进程正在执行. 一.多任务 多任 ...

  6. Linux内核设计与实现 总结笔记(第三章)进程

    进程管理 进程:处于执行期的程序. 线程:在进程中活动的对象 虚拟机制 虚拟处理器:多个进程分享一个处理器 虚拟内存:多个线程共享虚拟内存 一.进程描述符和任务结构 进程存放在双向循环链表中(队列), ...

  7. 把握linux内核设计思想(十三):内存管理之进程地址空间

    [版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet.文章仅供学习交流,请勿用于商业用途] 进程地址空间由进程可寻址的虚拟内存组成,Linux 的虚拟地址空间为0~4G字 ...

  8. Linux内核设计与实现 总结笔记(第十一章)定时器和时间管理

    时间管理在内核中占用非常重要的地位,内核中有大量的函数都需要基于时间驱动的,内核对相对时间和绝对时间都非常需要. 一.内核中的时间概念 内核必须在硬件的帮助下才能计算和管理时间,系统定时器以某种频率自 ...

  9. Linux内核设计与实现 总结笔记(第十三章)虚拟文件系统

    一.通用文件系统接口 Linux通过虚拟文件系统,使得用户可以直接使用open().read().write()访问文件系统,这种协作性和泛型存取成为可能. 不管文件系统是什么,也不管文件系统位于何种 ...

  10. 《Linux内核设计与实现》课本第十八章自学笔记——20135203齐岳

    <Linux内核设计与实现>课本第十八章自学笔记 By20135203齐岳 通过打印来调试 printk()是内核提供的格式化打印函数,除了和C库提供的printf()函数功能相同外还有一 ...

随机推荐

  1. 远程桌面 使用 本地输入法(虚拟化 终端 远程接入 RemoteApp)

    远程桌面连接组件是微软从Windows 2000 Server开始提供的,该组件一经推出便受到了很多用户的拥护和使用.   在WINDOWS XP和WINDOWS SERVER 2003中微软公司将该 ...

  2. centos7:Zookeeper集群安装

    将安装包上传到安装目录 解压文件 tar -zxvf zookeeper-3.4.12.tar.gz 移动解压后的文件到软件目录 mv zookeeper-3.4.12 /home/softwareD ...

  3. Servlet 响应 响应相关与重定向 请求 获取表单数据2种方法

    一.HttpServletResponse  (响应) 包括下面三个: 1.响应消息行  HTTP/1.1  200 OK 200是HTTP状态码, 代表请求已成功. (查httpservletres ...

  4. 【Linux开发】计算机底层是如何访问显卡的?

    1. 显卡驱动是怎么控制显卡的, 就是说, 使用那些指令控制显卡, 通过端口么? 2. DirectX 或 OpenGL 或 CUDA 或 OpenCL 怎么找到显卡驱动, 显卡驱动是不是要为他们提供 ...

  5. 【Qt开发】 V4L2_CAP_VIDEO_OVERLAY与V4L2_CAP_VIDEO_CAPTURE的区别

    原文地址http://www.cnblogs.com/tlm1992/archive/2012/06/12/2545772.html 这部分spec的内容没有全看懂,但是根据FSL的代码能知道这其中的 ...

  6. 使用logstash收集java、nginx、系统等常见日志

    目录 1.使用codec的multiline插件收集java日志... 1 2.收集nginx日志... 2 3.收集系统syslog日志... 3 4.使用fliter的grok模块收集mysql日 ...

  7. Java基础语法--IDEA快捷键

    Ctrl+Shift + Enter,语句完成“!”,否定完成,输入表达式时按 “!”键Ctrl+E,最近的文件Ctrl+Shift+E,最近更改的文件Shift+Click,可以关闭文件Ctrl+[ ...

  8. [转帖]深度解析区块链POW和POS的区别

    深度解析区块链POW和POS的区别 Proof of Work 还有Proof of Stake 之前理解程了 state ... 股权的意思 还有 delegated proof of Stake ...

  9. 全新一台node节点加入到集群中

    目录 前言 对新节点做解析 方法一 hosts 文件解析 方法二 bind 解析 测试 分发密钥对 推送 CA 证书 flanneld 部署 推送flanneld二进制命令 推送flanneld秘钥 ...

  10. 正反向代理、负载均衡、Nginx配置实现

    一.正反向代理 1.前提 我们曾经使用翻墙软件,访问google:使用了代理软件时,需要在浏览器选项中配置代理的地址,我们仅仅有代理这个概念,并不清楚代理还有正向和反向之分. 2.正向代理(代替客户端 ...