《深入Linux内核架构》简介和概述2

简介和概述

本章最后还涉及到一些相关的代码,将在这介绍。

《深入Linux内核架构》使用的源代码是kernel 2.6.24(后续称参考代码),这里以它为依据作说明。

计时

Linux提供了全局变量jiffies(和jiffies_64)作为时间坐标,它位于include\linux\jiffies.h:

/*
 * The 64-bit value is not atomic - you MUST NOT read it
 * without sampling the sequence number in xtime_lock.
 * get_jiffies_64() will do this for you as appropriate.
 */
extern u64 __jiffy_data jiffies_64;
extern unsigned long volatile __jiffy_data jiffies;

jiffies会按恒定的时间间隔递增。

链表

链表接口位于include\linux\list.h,链表数据结构必须包含如下类型的成员:

/*
 * Simple doubly linked list implementation.
 *
 * Some of the internal functions ("__xxx") are useful when
 * manipulating whole lists rather than single entries, as
 * sometimes we already know the next/prev entries and we can
 * generate better code by using them directly rather than
 * using the generic single-entry routines.
 */

struct list_head {
	struct list_head *next, *prev;
};

它是一个双向链表组件。

对于真正的双向链表实例,都需要包含它,下面是一个例子:

struct sas_port {
	struct device		dev;

	int			port_identifier;
	int			num_phys;
	/* port flags */
	unsigned int		is_backlink:1;

	/* the other end of the link */
	struct sas_rphy		*rphy;

	struct mutex		phy_list_mutex;
	struct list_head	phy_list;
};

有一个宏用来初始化链表:

#define LIST_HEAD_INIT(name) { &(name), &(name) }

下面是一个例子:

static struct list_head devreg_anchor = LIST_HEAD_INIT(devreg_anchor);

标准的双向链表如下图所示:

链表的操作函数有:

/**
 * list_add - add a new entry
 * @new: new entry to be added
 * @head: list head to add it after
 *
 * Insert a new entry after the specified head.
 * This is good for implementing stacks.
 */
static inline void list_add(struct list_head *new, struct list_head *head)

/**
 * list_del - deletes entry from list.
 * @entry: the element to delete from the list.
 * Note: list_empty on entry does not return true after this, the entry is in an undefined state.
 */
static inline void list_del(struct list_head *entry)

/**
 * list_empty - tests whether a list is empty
 * @head: the list to test.
 */
static inline int list_empty(struct list_head *head)

等等,这里就不全列举了。下面是一个函数调用的例子:

	BUG_ON(!list_empty(&port->phy_list));

内核对象

内核需要跟踪C语言中的结构体实例,它通过给这些实例包含内核对象来实现。

内核对象的结构位于include\linux\kobject.h,如下所示:

struct kobject {
	const char		* k_name;
	struct kref		kref;
	struct list_head	entry;
	struct kobject		* parent;
	struct kset		* kset;
	struct kobj_type	* ktype;
	struct sysfs_dirent	* sd;
};

k_name是对象的文本名称,可利用sysfs(《深入Linux内核架构》第十章会介绍)导出到用户空间。

kref是引用计数,当它的值是0,表示不需要该对象了。

其它成员暂不介绍。

kobject抽象实际上提供了在内核使用面向对象技术的可能性。

需要跟踪的结构体实例必须嵌入上述的kobject,下面是一个例子:

/* device block control structure */
struct edac_device_block {
	struct edac_device_instance *instance;	/* Up Pointer */
	char name[EDAC_DEVICE_NAME_LEN + 1];

	struct edac_device_counter counters;	/* basic UE and CE counters */

	int nr_attribs;		/* how many attributes */

	/* this block's attributes, could be NULL */
	struct edac_dev_sysfs_block_attribute *block_attributes;

	/* edac sysfs device control */
	struct kobject kobj;
};

数据类型定义

在include\linux\types.h中定义了很多的类型,比如u_int8_t等:

typedef		__u8		u_int8_t;
typedef		__s8		int8_t;
typedef		__u16		u_int16_t;
typedef		__s16		int16_t;
typedef		__u32		u_int32_t;
typedef		__s32		int32_t;

需要注意这里有包含一个头文件:

#include <asm/types.h>

但实际上并没有asm这样的目录,它实际上算是一个链接,真正对应的是带平台的:

它会在编译的时候真正指定。

字节序

计算机有大端和小端的字节序。

内核提供了函数和宏来处理字节序,位于include\linux\byteorder\generic.h中:

/*
 * inside the kernel, we can use nicknames;
 * outside of it, we must avoid POSIX namespace pollution...
 */
#define cpu_to_le64 __cpu_to_le64
#define le64_to_cpu __le64_to_cpu
#define cpu_to_le32 __cpu_to_le32
#define le32_to_cpu __le32_to_cpu
#define cpu_to_le16 __cpu_to_le16
#define le16_to_cpu __le16_to_cpu

per-cpu

在有若干个CPU的SMP(Symmetrical Multi-Processing)系统中,会为每个CPU分别创建变量的实例。

#define get_cpu()		({ preempt_disable(); smp_processor_id(); })

可以获取特定CPU的实例。

void smp_setup_processor_id(void);

可以获取当前活动的处理器ID。

__user

内核使用__user来标识指向用户空间中区域的指针,在没有进一步预防措施的情况下,不能轻易访问这些指针指向的区域。

比如:

alpha_clone(unsigned long clone_flags, unsigned long usp,
	    int __user *parent_tid, int __user *child_tid,
	    unsigned long tls_value, struct pt_regs *regs)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值