線程池原理及C語言實現線程池

備注:該線程池源碼參考自傳直播客培訓視頻配套資料;
源碼:https://pan.baidu.com/s/1zWuoE3q0KT5TUjmPKTb1lw 密碼:pp42
引言:線程池是一種多線程處理形式,大多用于高并發服務器上,它能合理有效的利用高并發服務器上的線程資源;

在Unix網絡編程中,線程與進程用于處理各項分支子功能,我們通常的操作是:接收消息 ==> 消息分類 ==> 線程創建 ==> 傳遞消息到子線程 ==> 線程分離 ==> 在子線程中執行任務 ==> 任務結束退出;
對大多數小型局域網的通信來說,上述方法足夠滿足需求;但當我們的通信范圍擴大到廣域網或大型局域網通信中時,我們將面臨大量消息頻繁請求服務器;在這種情況下,創建與銷毀線程都已經成為一種奢侈的開銷,特別對于嵌入式服務器來說更應保證內存資源的合理利用;
因此,線程池技術應運而生;線程池允許一個線程可以多次復用,且每次復用的線程內部的消息處理可以不相同,將創建與銷毀的開銷省去而不必來一個請求開一個線程;

結構講解:
線程池是一個抽象的概念,其內部由任務隊列,一堆線程,管理者線程組成;
這里寫圖片描述


我們將以上圖為例,實現一個最基礎的線程池,接下來將分部分依次講解;講解順序為:1.線程池總體結構 2.線程數組 3.任務隊列 4.管理者線程 5.使用線程池接口的例子
一、線程池總體結構

這里講解線程池在邏輯上的結構體;看下方代碼,該結構體threadpool_t中包含線程池狀態信息,任務隊列信息以及多線程操作中的互斥鎖;在任務結構體中包含了一個可以放置多種不同任務函數的函數指針,一個傳入該任務函數的void*類型的參數;
注意:在使用時需要將你的消息分類處理函數裝入任務的(*function);然后放置到任務隊列并通知空閑線程;

線程池狀態信息:描述當前線程池的基本信息,如是否開啟、最小線程數、最大線程數、存活線程數、忙線程數、待銷毀線程數等… …
任務隊列信息:描述當前任務隊列基本信息,如最大任務數、隊列不為滿條件變量、隊列不為空條件變量等… …
多線程互斥鎖:保證在同一時間點上只有一個線程在任務隊列中取任務并修改任務隊列信息、修改線程池信息;
函數指針:在打包消息階段,將分類后的消息處理函數放在(*function);
void*類型參數:用于傳遞消息處理函數需要的信息;

/*任務*/
typedef struct {
?? void *(*function)(void *);
?? void *arg;
} threadpool_task_t;

/*線程池管理*/
struct threadpool_t{
?? pthread_mutex_t lock;???????????????? /* 鎖住整個結構體 */
?? pthread_mutex_t thread_counter;?????? /* 用于使用忙線程數時的鎖 */
?? pthread_cond_t? queue_not_full;?????? /* 條件變量,任務隊列不為滿 */
?? pthread_cond_t? queue_not_empty;????? /* 任務隊列不為空 */

?? pthread_t *threads;?????????????????? /* 存放線程的tid,實際上就是管理了線 數組 */
?? pthread_t admin_tid;????????????????? /* 管理者線程tid */
?? threadpool_task_t *task_queue;??????? /* 任務隊列 */

?? /*線程池信息*/
?? int min_thr_num;????????????????????? /* 線程池中最小線程數 */
?? int max_thr_num;????????????????????? /* 線程池中最大線程數 */
?? int live_thr_num;???????????????????? /* 線程池中存活的線程數 */
?? int busy_thr_num;???????????????????? /* 忙線程,正在工作的線程 */
?? int wait_exit_thr_num;??????????????? /* 需要銷毀的線程數 */

?? /*任務隊列信息*/
?? int queue_front;????????????????????? /* 隊頭 */
?? int queue_rear;?????????????????????? /* 隊尾 */
?? int queue_size;

?? /* 存在的任務數 */
?? int queue_max_size;?????????????????? /* 隊列能容納的最大任務數 */
?? /*線程池狀態*/
?? int shutdown;???????????????????????? /* true為關閉 */
};

???

**/*創建線程池*/**
threadpool_t *
threadpool_create(int min_thr_num, int max_thr_num, int queue_max_size)
{?????????????? /*? 最小線程數?????????? 最大線程數???????? 最大任務數*/
?? int i;
?? threadpool_t *pool = NULL;
?? do
?? {
????? /* 線程池空間開辟 */
????? if ((pool=(threadpool_t *)malloc(sizeof(threadpool_t))) == NULL)
????? {
??????? printf("malloc threadpool false; \n");
??????? break;? ?
????? }
????? /*信息初始化*/
????? pool->min_thr_num = min_thr_num;
????? pool->max_thr_num = max_thr_num;
????? pool->busy_thr_num = 0;
????? pool->live_thr_num = min_thr_num;
????? pool->wait_exit_thr_num = 0;
????? pool->queue_front = 0;
????? pool->queue_rear = 0;
????? pool->queue_size = 0;
????? pool->queue_max_size = queue_max_size;
????? pool->shutdown = false;

????? /* 根據最大線程數,給工作線程數組開空間,清0 */
????? pool->threads = (pthread_t *)malloc(sizeof(pthread_t)*max_thr_num);
????? if (pool->threads == NULL)
????? {
???????? printf("malloc threads false;\n");
???????? break;
????? }
????? memset(pool->threads, 0, sizeof(pthread_t)*max_thr_num);

????? /* 隊列開空間 */
????? pool->task_queue =
????? (threadpool_task_t *)malloc(sizeof(threadpool_task_t)*queue_max_size);
????? if (pool->task_queue == NULL)
????? {
???????? printf("malloc task queue false;\n");
???????? break;
????? }

????? /* 初始化互斥鎖和條件變量 */
????? if ( pthread_mutex_init(&(pool->lock), NULL) != 0?????????? ||
?????????? pthread_mutex_init(&(pool->thread_counter), NULL) !=0? ||
?????? pthread_cond_init(&(pool->queue_not_empty), NULL) !=0? ||
?????? pthread_cond_init(&(pool->queue_not_full), NULL) !=0)
????? {
???????? printf("init lock or cond false;\n");
???????? break;
????? }

????? /* 啟動min_thr_num個工作線程 */
????? for (i=0; i<min_thr_num; i++)
????? {
???????? /* pool指向當前線程池? threadpool_thread函數在后面講解 */
???????? pthread_create(&(pool->threads[i]), NULL, threadpool_thread, (void *)pool);
???????? printf("start thread 0x%x... \n", (unsigned int)pool->threads[i]);
????? }
????? /* 管理者線程 admin_thread函數在后面講解 */
????? pthread_create(&(pool->admin_tid), NULL, admin_thread, (void *)pool);

????? return pool;
?? } while(0);

?? /* 釋放pool的空間 */
?? threadpool_free(pool);
?? return NULL;
}

???

二、線程數組

線程數組實際上是在線程池初始化時開辟的一段存放一堆線程tid的空間,在邏輯上形成一個池,里面放置著提前創建的線程;這段空間中包含了正在工作的線程,等待工作的線程(空閑線程),等待被銷毀的線程,申明但沒有初始化的線程空間;
這里寫圖片描述

/*工作線程*/
void *
threadpool_thread(void *threadpool)
{
? threadpool_t *pool = (threadpool_t *)threadpool;
? threadpool_task_t task;

? while (true)
? {
??? pthread_mutex_lock(&(pool->lock));

??? /* 無任務則阻塞在 “任務隊列不為空” 上,有任務則跳出 */
??? while ((pool->queue_size == 0) && (!pool->shutdown))
??? {
?????? printf("thread 0x%x is waiting \n", (unsigned int)pthread_self());
?????? pthread_cond_wait(&(pool->queue_not_empty), &(pool->lock));

?????? /* 判斷是否需要清除線程,自殺功能 */
?????? if (pool->wait_exit_thr_num > 0)
?????? {
????????? pool->wait_exit_thr_num--;
????????? /* 判斷線程池中的線程數是否大于最小線程數,是則結束當前線程 */
????????? if (pool->live_thr_num > pool->min_thr_num)
????????? {
???????????? printf("thread 0x%x is exiting \n", (unsigned int)pthread_self());
???????????? pool->live_thr_num--;
???????????? pthread_mutex_unlock(&(pool->lock));
???????????? pthread_exit(NULL);//結束線程
????????? }
?????? }
??? }

??? /* 線程池開關狀態 */
??? if (pool->shutdown) //關閉線程池
??? {
?????? pthread_mutex_unlock(&(pool->lock));
?????? printf("thread 0x%x is exiting \n", (unsigned int)pthread_self());
?????? pthread_exit(NULL); //線程自己結束自己
??? }

??? //否則該線程可以拿出任務
??? task.function = pool->task_queue[pool->queue_front].function; //出隊操作
??? task.arg = pool->task_queue[pool->queue_front].arg;

??? pool->queue_front = (pool->queue_front + 1) % pool->queue_max_size;? //環型結構
??? pool->queue_size--;

??? //通知可以添加新任務
??? pthread_cond_broadcast(&(pool->queue_not_full));

??? //釋放線程鎖
??? pthread_mutex_unlock(&(pool->lock));

??? //執行剛才取出的任務
??? printf("thread 0x%x start working \n", (unsigned int)pthread_self());
??? pthread_mutex_lock(&(pool->thread_counter));??????????? //鎖住忙線程變量
??? pool->busy_thr_num++;
??? pthread_mutex_unlock(&(pool->thread_counter));

??? (*(task.function))(task.arg);?????????????????????????? //執行任務

??? //任務結束處理
??? printf("thread 0x%x end working \n", (unsigned int)pthread_self());
??? pthread_mutex_lock(&(pool->thread_counter));
??? pool->busy_thr_num--;
??? pthread_mutex_unlock(&(pool->thread_counter));
? }

? pthread_exit(NULL);
}

???

三、任務隊列

任務隊列的存在形式與線程數組相似;在線程池初始化時根據傳入的最大任務數開辟空間;當服務器前方后請求到來后,分類并打包消息成為任務,將任務放入任務隊列并通知空閑線程來取;不同之處在于任務隊列有明顯的先后順序,先進先出;而線程數組中的線程則是一個競爭關系去拿到互斥鎖爭取任務;
這里寫圖片描述

/*向線程池的任務隊列中添加一個任務*/
int
threadpool_add_task(threadpool_t *pool, void *(*function)(void *arg), void *arg)
{
?? pthread_mutex_lock(&(pool->lock));

?? /*如果隊列滿了,調用wait阻塞*/
?? while ((pool->queue_size == pool->queue_max_size) && (!pool->shutdown))
????? pthread_cond_wait(&(pool->queue_not_full), &(pool->lock));

?? /*如果線程池處于關閉狀態*/
?? if (pool->shutdown)
?? {
????? pthread_mutex_unlock(&(pool->lock));
????? return -1;
?? }

?? /*清空工作線程的回調函數的參數arg*/
?? if (pool->task_queue[pool->queue_rear].arg != NULL)
?? {
????? free(pool->task_queue[pool->queue_rear].arg);
????? pool->task_queue[pool->queue_rear].arg = NULL;
?? }

?? /*添加任務到任務隊列*/
?? pool->task_queue[pool->queue_rear].function = function;
?? pool->task_queue[pool->queue_rear].arg = arg;
?? pool->queue_rear = (pool->queue_rear + 1) % pool->queue_max_size;? /* 邏輯環? */
?? pool->queue_size++;

?? /*添加完任務后,隊列就不為空了,喚醒線程池中的一個線程*/
?? pthread_cond_signal(&(pool->queue_not_empty));
?? pthread_mutex_unlock(&(pool->lock));

?? return 0;
}

???

四、管理者線程

作為線程池的管理者,該線程的主要功能包括:檢查線程池內線程的存活狀態,工作狀態;負責根據服務器當前的請求狀態去動態的增加或刪除線程,保證線程池中的線程數量維持在一個合理高效的平衡上;
說到底,它就是一個單獨的線程,定時的去檢查,根據我們的一個維持平衡算法去增刪線程;

/*管理線程*/
void *
admin_thread(void *threadpool)
{
?? int i;
?? threadpool_t *pool = (threadpool_t *)threadpool;
?? while (!pool->shutdown)
?? {
????? printf("admin -----------------\n");
????? sleep(DEFAULT_TIME);???????????????????????????? /*隔一段時間再管理*/
????? pthread_mutex_lock(&(pool->lock));?????????????? /*加鎖*/
????? int queue_size = pool->queue_size;?????????????? /*任務數*/
????? int live_thr_num = pool->live_thr_num;?????????? /*存活的線程數*/
????? pthread_mutex_unlock(&(pool->lock));???????????? /*解鎖*/

????? pthread_mutex_lock(&(pool->thread_counter));
????? int busy_thr_num = pool->busy_thr_num;?????????? /*忙線程數*/ ?
????? pthread_mutex_unlock(&(pool->thread_counter));

????? printf("admin busy live -%d--%d-\n", busy_thr_num, live_thr_num);
????? /*創建新線程 實際任務數量大于 最小正在等待的任務數量,存活線程數小于最大線程數*/
????? if (queue_size >= MIN_WAIT_TASK_NUM && live_thr_num <= pool->max_thr_num)
????? {
???????? printf("admin add-----------\n");
???????? pthread_mutex_lock(&(pool->lock));
???????? int add=0;

???????? /*一次增加 DEFAULT_THREAD_NUM 個線程*/
???????? for (i=0; i<pool->max_thr_num && add<DEFAULT_THREAD_NUM
????????????? && pool->live_thr_num < pool->max_thr_num; i++)
???????? {
??????????? if (pool->threads[i] == 0 || !is_thread_alive(pool->threads[i]))
?????????? {
????????????? pthread_create(&(pool->threads[i]), NULL, threadpool_thread, (void *)pool);
????????????? add++;
????????????? pool->live_thr_num++;
????????????? printf("new thread -----------------------\n");
?????????? }
???????? }

???????? pthread_mutex_unlock(&(pool->lock));
????? }

????? /*銷毀多余的線程 忙線程x2 都小于 存活線程,并且存活的大于最小線程數*/
????? if ((busy_thr_num*2) < live_thr_num? &&? live_thr_num > pool->min_thr_num)
????? {
???????? // printf("admin busy --%d--%d----\n", busy_thr_num, live_thr_num);
???????? /*一次銷毀DEFAULT_THREAD_NUM個線程*/
???????? pthread_mutex_lock(&(pool->lock));
???????? pool->wait_exit_thr_num = DEFAULT_THREAD_NUM;
???????? pthread_mutex_unlock(&(pool->lock));

???????? for (i=0; i<DEFAULT_THREAD_NUM; i++)
??????? {
?????????? //通知正在處于空閑的線程,自殺
?????????? pthread_cond_signal(&(pool->queue_not_empty));
?????????? printf("admin cler --\n");
??????? }
????? }

?? }

?? return NULL;


/*線程是否存活*/
int
is_thread_alive(pthread_t tid)
{
?? int kill_rc = pthread_kill(tid, 0);???? //發送0號信號,測試是否存活
?? if (kill_rc == ESRCH)? //線程不存在
?? {
????? return false;
?? }
?? return true;
}

???

五、釋放

/*釋放線程池*/
int
threadpool_free(threadpool_t *pool)
{
?? if (pool == NULL)
???? return -1;
?? if (pool->task_queue)
????? free(pool->task_queue);
?? if (pool->threads)
?? {
????? free(pool->threads);
????? pthread_mutex_lock(&(pool->lock));?????????????? /*先鎖住再銷毀*/
????? pthread_mutex_destroy(&(pool->lock));
????? pthread_mutex_lock(&(pool->thread_counter));
????? pthread_mutex_destroy(&(pool->thread_counter));
????? pthread_cond_destroy(&(pool->queue_not_empty));
????? pthread_cond_destroy(&(pool->queue_not_full));
?? }
?? free(pool);
?? pool = NULL;

?? return 0;
}

??

/*銷毀線程池*/
int
threadpool_destroy(threadpool_t *pool)
{
?? int i;
?? if (pool == NULL)
?? {
???? return -1;
?? }
?? pool->shutdown = true;

?? /*銷毀管理者線程*/
?? pthread_join(pool->admin_tid, NULL);

?? //通知所有線程去自殺(在自己領任務的過程中)
?? for (i=0; i<pool->live_thr_num; i++)
?? {
???? pthread_cond_broadcast(&(pool->queue_not_empty));
?? }

?? /*等待線程結束 先是pthread_exit 然后等待其結束*/
?? for (i=0; i<pool->live_thr_num; i++)
?? {
???? pthread_join(pool->threads[i], NULL);
?? }

?? threadpool_free(pool);
?? return 0;
}

??

六、接口

?? /* 線程池初始化,其管理者線程及工作線程都會啟動 */
??? threadpool_t *thp = threadpool_create(10, 100, 100);
??? printf("threadpool init ... ... \n");

?? /* 接收到任務后添加 */
?? threadpool_add_task(thp, do_work, (void *)p);

?? // ... ...

?? /* 銷毀 */
?? threadpool_destroy(thp);

??

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/384931.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384931.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384931.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

iptables 的mangle表

mangle表的主要功能是根據規則修改數據包的一些標志位&#xff0c;以便其他規則或程序可以利用這種標志對數據包進行過濾或策略路由。 內網的客戶機通過Linux主機連入Internet&#xff0c;而Linux主機與Internet連接時有兩條線路&#xff0c;它們的網關如圖所示。現要求對內網進…

Linux常用命令(一)

history 查看歷史命令 ctrlp 向上翻歷史紀錄 ctrln 向下翻歷史紀錄 ctrlb 光標向左移動 ctrlf 光標向右移動 ctrla 光標移動到行首 ctrle 光標移動到行尾 ctrlh 刪除光標前一個 ctrld 刪除光標后一個 ctrlu 刪除光標前所有 ctrlL clear命令 清屏 tab鍵可以補全命令/填充路徑…

ip route / ip rule /iptables 配置策略路由

Linux 使用 ip route , ip rule , iptables 配置策略路由 要求192.168.0.100以內的使用 10.0.0.1 網關上網&#xff0c;其他IP使用 20.0.0.1 上網。 首先要在網關服務器上添加一個默認路由&#xff0c;當然這個指向是絕大多數的IP的出口網關。 ip route add default gw 20.0.0.…

iptables:tproxy做透明代理

什么是透明代理 客戶端向真實服務器發起連接&#xff0c;代理機冒充服務器與客戶端建立連接&#xff0c;并以客戶端ip與真實服務器建立連接進行代理轉發。因此對于客戶端與服務器來說&#xff0c;代理機都是透明的。 如何建立透明代理 本地socket捕獲數據包 nat方式 iptables…

編譯參數(-D)

程序中可以使用#ifdef來控制輸出信息 #include<stdio.h> #define DEBUGint main() {int a 10;int b 20;int sum a b; #ifdef DEBUGprintf("%d %d %d\n",a,b,sum); #endifreturn 0; } 這樣在有宏定義DEBGU的時候就會有信息輸出 如果注銷掉宏定義就不會有輸…

libpcap講解與API接口函數講解

ibpcap&#xff08;Packet Capture Library&#xff09;&#xff0c;即數據包捕獲函數庫&#xff0c;是Unix/Linux平臺下的網絡數據包捕獲函數庫。它是一個獨立于系統的用戶層包捕獲的API接口&#xff0c;為底層網絡監測提供了一個可移植的框架。 一、libpcap工作原理 libpcap…

Linux常用命令(三)

man 查看幫助文檔 alias ls : 查看命令是否被封裝 echo &#xff1a; 顯示字符串到屏幕終端 echo $PATH : 將環境變量打印出來 poweroff&#xff1a;關機 rebot&#xff1a;重啟 需要管理員權限 vim是從vi發展過來的文本編輯器 命令模式&#xff1a;打開文件之后默認進入命令模…

淺談iptables防SYN Flood攻擊和CC攻擊

何為syn flood攻擊&#xff1a; SYN Flood是一種廣為人知的DoS&#xff08;拒絕服務攻擊&#xff09;是DDoS&#xff08;分布式拒絕服務攻擊&#xff09;的方式之一&#xff0c;這是一種利用TCP協議缺陷&#xff0c;發送大量偽造的TCP連接請求&#xff0c;從而使得被攻擊方資源…

Linux之靜態庫

命名規則&#xff1a; lib 庫的名字 .a 制作步驟 生成對應.o文件 .c .o 將生成的.o文件打包 ar rcs 靜態庫的名字&#xff08;libMytest.a&#xff09; 生成的所有的.o 發布和使用靜態庫&#xff1a; 1&#xff09; 發布靜態 2&#xff09; 頭文件 文件如下圖所示&…

iptables詳解和練習

防火墻&#xff0c;其實說白了講&#xff0c;就是用于實現Linux下訪問控制的功能的&#xff0c;它分為硬件的或者軟件的防火墻兩種。無論是在哪個網絡中&#xff0c;防火墻工作的地方一定是在網絡的邊緣。而我們的任務就是需要去定義到底防火墻如何工作&#xff0c;這就是防火墻…

Linux之動態庫

命令規則 lib 名字 .so 制作步驟 1&#xff09;生成與位置無關的代碼&#xff08;生成與位置無關的代碼&#xff09; 2&#xff09;將.o打包成共享庫&#xff08;動態庫&#xff09; 發布和使用共享庫 動態庫運行原理&#xff1a; 生成動態庫&#xff1a; gcc -fPIC -c *.c -…

linux下源碼安裝vsftpd-3.0.2

1&#xff09;在http://vsftpd.beasts.org/網站中查找并下載 vsftpd-3.0.2.tar.gz源碼包 2)如果自己的機器上安裝有yum可以用yum grouplist | less指令查看以下開發環境&#xff0c;當然這一步不做也行 3&#xff09;拆解源碼包 4&#xff09;查看源碼包 5&#xff09;編輯…

Linux之GDB調試命令

gdb啟動 gdb 程序名 l 查看源代碼&#xff08;默認顯示十行&#xff09; l 文件名&#xff1a;行數 l 文件名&#xff1a;函數名 添加斷點 break 行數 &#xff08;b 也行&#xff09; b 15 if i 15 條件斷點 i b 查看斷點信息 start 程序執行一步 n 單步調試 s 單步&#xf…

Gdb 調試core文件詳解

一&#xff0c;什么是coredump 我們經常聽到大家說到程序core掉了&#xff0c;需要定位解決&#xff0c;這里說的大部分是指對應程序由于各種異常或者bug導致在運行過程中異常退出或者中止&#xff0c;并且在滿足一定條件下&#xff08;這里為什么說需要滿足一定的條件呢&#…

Linux之GDB命令(二)

gdb命令&#xff1a; 前提條件&#xff1a;可執行文件必須包含調試信息 gcc -ggdb 文件名 –啟動gdb調試查看代碼命令 當前文件&#xff1a; list 行號&#xff08;函數名&#xff09; 指定文件&#xff1a; list 文件名&#xff1a;行號&#xff08;函數名&#x…

Windows下編譯openssl庫

1、概述 OpenSSL是一個開放源代碼的軟件庫包&#xff0c;它實現了 SSL&#xff08;Secure SocketLayer&#xff09;和 TLS&#xff08;Transport Layer Security&#xff09;協議&#xff0c;所以應用程序可以使用這個包來進行安全通信&#xff0c;避免竊聽&#xff0c;同時確…

Makefile規則介紹

Makefile 一個規則 三要素&#xff1a;目標&#xff0c;依賴&#xff0c;命令 目標&#xff1a;依賴命令 1、第一條規則是用來生成終極目標的規則 如果規則中的依賴不存在&#xff0c;向下尋找其他的規則 更新機制&#xff1a;比較的是目標文件和依賴文件的時間 兩個函…

windows環境下C語言socket編程

最近由于實驗需要&#xff0c;要求寫一個c程序與java程序通信的軟件&#xff0c;為了測試首先寫了一個windows環境下c語言的socket&#xff08;tcp&#xff09;通信程序。 首先socket通信的步驟&#xff1a; 圖一 socket通信步驟&#xff08;轉載) 圖二 三次握手協議&…

進程控制塊(PCB)

進程控制塊PCB 我們知道&#xff0c;每個進程在內核中都有一個進程控制塊&#xff08;PCB&#xff09;來維護進程相關的信息&#xff0c;Linux內核的進程控制塊是task_struct結構體。 /usr/src/linux-headers-3.16.0-30/include/linux/sched.h文件中可以查看struct task_struct…

網絡層攻擊防御

網絡層攻擊防御 網絡層攻擊防御主要分為以下三類&#xff1a; TCP類報文攻擊防御 UDP類報文攻擊防御 ICMP類報文攻擊防御 TCP類報文攻擊防御 TCP正常的交互過程&#xff1a; 圖&#xff1a;TCP正常交互過程 在TCP/IP協議中&#xff0c;TCP協議提供可靠的連接服務&#xff0c…