《深入Linux內核架構》讀書筆記002——簡介和概述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)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章