Linux 内核原理摘录_linux



文章目录

  • 一、Linux 内核设计与实现
  • 1、进程管理
  • (1)调度
  • 2、内核数据结构
  • (1)kfifo
  • 3、中断



一、Linux 内核设计与实现

    本章主要用来摘录《Linux 内核设计与实现》一书中学习知识点,其基于 Linux 2.6.34

1、进程管理

// include/linux/sched.h

struct task_struct {
	volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */
	void *stack;
	atomic_t usage;
	unsigned int flags;	/* per process flags, defined below */
	unsigned int ptrace;

	int lock_depth;		/* BKL lock depth */
	
	// ...
}

    进程描述符 task_struct 包含了一个具体进程的所有信息。其相对较大,在 32 位机器上,它大约有 1.7KB

Linux 内核原理摘录_内核数据结构_02


    Linux 通过 slab 分配器分配 task_struct 结构。在 2.6 以前的内核中,各个进程的 task_struct 存放在它们内核栈的尾端。这样做是为了让那些像 x86 那样寄存器较少的硬件体系结构只要通过栈指针就能计算出它的位置,而避免使用额外的寄存器专门记录。由于现在用 slab 分配器动态生成 task_struct ,所以只需要在栈底创建一个新的结构 struct thread_info

// arch/x86/include/asm/thread_info.h

struct thread_info {
	struct task_struct	*task;		/* main task structure */
	struct exec_domain	*exec_domain;	/* execution domain */
	__u32			flags;		/* low level flags */
	__u32			status;		/* thread synchronous flags */
	__u32			cpu;		/* current CPU */
	int			preempt_count;	/* 0 => preemptable,
						   <0 => BUG */
	mm_segment_t		addr_limit;
	struct restart_block    restart_block;
	void __user		*sysenter_return;
#ifdef CONFIG_X86_32
	unsigned long           previous_esp;   /* ESP of the previous stack in
						   case of nested (IRQ) stacks
						*/
	__u8			supervisor_stack[0];
#endif
	int			uaccess_err;
};

Linux 内核原理摘录_服务器_03

(1)调度

CFS 调度

Linux 内核原理摘录_运维_04

2、内核数据结构

(1)kfifo

// kernel/kfifo.c

/**
 * 使用 buffer 内存创建并初始化kfifo队列
 *
 * @param fifo kfifo队列
 * @param buffer 指向内存地址
 * @param size 内存大小,必须是 2 的幂
 */
void kfifo_init(struct kfifo *fifo, void *buffer, unsigned int size);

/**
 * 动态创建并初始化kfifo队列
 *
 * @param fifo kfifo队列
 * @param size 创建kfifo队列大小
 * @param gfp_mask 标识
 * @return
 */
int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask);

/**
 * 把数据推入到队列。该函数把 from 指针所指的 len 字节数据拷贝到 fifo 所指的队列中,如果成功,
 * 则返回推入数据的字节大小。如果队列中的空闲字节小于 len,则该函数值最多可拷贝队列可用空间那么多
 * 的数据,这样的话,返回值可能小于 len。
 */
unsigned int kfifo_in(struct kfifo *fifo, const void *from, unsigned int len);

/**
 * 该函数从 fifo 所指向的队列中拷贝出长度为 len 字节的数据到 to 所指的缓冲中。如果成功,
 * 该函数则返回拷贝的数据长度。如果队列中数据大小小于 len, 则该函数拷贝出的数据必然小于
 * 需要的数据大小
 */
unsigned int kfifo_out(struct kfifo *fifo, void *to, unsigned int len);

/**
 * 与 kfifo_out 类似,获取数据,但读后不删除数据。参数 offset 指向队列中的索引位置,如果
 * 该参数为 0,则读队列头,这时候和 kfifo_out 一样。
 */
unsigned int kfifo_out_peek(struct kfifo *fifo, void *to, unsigned int len, unsigned offset);

Linux 内核原理摘录_服务器_05


Linux 内核原理摘录_运维_06

3、中断

Linux 内核原理摘录_数据_07