主頁 > 作業系統 > linux內核分析———SLAB原理及實作

linux內核分析———SLAB原理及實作

2020-09-12 02:53:18 作業系統

linux內核分析———SLAB原理及實作

Slab原理及實作

1. 整體關系圖

!

注:SLAB,SLOB,SLUB都是內核提供的分配器,其前端介面都是一致的,其中SLAB是通用的分配器,SLOB針對微小的嵌入式系統,其演算法較為簡單(最先適配演算法),SLUB是面向配備大量物理記憶體的大規模并行系統,通過也描述符中未使用的欄位來管理頁組,降低SLUB本身資料結構的記憶體開銷,

2. 相關資料結構

2.1 快取kmem_cache (/mm/slab.c)

struct kmem_cache {

struct array_cache *array[NR_CPUS];

unsigned int batchcount;//從本地高速快取交換的物件的數量

unsigned int limit;//本地高速快取中空閑物件的數量

unsigned int shared;//是否存在共享CPU高速快取

unsigned int buffer_size;//物件長度+填充位元組

u32 reciprocal_buffer_size;//倒數,加快計算



unsigned int flags;/*高速快取永久性的標志,當前只CFLGS_OFF_SLAB*/

unsigned int num;/*封裝在一個單獨的slab中的物件數目*/

unsigned int gfporder;/*每個slab包含的頁框數取2為底的對數*/



gfp_t gfpflags;/* e.g. GFP_DMA分配頁框是傳遞給伙伴系統的標志*/

size_t colour; /* cache colouring range快取的顏色個數free/aln*/



unsigned int colour_off;

/*slab的基本對齊偏移,為aln的整數倍,用來計算left_over*/



struct kmem_cache *slabp_cache;

//slab描述符放在外部時使用,其指向的高速快取來存盤描述符

unsigned int slab_size;//單個slab頭的大小,包括SLAB和物件描述符

unsigned int dflags; /*描述高速快取動態屬性,目前沒用*/



/*建構式*/

void(*ctor)(struct kmem_cache *, void *);

const char *name;

struct list_head next;//高速快取描述符雙向鏈表指標



/*統計量*/

#if STATS

unsigned long num_active;

unsigned long num_allocations;

unsigned long high_mark;

unsigned long grown;

unsigned long reaped;

unsigned long errors;

unsigned long max_freeable;

unsignedlong node_allocs;

unsigned long node_frees;

unsigned long node_overflow;

atomic_t allochit;

atomic_t allocmiss;

atomic_t freehit;

atomic_t freemiss;

#endif

#if DEBUG

into bj_offset;//物件間的偏移

int obj_size;//物件本身的大小,

#endif

//存放的是所有節點對應的相關資料,每個節點擁有各自的資料;

struc tkmem_list3 *nodelists[MAX_NUMNODES];/

}

2.2 array_cache本地高速快取,每個CPU對應一個該結構

/*

* struct array_cache

*

*Purpose:

* - LIFO ordering, to hand out cache-warm objectsfrom _alloc

* - reduce the number of linked list operations

* - reduce spinlock operations

*

* The limit is stored in the per-cpu structure toreduce the data cache

* footprint.

*

*/

struct array_cache {

unsigned int avail;//可用物件數目

unsigned int limit;//可擁有的最大物件數目,和kmem_cache中一樣

unsigned int batchcount;//同kmem_cache

unsigned int touched;//是否在收縮后被訪問過

spinlock_t lock;

void *entry[]; /*偽陣列,沒有任何資料項,其后為釋放的物件指標陣列*/

};

2.3 kmem_list3管理slab鏈表的資料結構

/*

* The slab lists for all objects.

*/

struct kmem_list3 {

struct list_head slabs_partial; /* partial listfirst, better asm code */

struct list_head slabs_full;

struct list_head slabs_free;

unsigned long free_objects;//半空和全空鏈表中物件的個數

unsigned int free_limit;//所有slab上允許未使用的物件最大數目

unsigned int colour_next; /* 下一個slab的顏色*/

spinlock_t list_lock;

struct array_cache *shared; /* shared per node */

struct array_cache **alien; /* on other nodes */

unsigned long next_reap; /* 兩次快取收縮時的間隔,降低次數,提高性能*/

int free_touched; /* 0收縮1獲取一個物件*/

};

2.4 slab物件

struct slab {

struct list_head list;//SLAB所在的鏈表

unsigned long colouroff;//SLAB中第一個物件的偏移

void *s_mem; /* including colour offset 第一個物件的地址*/

unsigned int inuse; /* num of objs active in slab被使用的物件數目*/

kmem_bufctl_t free;//下一個空閑物件的下標

unsigned short nodeid;//用于尋址在高速快取中kmem_list3的下標

};


3. 相關函式

3.1 kmem_cache_create (mm/slab.c)

/**

* kmem_cache_create - Create a cache.

* @name: A string which is used in /proc/slabinfo toidentify this cache.

* @size: The size of objects to be created in thiscache.

* @align: The required alignment for the objects.

* @flags: SLAB flags

* @ctor: A constructor for the objects.

*

* Returns a ptr to the cache on success, NULL onfailure.

* Cannot be calledwithin a int, but can be interrupted.

* The @ctor is run when new pages are allocated bythe cache.



struct kmem_cache *

kmem_cache_create (const char *name, size_t size,size_t align,unsigned long flags,

void (*ctor)(struct kmem_cache *, void *))

{

size_t left_over, slab_size, ralign;

struct kmem_cache *cachep = NULL, *pc;

/*引數有效性檢查,名字有效性,物件長度比處理器字長還短,或者超過了允許分配的最大值,不能處在中斷背景關系,可能導致睡眠*/

if (!name || in_interrupt() || (size <BYTES_PER_WORD) ||

size > KMALLOC_MAX_SIZE) {

printk(KERN_ERR "%s: Early error in slab%s\n", __FUNCTION__,

name);

BUG();

}



/*獲得鎖*/

mutex_lock(&cache_chain_mutex);

....

/*

將大小舍入到處理器字長的倍數

*/

if (size & (BYTES_PER_WORD - 1)) {

size += (BYTES_PER_WORD - 1);

size &= ~(BYTES_PER_WORD - 1);

}



/* 計算對齊值*/



//如果設定了該標志,則用硬體快取行

if (flags & SLAB_HWCACHE_ALIGN) {

ralign = cache_line_size();//獲得硬體快取行

//如果物件足夠小,則將對齊值減半,,盡可能增加單行物件數目

while (size <= ralign )

ralign /= 2;

} else {//否則使用處理器字長

ralign = BYTES_PER_WORD;

}



/*體系結構強制最小值*/

if (ralign < ARCH_SLAB_MINALIGN) {

ralign = ARCH_SLAB_MINALIGN;

}

/*呼叫者強制對齊值*/

if (ralign < align) {

ralign = align;

}

/*計算出對齊值.*/

align = ralign;







/*從cache_cache快取中分配一個kmem_cache新實體*/

cachep = kmem_cache_zalloc(&cache_cache,GFP_KERNEL);

//填充cachep成員

cachep->obj_size = size;//將填充后的物件賦值,





//設定SLAB頭位置

//如果物件大小超過一頁的1/8則放在外部

if ((size >= (PAGE_SIZE >> 3)) &&!slab_early_init)

flags |= CFLGS_OFF_SLAB;//設定將SLAB放在外部

size = ALIGN(size, align);//按對齊大小對齊



//計算快取長度

//利用calculate_slab_order迭代來找到理想的slab長度,size指物件的長度

left_over = calculate_slab_order(cachep, size,align, flags);



if (!cachep->num) {//NUM指SLAB物件的數目

printk(KERN_ERR

"kmem_cache_create: couldn't createcache %s.\n", name);

kmem_cache_free(&cache_cache, cachep);

cachep = NULL;

goto oops;

}



//再次計算SLAB頭存放位置

//計算slab頭的大小=物件的數目x物件描述符的大小+slab描述符

slab_size = ALIGN(cachep->num *sizeof(kmem_bufctl_t)

+ sizeof(struct slab), align);



//如果有足夠的空間,容納SLAB頭則將其放在SLAB上

if (flags & CFLGS_OFF_SLAB && left_over>= slab_size) {

flags &= ~CFLGS_OFF_SLAB;

left_over -= slab_size;

}

//如果標志仍然存在,則計算外部的slab頭大小

if (flags & CFLGS_OFF_SLAB) {

/* 此處不用對齊了*/

slab_size =

cachep->num * sizeof(kmem_bufctl_t) +sizeof(struct slab);

}



//著色

cachep->colour_off =cache_line_size();//

/* Offset must be a multiple of the alignment. */

if (cachep->colour_off< align)

cachep->colour_off = align;

cachep->colour = left_over /cachep->colour_off;//獲取顏色值

cachep->slab_size = slab_size;

cachep->flags = flags;

cachep->gfpflags = 0; //分配頁框的標志

if (CONFIG_ZONE_DMA_FLAG && (flags &SLAB_CACHE_DMA))

cachep->gfpflags |= GFP_DMA;

cachep->buffer_size = size;

cachep->reciprocal_buffer_size =reciprocal_value(size);

//如果在SLAB頭在外部,則找一個合適的快取指向slabp_cache,從通用快取中

if (flags & CFLGS_OFF_SLAB) {

cachep->slabp_cache= kmem_find_general_cachep(slab_size, 0u);

BUG_ON(ZERO_OR_NULL_PTR(cachep->slabp_cache));

}

cachep->ctor = ctor;

cachep->name = name;



//設定per-cpu快取

if (setup_cpu_cache(cachep)){

__kmem_cache_destroy(cachep);

cachep = NULL;

goto oops;

}



/* 加入鏈表*/

list_add(&cachep->next, &cache_chain);

/*解鎖*/

mutex_unlock(&cache_chain_mutex);

return cachep;

}

3.2 物件分配函式kmem_cache_alloc(kmem_cache_t* cachep, gfp_t flags)

static inline void *____cache_alloc(struct kmem_cache *cachep,gfp_t flags)

{

void *objp;

struct array_cache *ac;



check_irq_off();



ac = cpu_cache_get(cachep);//獲得高速快取中CPU快取

if (likely(ac->avail)) {//如果CPU快取中還有空間,則從中分配

STATS_INC_ALLOCHIT(cachep);

ac->touched = 1;

objp = ac->entry[--ac->avail];

} else {//否則要填充CPU高速快取了

STATS_INC_ALLOCMISS(cachep);

objp = cache_alloc_refill(cachep,flags);

}

return objp;

}
//填充CPU高速快取

static void *cache_alloc_refill(structkmem_cache *cachep, gfp_t flags)

{

int batchcount;

struct kmem_list3 *l3;

struct array_cache *ac;

int node;

ac = cpu_cache_get(cachep);//獲得高所快取所在本地CPU快取

retry:

batchcount = ac->batchcount;

if (!ac->touched && batchcount > BATCHREFILL_LIMIT){

/*如果不經常活動,則部分填充*/

batchcount = BATCHREFILL_LIMIT;//16

}

l3 = cachep->nodelists[node];//獲得相應的kmem_list3結構體

...

/* 先考慮從共享本地CPU高速快取*/

if (l3->shared && transfer_objects(ac, l3->shared,batchcount))

goto alloc_done;



while (batchcount > 0) {//老老實實的從本高速快取分配

struct list_head *entry;

struct slab *slabp;

/* Get slab alloc is to come from. */

entry = l3->slabs_partial.next;//半滿的鏈表

if (entry == &l3->slabs_partial) {//如果半空的都沒了,找全空的

l3->free_touched = 1;

entry = l3->slabs_free.next;

if (entry == &l3->slabs_free)//全空的也沒了,必須擴充了

cache_grow(cachep, flags | GFP_THISNODE, node, NULL);

}

//此時,已經找到了一個鏈表(半慷訓者全空)

slabp = list_entry(entry, struct slab, list);//找到一個slab

check_slabp(cachep, slabp);

check_spinlock_acquired(cachep);

while (slabp->inuse < cachep->num &&batchcount--)

{//回圈從slab中分配物件

ac->entry[ac->avail++] =slab_get_obj(cachep, slabp,node);

}

check_slabp(cachep, slabp);



/*將slab放到合適的鏈中:*/

list_del(&slabp->list);

if (slabp->free == BUFCTL_END)//如果已經沒有空閑物件了,則放到滿鏈表中

list_add(&slabp->list, &l3->slabs_full);

else//否則放在半滿鏈表

list_add(&slabp->list, &l3->slabs_partial);

}

...

ac->touched = 1;

return ac->entry[--ac->avail];

}

//按次序從SLAB中起初物件

static void *slab_get_obj(struct kmem_cache *cachep, struct slab*slabp,

int nodeid)

{

void *objp =index_to_obj(cachep, slabp, slabp->free);//找到要找的物件

kmem_bufctl_t next;

slabp->inuse++;//增加計數器

next =slab_bufctl(slabp)[slabp->free];

//獲得slab_bufctl[slab->free]的值,為下一次鎖定的空閑下標

slabp->free =next;//將鎖定下標放到free中

return objp;

}

3.4 cache_grow

//增加新的SLAB

static int cache_grow(structkmem_cache *cachep, gfp_t flags, int nodeid, void *objp)

{

struct slab *slabp;

size_t offset;

gfp_t local_flags;

struct kmem_list3 *l3;

...

l3 = cachep->nodelists[nodeid];

...

/* 計算偏移量和下一個顏色.*/

offset = l3->colour_next;//計算下一個顏色

l3->colour_next++;//如果到了最大值則回0

if (l3->colour_next >= cachep->colour)

l3->colour_next = 0;

offset *= cachep->colour_off;//計算此SLAB的偏移



//從伙伴系統獲得物理頁

objp = kmem_getpages(cachep, local_flags, nodeid);

...

/* 如果slab頭放在外部,則呼叫此函式分配函式*/

slabp = alloc_slabmgmt(cachep, objp, offset,

local_flags & ~GFP_CONSTRAINT_MASK, nodeid);

slabp->nodeid = nodeid;//在kmem_cache中陣列的下標

//依次對每個物理頁的lru.next=cache,lru.prev=slab

slab_map_pages(cachep, slabp, objp);

//呼叫各個物件的構造器函式,初始化新SLAB中的物件

cache_init_objs(cachep, slabp);

/* 將新的SLAB加入到全空鏈表中*/

list_add_tail(&slabp->list, &(l3->slabs_free));

STATS_INC_GROWN(cachep);

l3->free_objects += cachep->num;//更新空閑物件的數目

...

return 0;

}

3.5 釋放物件kmem_cache_free

//真正的處理函式

static inline void __cache_free(struct kmem_cache *cachep, void*objp)

{

struct array_cache *ac = cpu_cache_get(cachep);

...



if (likely(ac->avail < ac->limit)){//如果CPU高速快取還有位子,則直接釋放

ac->entry[ac->avail++] = objp;

return;

} else {//否則需要將部分物件FLUSH到SLAB中了

STATS_INC_FREEMISS(cachep);

cache_flusharray(cachep, ac);

ac->entry[ac->avail++] = objp;

}

}
//將部分CPU高速快取FLUSH到SLAB中

static void cache_flusharray(struct kmem_cache *cachep, structarray_cache *ac)

{

int batchcount;

struct kmem_list3 *l3;

int node = numa_node_id();



batchcount = ac->batchcount;//指定數量

l3 = cachep->nodelists[node];

if (l3->shared) {//如果共享CPU快取存在,則將共享快取填滿,然后回傳

struct array_cache *shared_array = l3->shared;

int max = shared_array->limit - shared_array->avail;

if (max) {//

if (batchcount > max)

batchcount = max;

//這里只是拷貝,并沒有移除

memcpy(&(shared_array->entry[shared_array->avail]),

ac->entry, sizeof(void *) * batchcount);

shared_array->avail += batchcount;

goto free_done;

}

}

//否則需要釋放到SLAB中了

free_block(cachep,ac->entry, batchcount, node);

free_done:

//對CPU高速快取進行移除操作

spin_unlock(&l3->list_lock);

ac->avail -= batchcount;

memmove(ac->entry, &(ac->entry[batchcount]),sizeof(void *)*ac->avail);

}

//將nr_objects個物件釋放到SLAB中,objpp指CPU快取陣列

static void free_block(struct kmem_cache *cachep, void **objpp,int nr_objects, int node)

{

int i;

struct kmem_list3 *l3;



for (i = 0; i < nr_objects; i++) {//對每一個物件處理,先從頭部處理,LIFO

void *objp = objpp[i];

struct slab *slabp;



slabp = virt_to_slab(objp);//獲得SLAB描述符

l3 = cachep->nodelists[node];

list_del(&slabp->list);//將SLAB從原來的鏈表中洗掉

check_spinlock_acquired_node(cachep, node);

check_slabp(cachep, slabp);

slab_put_obj(cachep, slabp, objp,node);//將objp放到slab中,和slab_get_obj相反

STATS_DEC_ACTIVE(cachep);

l3->free_objects++;//增加高速快取的可用物件數目

check_slabp(cachep, slabp);



/*將SLAB重新插入鏈表*/

if (slabp->inuse == 0) {//如果SLAB是全空的

if (l3->free_objects > l3->free_limit)

{//并且高速快取空閑物件已經超出限制,則需要將SLAB回傳給底層頁框管理器

l3->free_objects -= cachep->num;

slab_destroy(cachep, slabp);

} else {//直接插入空閑鏈表

list_add(&slabp->list, &l3->slabs_free);

}

} else {//直接插入部分空閑鏈表

list_add_tail(&slabp->list, &l3->slabs_partial);

}

}

}

3.5 高速快取的銷毀kmem_cache_destroy,此函式用在模塊卸載時使用,釋放以前分配的空間

4. 通用快取

即kmalloc和kfree使用的,放在malloc_size表中,從32-33554432共21個成員,成員的結構如

/* Size description struct for general caches. */

struct cache_sizes {

size_t cs_size;//物件大小

struct kmem_cache *cs_cachep;//對應的高速快取

struct kmem_cache *cs_dmacachep;//對應的DMA訪問快取

};
//通用高速快取在/kmalloc_sizes.h

struct cache_sizes malloc_sizes[] = {

#define CACHE(x) { .cs_size = (x) },

#include <linux/kmalloc_sizes.h>

CACHE(ULONG_MAX)

#undef CACHE

};

Kmalloc_sizes.h

#if (PAGE_SIZE == 4096)

CACHE(32)

#endif

CACHE(64)

#if L1_CACHE_BYTES < 64

CACHE(96)

#endif

CACHE(128)

#if L1_CACHE_BYTES < 128

CACHE(192)

#endif

CACHE(256)

CACHE(512)

CACHE(1024)

CACHE(2048)

CACHE(4096)

CACHE(8192)

CACHE(16384)

CACHE(32768)

CACHE(65536)

CACHE(131072)

#if KMALLOC_MAX_SIZE >= 262144

CACHE(262144)

#endif

#if KMALLOC_MAX_SIZE >= 524288

CACHE(524288)

#endif

#if KMALLOC_MAX_SIZE >= 1048576

CACHE(1048576)

#endif

#if KMALLOC_MAX_SIZE >= 2097152

CACHE(2097152)

#endif

#if KMALLOC_MAX_SIZE >= 4194304

CACHE(4194304)

#endif

#if KMALLOC_MAX_SIZE >= 8388608

CACHE(8388608)

#endif

#if KMALLOC_MAX_SIZE >= 16777216

CACHE(16777216)

#endif

#if KMALLOC_MAX_SIZE >= 33554432

CACHE(33554432)

#endif

4.1 kalloc函式

//分配函式

static inline void *kmalloc(size_t size, gfp_t flags)

{

if (__builtin_constant_p(size))

{//是否用常數指定所需的記憶體長度

int i = 0;

//找到合適大小的i值

...

//按型別進行分配

#ifdef CONFIG_ZONE_DMA

if (flags & GFP_DMA)

return kmem_cache_alloc(malloc_sizes[i].cs_dmacachep,

flags);

#endif

return kmem_cache_alloc(malloc_sizes[i].cs_cachep, flags);

}//不使用常數指定

return __kmalloc(size, flags);

}
//大小不用指定的分配

static __always_inline void *__do_kmalloc(size_t size, gfp_tflags, void *caller)

{

struct kmem_cache *cachep;

cachep = __find_general_cachep(size, flags);//找一個合適大小的高速快取

if (unlikely(ZERO_OR_NULL_PTR(cachep)))

return cachep;

return __cache_alloc(cachep, flags, caller);//分配函式

}

4.2 釋放函式kfree

//kmalloc對應的釋放函式

void kfree(const void *objp)

{

struct kmem_cache *c;

unsigned long flags;

...

c =virt_to_cache(objp);//獲得高速快取

debug_check_no_locks_freed(objp, obj_size(c));

__cache_free(c, (void*)objp);//呼叫此函式完成實質性的分配

local_irq_restore(flags);

}

轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/9826.html

標籤:嵌入式

上一篇:初級模擬電路:4-4 re模型詳解

下一篇:微信小程式接入LeanCloud

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • CA和證書

    1、在 CentOS7 中使用 gpg 創建 RSA 非對稱密鑰對 gpg --gen-key #Centos上生成公鑰/密鑰對(存放在家目錄.gnupg/) 2、將 CentOS7 匯出的公鑰,拷貝到 CentOS8 中,在 CentOS8 中使用 CentOS7 的公鑰加密一個檔案 gpg -a ......

    uj5u.com 2020-09-10 00:09:53 more
  • Kubernetes K8S之資源控制器Job和CronJob詳解

    Kubernetes的資源控制器Job和CronJob詳解與示例 ......

    uj5u.com 2020-09-10 00:10:45 more
  • VMware下安裝CentOS

    VMware下安裝CentOS 一、軟硬體準備 1 Centos鏡像準備 1.1 CentOS鏡像下載地址 下載地址 1.2 CentOS鏡像下載程序 點擊下載地址進入如下圖的網站,選擇需要下載的版本,這里選擇的是Centos8,點擊如圖所示。 決定選擇Centos8后,選擇想要的鏡像源進行下載,此 ......

    uj5u.com 2020-09-10 00:12:10 more
  • 如何使用Grep命令查找多個字串

    如何使用Grep 命令查找多個字串 大家好,我是良許! 今天向大家介紹一個非常有用的技巧,那就是使用 grep 命令查找多個字串。 簡單介紹一下,grep 命令可以理解為是一個功能強大的命令列工具,可以用它在一個或多個輸入檔案中搜索與正則運算式相匹配的文本,然后再將每個匹配的文本用標準輸出的格式 ......

    uj5u.com 2020-09-10 00:12:28 more
  • git配置http代理

    git配置http代理 經常遇到克隆 github 慢的問題,這里記錄一下幾種配置 git 代理的方法,解決 clone github 過慢。 目錄 git配置代理 git單獨配置github代理 git配置全域代理 配置終端環境變數 git配置代理 主要使用 git config 命令 git單獨 ......

    uj5u.com 2020-09-10 00:12:33 more
  • Linux npm install 裝包時提示Error EACCES permission denied解

    npm install 裝包時提示Error EACCES permission denied解決辦法 ......

    uj5u.com 2020-09-10 00:12:53 more
  • Centos 7下安裝nginx,使用yum install nginx,提示沒有可用的軟體包

    Centos 7下安裝nginx,使用yum install nginx,提示沒有可用的軟體包。 18 (flaskApi) [root@67 flaskDemo]# yum -y install nginx 19 已加載插件:fastestmirror, langpacks 20 Loading ......

    uj5u.com 2020-09-10 00:13:13 more
  • Linux查看服務器暴力破解ssh IP

    在公網的服務器上經常遇到別人爆破你服務器的22埠,用來挖礦或者干其他嘿嘿嘿的事情~ 這種情況下正確的做法是: 修改默認ssh的22埠 使用設定密鑰登錄或者白名單ip登錄 建議服務器密碼為復雜密碼 創建普通用戶登錄服務器(root權限過大) 建立堡壘機,實作統一管理服務器 統計爆破IP [root ......

    uj5u.com 2020-09-10 00:13:17 more
  • CentOS 7系統常見快捷鍵操作方式

    Linux系統中一些常見的快捷方式,可有效提高操作效率,在某些時刻也能避免操作失誤帶來的問題。 ......

    uj5u.com 2020-09-10 00:13:31 more
  • CentOS 7作業系統目錄結構介紹

    作業系統存在著大量的資料檔案資訊,相應檔案資訊會存在于系統相應目錄中,為了更好的管理資料資訊,會將系統進行一些目錄規劃,不同目錄存放不同的資源。 ......

    uj5u.com 2020-09-10 00:13:35 more
最新发布
  • vim的常用命令

    Vim的6種基本模式 1. 普通模式在普通模式中,用的編輯器命令,比如移動游標,洗掉文本等等。這也是Vim啟動后的默認模式。這正好和許多新用戶期待的操作方式相反(大多數編輯器默認模式為插入模式)。 2. 插入模式在這個模式中,大多數按鍵都會向文本緩沖中插入文本。大多數新用戶希望文本編輯器編輯程序中一 ......

    uj5u.com 2023-04-20 08:43:21 more
  • vim的常用命令

    Vim的6種基本模式 1. 普通模式在普通模式中,用的編輯器命令,比如移動游標,洗掉文本等等。這也是Vim啟動后的默認模式。這正好和許多新用戶期待的操作方式相反(大多數編輯器默認模式為插入模式)。 2. 插入模式在這個模式中,大多數按鍵都會向文本緩沖中插入文本。大多數新用戶希望文本編輯器編輯程序中一 ......

    uj5u.com 2023-04-20 08:42:36 more
  • docker學習

    ###Docker概述 真實專案部署環境可能非常復雜,傳統發布專案一個只需要一個jar包,運行環境需要單獨部署。而通過Docker可將jar包和相關環境(如jdk,redis,Hadoop...)等打包到docker鏡像里,將鏡像發布到Docker倉庫,部署時下載發布的鏡像,直接運行發布的鏡像即可。 ......

    uj5u.com 2023-04-19 09:26:53 more
  • 設定Windows主機的瀏覽器為wls2的默認瀏覽器

    這里以Chrome為例。 1. 準備作業 wsl是可以使用Windows主機上安裝的exe程式,出于安全考慮,默認情況下改功能是無法使用。要使用的話,終端需要以管理員權限啟動。 我這里以Windows Terminal為例,介紹如何默認使用管理員權限打開終端,具體操作如下圖所示: 2. 操作 wsl ......

    uj5u.com 2023-04-19 09:25:49 more
  • docker學習

    ###Docker概述 真實專案部署環境可能非常復雜,傳統發布專案一個只需要一個jar包,運行環境需要單獨部署。而通過Docker可將jar包和相關環境(如jdk,redis,Hadoop...)等打包到docker鏡像里,將鏡像發布到Docker倉庫,部署時下載發布的鏡像,直接運行發布的鏡像即可。 ......

    uj5u.com 2023-04-19 09:19:04 more
  • Linux學習筆記

    IP地址和主機名 IP地址 ifconfig可以用來查詢本機的IP地址,如果不能使用,可以通過install net-tools安裝。 Centos系統下ens33表示主網卡;inet后表示IP地址;lo表示本地回環網卡; 127.0.0.1表示代指本機;0.0.0.0可以用于代指本機,同時在放行設 ......

    uj5u.com 2023-04-18 06:52:01 more
  • 解決linux系統的kdump服務無法啟動的問題

    問題:專案麒麟系統服務器的kdump服務無法啟動,沒有相關日志無法定位問題。 1、查看服務狀態是關閉的,重啟系統也無法啟動 systemctl status kdump 2、修改grub引數,修改“crashkernel”為“512M(有的機器數值太大太小都會導致報錯,建議從128M開始試,或者加個 ......

    uj5u.com 2023-04-12 09:59:50 more
  • 解決linux系統的kdump服務無法啟動的問題

    問題:專案麒麟系統服務器的kdump服務無法啟動,沒有相關日志無法定位問題。 1、查看服務狀態是關閉的,重啟系統也無法啟動 systemctl status kdump 2、修改grub引數,修改“crashkernel”為“512M(有的機器數值太大太小都會導致報錯,建議從128M開始試,或者加個 ......

    uj5u.com 2023-04-12 09:59:01 more
  • 你是不是暴露了?

    作者:袁首京 原創文章,轉載時請保留此宣告,并給出原文連接。 如果您是計算機相關從業人員,那么應該經歷不止一次網路安全專項檢查了,你肯定是收到過資訊系統技術檢測報告,要求你加強風險監測,確保你提供的系統服務堅實可靠了。 沒檢測到問題還好,檢測到問題的話,有些處理起來還是挺麻煩的,尤其是線上正在運行的 ......

    uj5u.com 2023-04-05 16:52:56 more
  • 細節拉滿,80 張圖帶你一步一步推演 slab 記憶體池的設計與實作

    1. 前文回顧 在之前的幾篇記憶體管理系列文章中,筆者帶大家從宏觀角度完整地梳理了一遍 Linux 記憶體分配的整個鏈路,本文的主題依然是記憶體分配,這一次我們會從微觀的角度來探秘一下 Linux 內核中用于零散小記憶體塊分配的記憶體池 —— slab 分配器。 在本小節中,筆者還是按照以往的風格先帶大家簡單 ......

    uj5u.com 2023-04-05 16:44:11 more