新聞中心
Linux是一款開(kāi)源的、基于Unix的操作系統(tǒng)。作為世界上最著名的服務(wù)器操作系統(tǒng)之一,Linux已經(jīng)成為了不可或缺的一部分,它在云計(jì)算、大數(shù)據(jù)處理和安全方面發(fā)揮著至關(guān)重要的作用。在Linux內(nèi)核中,對(duì)于任何一位程序員和系統(tǒng)工程師而言,最基本的就是對(duì)Linux源碼的理解。本篇文章將深入探究linux 3.10.0源碼,幫助大家更好地了解內(nèi)核的奧秘。

成都創(chuàng)新互聯(lián)專(zhuān)注于金堂縣企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站設(shè)計(jì),商城網(wǎng)站制作。金堂縣網(wǎng)站建設(shè)公司,為金堂縣等地區(qū)提供建站服務(wù)。全流程定制開(kāi)發(fā),專(zhuān)業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,成都創(chuàng)新互聯(lián)專(zhuān)業(yè)和態(tài)度為您提供的服務(wù)
1. 開(kāi)始我們的探究之旅
我們需要了解的是,Linux 3.10.0是一個(gè)穩(wěn)定版的內(nèi)核版本。通過(guò)獲取這個(gè)版本的源碼,我們可以找到一個(gè)名為“Documentation”的文件夾,其中包含了豐富的文檔和使用手冊(cè)。這些文檔在大多數(shù)情況下是完整的,詳細(xì)的,說(shuō)明了源代碼的使用和實(shí)現(xiàn)方法,以及核心代碼的一些關(guān)鍵部分的詳細(xì)說(shuō)明。
在文檔中,你可以找到大量的信息,包括Linux的基本結(jié)構(gòu)、驅(qū)動(dòng)程序和系統(tǒng)調(diào)用、內(nèi)存管理和進(jìn)程管理等核心要素,都有詳細(xì)的說(shuō)明。不僅如此,還有一些有關(guān)開(kāi)發(fā)者文檔的信息,例如如何為L(zhǎng)inux內(nèi)核提交一個(gè)補(bǔ)丁等等。
2. 探究?jī)?nèi)核的組成部分
在探究Linux源代碼時(shí),我們首先要了解Linux內(nèi)核的組成部分。補(bǔ)丁是內(nèi)核開(kāi)發(fā)的重要組成部分。補(bǔ)丁是完整代碼的一部分,可以應(yīng)用于一個(gè)代碼庫(kù)的部分,而不會(huì)影響庫(kù)中其他部分的代碼。
除了補(bǔ)丁之外,Linux內(nèi)核還包括若干個(gè)子系統(tǒng),其中最重要的三個(gè)子系統(tǒng)是進(jìn)程管理、內(nèi)存管理和設(shè)備管理。進(jìn)程管理主要負(fù)責(zé)Linux操作系統(tǒng)中進(jìn)程的分配,執(zhí)行和退出。內(nèi)存管理負(fù)責(zé)管理系統(tǒng)內(nèi)部的內(nèi)存分配和釋放,以及為L(zhǎng)inux中各個(gè)進(jìn)程分配內(nèi)存。設(shè)備管理是指對(duì)各個(gè)設(shè)備進(jìn)行管理,包括塊設(shè)備、字符設(shè)備、網(wǎng)絡(luò)設(shè)備等等。
3. 了解虛擬空間管理類(lèi)
在Linux內(nèi)核中,有一個(gè)非常重要的類(lèi)稱(chēng)為vm_area_struct。這個(gè)類(lèi)在虛擬內(nèi)存管理期間扮演了重要角色,特別是在內(nèi)存映射、文件交換和共享內(nèi)存等功能中。每個(gè)進(jìn)程都有一個(gè)vm_area_struct列表,Linux內(nèi)核在啟動(dòng)進(jìn)程時(shí)會(huì)為每個(gè)進(jìn)程分配一個(gè)虛擬地址空間,該進(jìn)程的虛擬地址空間將以vm_area_struct列表的形式表示。
在深入了解vm_area_struct之前,我們需要了解一些vm_area_struct中包含的字段。其中一個(gè)很重要的字段是start,它表示vm_area的起始地址。另一個(gè)很重要的字段是end,它表示vm_area的結(jié)束地址。其中,每個(gè)vm_area都表示一個(gè)可以被映射到其上的虛擬地址范圍。
4. 數(shù)據(jù)結(jié)構(gòu)的實(shí)現(xiàn)
現(xiàn)在,我們來(lái)進(jìn)一步了解Linux內(nèi)核的數(shù)據(jù)結(jié)構(gòu)。在任何一個(gè)操作系統(tǒng)中,數(shù)據(jù)結(jié)構(gòu)是非常重要的一部分,因?yàn)樗鼈儧Q定了數(shù)據(jù)如何存儲(chǔ)和管理。在Linux內(nèi)核中,有幾個(gè)非常有代表性的數(shù)據(jù)結(jié)構(gòu),例如鏈表、堆棧、哈希表等等。
鏈表是最基本的數(shù)據(jù)結(jié)構(gòu)之一,在Linux內(nèi)核中被廣泛應(yīng)用。由于Linux最基本的結(jié)構(gòu)是列表結(jié)構(gòu),所以L(fǎng)inux內(nèi)核中的許多數(shù)據(jù)結(jié)構(gòu)都是以鏈表為基礎(chǔ)的。它們通常用于維護(hù)內(nèi)存塊、進(jìn)程、文件系統(tǒng)節(jié)點(diǎn)等數(shù)據(jù)結(jié)構(gòu)。
堆棧是Linux內(nèi)核中的另一個(gè)非常重要的數(shù)據(jù)結(jié)構(gòu),可以通過(guò)其中的IO棧,對(duì)文件和網(wǎng)絡(luò)操作進(jìn)行讀寫(xiě)操作。在文件系統(tǒng)中,堆棧用于跟蹤和查找文件和目錄節(jié)點(diǎn),以及創(chuàng)建和修改文件。
哈希表在Linux內(nèi)核中也非常常見(jiàn)。它們通常用于維護(hù)各種資源的關(guān)系,例如進(jìn)程和文件之間的關(guān)系,內(nèi)存映射的對(duì)應(yīng)關(guān)系等等。
5.
對(duì)于任何一位程序員來(lái)說(shuō),了解Linux內(nèi)核源代碼的理解是非常必要的。通過(guò)閱讀源代碼和文檔,我們可以更好地理解內(nèi)核的工作原理,加強(qiáng)自己在系統(tǒng)管理、網(wǎng)絡(luò)安全、云計(jì)算和大數(shù)據(jù)處理等方面的能力。在學(xué)習(xí)過(guò)程中,我們需要學(xué)會(huì)了解Linux內(nèi)核的組成部分、虛擬內(nèi)存管理以及常見(jiàn)的數(shù)據(jù)結(jié)構(gòu)。掌握這些基本知識(shí),可以幫助我們更好地探索Linux內(nèi)核的奧秘。
成都網(wǎng)站建設(shè)公司-創(chuàng)新互聯(lián),建站經(jīng)驗(yàn)豐富以策略為先導(dǎo)10多年以來(lái)專(zhuān)注數(shù)字化網(wǎng)站建設(shè),提供企業(yè)網(wǎng)站建設(shè),高端網(wǎng)站設(shè)計(jì),響應(yīng)式網(wǎng)站制作,設(shè)計(jì)師量身打造品牌風(fēng)格,熱線(xiàn):028-86922220源代碼放在linux里,怎么訪(fǎng)問(wèn)
1、首先源代碼放在linux里的訪(fǎng)問(wèn)源碼路徑,一般路徑都是在根目錄下的/usr/src下,其中l(wèi)inux-***代表版本號(hào)。
2、其次確定當(dāng)前系統(tǒng)的版本,hostnamectl可以查看當(dāng)前系統(tǒng)信息。
3、最后可以看到,每個(gè)driver目錄都有一個(gè)Kcongif目錄可支持裁剪。
Linux 之mutex 源碼分析
mutex相關(guān)的函數(shù)并不是linux kernel實(shí)現(xiàn)的,而是glibc實(shí)現(xiàn)的,源碼位于埋笑nptl目錄下。
首先說(shuō)數(shù)據(jù)結(jié)構(gòu):
typedef union
{
struct
{
int __lock;
unsigned int __count;
int __owner;
unsigned int __nusers;
/* KIND must stay at this position in the structure to maintain
binary compatibility. */
int __kind;
int __spins;
} __data;
char __size;
long int __align;
} pthread_mutex_t;
int __lock; 資晌粗源競(jìng)爭(zhēng)引用計(jì)數(shù)
int __kind; 鎖類(lèi)型,init 函數(shù)中mutexattr 參數(shù)傳遞,該參數(shù)可以為NULL,一般為 PTHREAD_MUTEX_NORMAL
結(jié)構(gòu)體其他元素暫時(shí)不了解,以后更新。
/*nptl/pthread_mutex_init.c*/
int
__pthread_mutex_init (mutex, mutexattr)
pthread_mutex_t *mutex;
const pthread_mutexattr_t *mutexattr;
{
const struct pthread_mutexattr *imutexattr;
assert (sizeof (pthread_mutex_t) __data.__kind = imutexattr->mutexkind & ~0x;
/* Default values: mutex not used yet. */
// mutex->__count = 0;already done by memset
宴液鎮(zhèn) // mutex->__owner = 0;already done by memset
// mutex->__nusers = 0;already done by memset
// mutex->__spins = 0;already done by memset
return 0;
}
init函數(shù)就比較簡(jiǎn)單了,將mutex結(jié)構(gòu)體清零,設(shè)置結(jié)構(gòu)體中__kind屬性。
/*nptl/pthread_mutex_lock.c*/
int
__pthread_mutex_lock (mutex)
pthread_mutex_t *mutex;
{
assert (sizeof (mutex->__size) >= sizeof (mutex->__data));
pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
switch (__builtin_expect (mutex->__data.__kind, PTHREAD_MUTEX_TIMED_NP))
{
…
default:
/* Correct code cannot set any other type. */
case PTHREAD_MUTEX_TIMED_NP:
simple:
/* Normal mutex. */
LLL_MUTEX_LOCK (mutex->__data.__lock);
break;
…
}
/* Record the ownership. */
assert (mutex->__data.__owner == 0);
mutex->__data.__owner = id;
#ifndef NO_INCR
++mutex->__data.__nusers;
#endif
return 0;
}
該函數(shù)主要是調(diào)用LLL_MUTEX_LOCK, 省略部分為根據(jù)mutex結(jié)構(gòu)體__kind屬性不同值做些處理。
宏定義函數(shù)LLL_MUTEX_LOCK最終調(diào)用,將結(jié)構(gòu)體mutex的__lock屬性作為參數(shù)傳遞進(jìn)來(lái)
#define __lll_mutex_lock(futex) \
((void) ({\
int *__futex = (futex); \
if (atomic_compare_and_exchange_bool_acq (__futex, 1, 0) != 0)\
__lll_lock_wait (__futex);\
}))
atomic_compare_and_exchange_bool_acq (__futex, 1, 0)宏定義為:
#define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
({ __typeof (mem) __gmemp = (mem);\
__typeof (*mem) __gnewval = (newval); \
\
*__gmemp == (oldval) ? (*__gmemp = __gnewval, 0) : 1; })
這個(gè)宏實(shí)現(xiàn)的功能是:
如果mem的值等于oldval,則把newval賦值給mem,放回0,否則不做任何處理,返回1.
由此可以看出,當(dāng)mutex鎖限制的資源沒(méi)有競(jìng)爭(zhēng)時(shí),__lock 屬性被置為1,并返回0,不會(huì)調(diào)用__lll_lock_wait (__futex); 當(dāng)存在競(jìng)爭(zhēng)時(shí),再次調(diào)用lock函數(shù),該宏不做任何處理,返回1,調(diào)用__lll_lock_wait (__futex);
void
__lll_lock_wait (int *futex)
{
do
{
int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1);
if (oldval != 0)
lll_futex_wait (futex, 2);
}
while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0);
}
atomic_compare_and_exchange_val_acq (futex, 2, 1); 宏定義:
/* The only basic operation needed is compare and exchange. */
#define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
({ __typeof (mem) __gmemp = (mem);\
__typeof (*mem) __gret = *__gmemp;\
__typeof (*mem) __gnewval = (newval); \
\
if (__gret == (oldval)) \
*__gmemp = __gnewval; \
__gret; })
這個(gè)宏實(shí)現(xiàn)的功能是,當(dāng)mem等于oldval時(shí),將mem置為newval,始終返回mem原始值。
此時(shí),futex等于1,futex將被置為2,并且返回1. 進(jìn)而調(diào)用
lll_futex_wait (futex, 2);
#define lll_futex_timed_wait(ftx, val, timespec)\
({ \
DO_INLINE_SYSCALL(futex, 4, (long) (ftx), FUTEX_WAIT, (int) (val),\
(long) (timespec)); \
_r10 == -1 ? -_retval : _retval;\
})
該宏對(duì)于不同的平臺(tái)架構(gòu)會(huì)用不同的實(shí)現(xiàn),采用匯編語(yǔ)言實(shí)現(xiàn)系統(tǒng)調(diào)用。不過(guò)確定的是調(diào)用了Linux kernel的futex系統(tǒng)調(diào)用。
futex在linux kernel的實(shí)現(xiàn)位于:kernel/futex.c
SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val,
struct timespec __user *, utime, u32 __user *, uaddr2,
u32, val3)
{
struct timespec ts;
ktime_t t, *tp = NULL;
u32 val2 = 0;
int cmd = op & FUTEX_CMD_MASK;
if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI ||
cmd == FUTEX_WAIT_BITSET ||
cmd == FUTEX_WAIT_REQUEUE_PI)) {
if (copy_from_user(&ts, utime, sizeof(ts)) != 0)
return -EFAULT;
if (!timespec_valid(&ts))
return -EINVAL;
t = timespec_to_ktime(ts);
if (cmd == FUTEX_WAIT)
t = ktime_add_safe(ktime_get(), t);
tp = &t;
}
/*
* requeue parameter in ‘utime’ if cmd == FUTEX_*_REQUEUE_*.
* number of waiters to wake in ‘utime’ if cmd == FUTEX_WAKE_OP.
*/
if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE ||
cmd == FUTEX_CMP_REQUEUE_PI || cmd == FUTEX_WAKE_OP)
val2 = (u32) (unsigned long) utime;
return do_futex(uaddr, op, val, tp, uaddr2, val2, val3);
}
futex具有六個(gè)形參,pthread_mutex_lock最終只關(guān)注了前四個(gè)。futex函數(shù)對(duì)參數(shù)進(jìn)行判斷和轉(zhuǎn)化之后,直接調(diào)用do_futex。
long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
u32 __user *uaddr2, u32 val2, u32 val3)
{
int clockrt, ret = -ENOSYS;
int cmd = op & FUTEX_CMD_MASK;
int fshared = 0;
if (!(op & FUTEX_PRIVATE_FLAG))
fshared = 1;
clockrt = op & FUTEX_CLOCK_REALTIME;
if (clockrt && cmd != FUTEX_WAIT_BITSET && cmd != FUTEX_WAIT_REQUEUE_PI)
return -ENOSYS;
switch (cmd) {
case FUTEX_WAIT:
val3 = FUTEX_BITSET_MATCH_ANY;
case FUTEX_WAIT_BITSET:
ret = futex_wait(uaddr, fshared, val, timeout, val3, clockrt);
break;
…
default:
ret = -ENOSYS;
}
return ret;
}
省略部分為對(duì)其他cmd的處理,pthread_mutex_lock函數(shù)最終傳入的cmd參數(shù)為FUTEX_WAIT,所以在此只關(guān)注此分之,分析futex_wait函數(shù)的實(shí)現(xiàn)。
static int futex_wait(u32 __user *uaddr, int fshared,
u32 val, ktime_t *abs_time, u32 bitset, int clockrt)
{
struct hrtimer_sleeper timeout, *to = NULL;
struct restart_block *restart;
struct futex_hash_bucket *hb;
struct futex_q q;
int ret;
… … //delete parameters check and convertion
retry:
/* Prepare to wait on uaddr. */
ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);
if (ret)
goto out;
/* queue_me and wait for wakeup, timeout, or a signal. */
futex_wait_queue_me(hb, &q, to);
… … //other handlers
return ret;
}
futex_wait_setup 將線(xiàn)程放進(jìn)休眠隊(duì)列中,
futex_wait_queue_me(hb, &q, to);將本線(xiàn)程休眠,等待喚醒。
喚醒后,__lll_lock_wait函數(shù)中的while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0); 語(yǔ)句將被執(zhí)行,由于此時(shí)futex在pthread_mutex_unlock中置為0,所以atomic_compare_and_exchange_bool_acq (futex, 2, 0)語(yǔ)句將futex置為2,返回0. 退出循環(huán),訪(fǎng)問(wèn)用戶(hù)控件的臨界資源。
/*nptl/pthread_mutex_unlock.c*/
int
internal_function attribute_hidden
__pthread_mutex_unlock_usercnt (mutex, decr)
pthread_mutex_t *mutex;
int decr;
{
switch (__builtin_expect (mutex->__data.__kind, PTHREAD_MUTEX_TIMED_NP))
{
… …
default:
/* Correct code cannot set any other type. */
case PTHREAD_MUTEX_TIMED_NP:
case PTHREAD_MUTEX_ADAPTIVE_NP:
/* Normal mutex. Nothing special to do. */
break;
}
/* Always reset the owner field. */
mutex->__data.__owner = 0;
if (decr)
/* One less user. */
mutex->__data.__nusers;
/* Unlock. */
lll_mutex_unlock (mutex->__data.__lock);
return 0;
}
省略部分是針對(duì)不同的__kind屬性值做的一些處理,最終調(diào)用 lll_mutex_unlock。
該宏函數(shù)最終的定義為:
#define __lll_mutex_unlock(futex)\
((void) ({ \
int *__futex = (futex); \
int __val = atomic_exchange_rel (__futex, 0);\
\
if (__builtin_expect (__val > 1, 0)) \
lll_futex_wake (__futex, 1);\
}))
atomic_exchange_rel (__futex, 0);宏為:
#define atomic_exchange_rel(mem, value) \
(__sync_synchronize (), __sync_lock_test_and_set (mem, value))
實(shí)現(xiàn)功能為:將mem設(shè)置為value,返回原始mem值。
__builtin_expect (__val > 1, 0) 是編譯器優(yōu)化語(yǔ)句,告訴編譯器期望值,也就是大多數(shù)情況下__val > 1 ?是0,其邏輯判斷依然為if(__val > 1)為真的話(huà)執(zhí)行 lll_futex_wake。
現(xiàn)在分析,在資源沒(méi)有被競(jìng)爭(zhēng)的情況下,__futex 為1,那么返回值__val則為1,那么 lll_futex_wake (__futex, 1);不會(huì)被執(zhí)行,不產(chǎn)生系統(tǒng)調(diào)用。 當(dāng)資源產(chǎn)生競(jìng)爭(zhēng)的情況時(shí),根據(jù)對(duì)pthread_mutex_lock 函數(shù)的分析,__futex為2, __val則為2,執(zhí)行 lll_futex_wake (__futex, 1); 從而喚醒等在臨界資源的線(xiàn)程。
lll_futex_wake (__futex, 1); 最終會(huì)調(diào)動(dòng)同一個(gè)系統(tǒng)調(diào)用,即futex, 只是傳遞的cmd參數(shù)為FUTEX_WAKE。
在linux kernel的futex實(shí)現(xiàn)中,調(diào)用
static int futex_wake(u32 __user *uaddr, int fshared, int nr_wake, u32 bitset)
{
struct futex_hash_bucket *hb;
struct futex_q *this, *next;
struct plist_head *head;
union futex_key key = FUTEX_KEY_INIT;
int ret;
if (!bitset)
return -EINVAL;
ret = get_futex_key(uaddr, fshared, &key);
if (unlikely(ret != 0))
goto out;
hb = hash_futex(&key);
spin_lock(&hb->lock);
head = &hb->chain;
plist_for_each_entry_safe(this, next, head, list) {
if (match_futex (&this->key, &key)) {
if (this->pi_state || this->rt_waiter) {
ret = -EINVAL;
break;
}
/* Check if one of the bits is set in both bitsets */
if (!(this->bitset & bitset))
continue;
wake_futex(this);
if (++ret >= nr_wake)
break;
}
}
spin_unlock(&hb->lock);
put_futex_key(fshared, &key);
out:
return ret;
}
該函數(shù)遍歷在該mutex上休眠的所有線(xiàn)程,調(diào)用wake_futex進(jìn)行喚醒,
static void wake_futex(struct futex_q *q)
{
struct task_struct *p = q->task;
/*
* We set q->lock_ptr = NULL _before_ we wake up the task. If
* a non futex wake up happens on another CPU then the task
* might exit and p would dereference a non existing task
* struct. Prevent this by holding a reference on p across the
* wake up.
*/
get_task_struct(p);
plist_del(&q->list, &q->list.plist);
/*
* The waiting task can free the futex_q as soon as
* q->lock_ptr = NULL is written, without taking any locks. A
* memory barrier is required here to prevent the following
* store to lock_ptr from getting ahead of the plist_del.
*/
p_wmb();
q->lock_ptr = NULL;
wake_up_state(p, TASK_NORMAL);
put_task_struct(p);
}
關(guān)于linux 3.10.0源碼的介紹到此就結(jié)束了,不知道你從中找到你需要的信息了嗎 ?如果你還想了解更多這方面的信息,記得收藏關(guān)注本站。
創(chuàng)新互聯(lián)【028-86922220】值得信賴(lài)的成都網(wǎng)站建設(shè)公司。多年持續(xù)為眾多企業(yè)提供成都網(wǎng)站建設(shè),成都品牌建站設(shè)計(jì),成都高端網(wǎng)站制作開(kāi)發(fā),SEO優(yōu)化排名推廣服務(wù),全網(wǎng)營(yíng)銷(xiāo)讓企業(yè)網(wǎng)站產(chǎn)生價(jià)值。
網(wǎng)站名稱(chēng):深入探究Linux3.10.0源碼,窺探內(nèi)核的奧秘(linux3.10.0源碼)
網(wǎng)頁(yè)URL:http://m.fisionsoft.com.cn/article/djgpooi.html


咨詢(xún)
建站咨詢(xún)
