Linux | 進程控制(進程終止與進程等待)

文章目錄

  • Linux | 進程控制 — 進程終止 & 進程等待
    • 1、進程終止
      • 進程常見退出方法
      • 1.1退出碼
        • 基本概念
        • 獲取退出碼的方式
        • 常見退出碼約定
        • 使用場景
      • 1.2 strerror函數 & errno宏
      • 1.3 _exit函數
      • 1.4_exit和exit的區別
        • 1.4.1 所屬頭文件與函數原型
        • 1.4.2 執行過程差異
        • **結合現象分析**:
    • 2、進程等待
      • 2.1 進程等待的作用
      • 2.2 僵尸進程(Zombie Process)
      • 2.3 `wait()` 系統調用
      • 2.4 `waitpid()` 系統調用
      • 2.5 示例代碼
    • 3、進程程序替換
      • 3.1 `exec` 系列函數
        • 3.1.1 `execl()`
        • 3.1.2 `execlp()`
        • 3.1.3 `execle()`
        • 3.1.4 `execv()`
        • 3.1.5 `execvp()`
        • 3.1.6 `execvpe()`
      • 3.2 `exec` 系列函數的特點
      • 3.3 示例代碼

Linux | 進程控制 — 進程終止 & 進程等待

1、進程終止

進程常見退出方法

進程退出場景

  • 代碼運行完畢,結果正確
  • 代碼運行完畢,結果不正確
  • 代碼異常終止

正常終止(可以通過echo $?查看進程退出碼)

1.從main返回

2.調用exit

3._exit

異常退出:

  • ctrl + c,信號終止

1.1退出碼

在 Linux 系統中,進程的退出碼(也稱為返回值)是進程結束時返回給其父進程或系統的值,用于表示進程執行的結果。下面從基本概念、獲取方式、常見約定、使用場景等方面詳細講解。

基本概念
  • 進程的退出碼是一個整數值,范圍通常是 0 - 255。在 C 語言編寫的程序中,通常通過 main 函數的 return 語句或者 exit() 函數來設置退出碼。例如:
#include <stdio.h>
#include <stdlib.h>int main() {// 使用 return 語句設置退出碼return 0; // 或者使用 exit() 函數// exit(0); 
}
獲取退出碼的方式
  • 父進程獲取子進程退出碼:父進程可以使用 wait()waitpid() 等系統調用獲取子進程的退出狀態信息,然后通過一些宏來提取退出碼。示例如下:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>int main() {pid_t pid = fork();if (pid == 0) {// 子進程return 42;} else if (pid > 0) {// 父進程int status;waitpid(pid, &status, 0);if (WIFEXITED(status)) {int exit_code = WEXITSTATUS(status);printf("子進程退出碼: %d\n", exit_code);}}return 0;
}
  • shell 中獲取進程退出碼:在 shell 里,可以使用 $? 變量獲取上一個執行命令的退出碼。例如:
./my_program
echo $?
常見退出碼約定

雖然 Linux 沒有強制統一所有程序使用特定的退出碼,但存在一些被廣泛遵循的約定:

  • 退出碼 0:表示進程正常結束,任務成功完成。這是最常見的退出碼,表示程序按預期執行完畢。
  • 退出碼 1:一般代表通用的錯誤,當程序遇到一些未明確分類的錯誤時,常返回這個退出碼。
  • 退出碼 2:通常意味著程序在使用命令行參數時出現了錯誤,例如參數數量不對、參數格式錯誤等。
  • 退出碼 126:表示命令雖然找到了,但由于權限問題或其他原因無法執行。
  • 退出碼 127:表明命令未找到,可能是因為命令拼寫錯誤或者該命令不在系統的搜索路徑中。
  • 退出碼 128 + N:其中 N 是信號編號。當進程因接收到信號而終止時,退出碼通常是 128 + 信號編號。例如,進程因接收到 SIGTERM(信號編號 15)而終止,退出碼就是 143(128 + 15)。
使用場景
  • 錯誤處理與調試*:開發人員可以根據退出碼快速定位程序出現問題的大致原因。例如,如果程序返回退出碼 2,就可以先檢查命令行參數的處理邏輯。
  • 腳本流程控制:在 shell 腳本中,根據命令的退出碼決定后續的操作。比如,如果某個依賴程序執行失敗(返回非零退出碼),腳本可以選擇終止執行或者嘗試其他替代方案。
./dependency_program
if [ $? -ne 0 ]; thenecho "依賴程序執行失敗,腳本終止"exit 1
fi
  • 系統監控:系統監控工具可以根據進程的退出碼判斷進程是否正常運行。如果進程頻繁以非零退出碼結束,可能表示系統存在潛在問題,需要進一步排查。

1.2 strerror函數 & errno宏

strerror

頭文件#include<string.h>

返回值:指向描述error errnum的錯誤字符串的指針,簡單來說可以將退出碼和對應的錯誤對應上。

舉例:

#include<string.h>
int main()
{for(int i=0;i<10;i++){printf("%d: %s\n",strerror(i));}return 0;
}

效果如下,后面輸出的就是退出碼對應的錯誤描述:

errno

頭文件#include<errno.h>

簡單的說,errno會返回最后的一次錯誤碼,使用errno可以獲得退出碼,通過返回退出碼,在多進程中也可以讓父進程知道子進程的狀況。

注意:但是當進程異常退出的時候,本質可能就是代碼沒有跑完,那么進程的退出碼就無意義了,所以應該要先看進程退出的時候,如果要關心進程的推出情況,要先關心退出時后有沒有出異常,如果沒有異常,再看結果是否正確,然后關心退出碼。


  • 父進程關心子進程的退出,只需要確定:
    1. 父進程是否收到來自子進程的信號,若沒有,說明沒有異常,代碼正常跑完
    2. 查看退出結果:0表示成功,非0表示錯誤,對應各自的原因

舉例:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>int main()
{int ret = 0;char *p = (char*)malloc(1000*1000*1000*4);if(p==NULL){printf("malloc error, %d: %s\n".errno,strerror(errno));ret = errno;}   else{printf("malloc success\n");}   return ret;
}

1.3 _exit函數

頭文件#include<unistd.h>

函數格式void _exit(int status);

exit函數最后也會調用_exit,但是在調用exit之前,還會做以下工作:

1、執行用戶通過atexiton_exit定義的清理函數

2、關閉所有打開的流,所有的緩存數據均被寫入

3、調用_exit

例1:

int main()
{printf("hello linux\n");exit(12);
}

或者:

int main()
{printf("hello linux\n");return 12;
}

編譯執行完后再使用echo $?查詢退出碼,效果均如下:
在這里插入圖片描述

區別在于:exit在任意地方被調用,都表示調用進程直接退出,如果調用的是return,只表示當前函數返回,原進程繼續運行,如果調用一個含exit或者return的函數,就可以明顯觀察到。

1.4_exit和exit的區別

在 Linux 系統中,exit_exit 都用于終止進程,但它們在功能實現、調用過程以及使用場景等方面存在明顯區別,下面為你詳細介紹:

1.4.1 所屬頭文件與函數原型
  • exit:它是標準 C 庫中的函數,其原型定義在 <stdlib.h> 頭文件中,函數原型為 void exit(int status);。這里的 status 是進程的退出狀態碼,通常 0 表示正常退出,非零表示異常退出。
  • _exit:這是一個系統調用,其原型定義在 <unistd.h> 頭文件中,函數原型為 void _exit(int status);status 的含義與 exit 中的相同。

1.4.2 執行過程差異
  • exit

    • 在調用 exit 時,它會先執行一些清理工作。首先,會調用所有通過 atexit 函數注冊的清理函數,這些函數可以用于釋放資源、關閉文件描述符等操作。
    • 接著,會刷新所有打開的標準 I/O 流緩沖區,將緩沖區中的數據寫入對應的文件或設備。
    • 最后,調用 _exit 系統調用來真正終止進程,并將 status 作為退出狀態返回給父進程。
  • _exit

    • _exit 是一個底層的系統調用,它會直接終止進程,不會執行任何清理工作。也就是說,它不會調用 atexit 注冊的函數,也不會刷新標準 I/O 流緩沖區。
結合現象分析
int main()
{printf("hello world");sleep(1);//使用sleep能夠觀察到一些現象,下文會提及exit(11);
}

運行完畢后再調用echo $?查看退出碼,效果如下:

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

但是將exit改為_exit后:

int main()
{printf("hello world");sleep(1);_exit(11);
}

運行完畢后再調用echo $?查看退出碼,效果如下:

在這里插入圖片描述

原因

當代碼中輸出的內容以\n結尾時,當代碼運行到printf這條語句時,程序會直接輸出內容,但是如果沒有以\n結尾,那么就會先將內容存到緩沖區中,當程序結束前會沖刷緩沖,關閉流,然后就有打印輸出的效果,也正因此會發現運行的時候是先等待了一秒鐘,輸出句子后程序馬上結束,而不是先輸出句子,等待一秒鐘再結束程序。


結合下圖

  • 調用exit()后會先執行用戶定義的清理函數,再沖刷緩沖,關閉流等,因此會有打印字符串的效果,最后再調用_exit系統調用
  • _exit()是一個系統調用接口,調用_exit()后,其會在操作系統內部直接終止進程,對應緩沖區的數據不做刷新。

2、進程等待

2.1 進程等待的作用

  • 之前在Linux | 進程狀態一文中有提及過僵尸進程的問題,如果子進程退出,父進程沒有反應,可能造成僵尸進程的問題,導致內存泄漏
  • 當進程一旦變成僵尸狀態,即使使用Kill -9也無法結束進程,需要通過進程等待來結束它,進而解決內存泄漏的問題
  • 需要通過進程等待,獲得子進程的退出情況和父進程給子進程分配的任務完成的情況,例如子進程執行程序完畢后結果是否正確,或者是否正常退出
  • 父進程通過進程等待的方式,回收子進程資源,獲取子進程退出信息。

在Linux中,進程等待是指一個進程(通常是父進程)等待其子進程終止并獲取其退出狀態。這是通過系統調用 wait()waitpid() 來實現的。進程等待的主要目的是防止子進程成為“僵尸進程”(Zombie Process),并確保父進程能夠獲取子進程的退出狀態。

2.2 僵尸進程(Zombie Process)

當一個子進程終止時,它的退出狀態需要被父進程讀取。如果父進程沒有讀取子進程的退出狀態,子進程的進程描述符仍然保留在系統中,這種進程稱為“僵尸進程”。僵尸進程不占用CPU資源,但會占用進程表中的條目,如果系統中存在大量僵尸進程,可能會導致進程表耗盡,無法創建新的進程。

2.3 wait() 系統調用

wait() 系統調用會使父進程阻塞,直到它的任意一個子進程終止。如果已經有子進程終止,wait() 會立即返回。

#include <sys/types.h>
#include <sys/wait.h>pid_t wait(int *status);
  • 參數:

    • status: 一個指向整數的指針,用于存儲子進程的退出狀態。可以通過宏(如 WIFEXITED(status)WEXITSTATUS(status) 等)來解析這個狀態。
  • 返回值:

    • 成功時返回終止的子進程的PID。
    • 如果沒有子進程,返回-1,并設置 errnoECHILD

2.4 waitpid() 系統調用

waitpid() 提供了比 wait() 更靈活的控制,允許父進程等待特定的子進程,并且可以指定是否阻塞。

#include <sys/types.h>
#include <sys/wait.h>pid_t waitpid(pid_t pid, int *status, int options);
  • 參數:

    • pid: 指定要等待的子進程的PID。
      • pid > 0: 等待進程ID等于 pid 的子進程。
      • pid = -1: 等待任意子進程,與 wait() 類似。
      • pid = 0: 等待與調用進程屬于同一個進程組的任意子進程。
      • pid < -1: 等待進程組ID等于 pid 絕對值的任意子進程。
    • status: 與 wait() 中的 status 參數相同,用于存儲子進程的退出狀態。
    • options: 控制 waitpid() 的行為,常用的選項有:
      • WNOHANG: 如果沒有子進程退出,立即返回,不阻塞。
      • WUNTRACED: 如果子進程被暫停(例如通過 SIGSTOP 信號),也返回。
  • 返回值:

    • 成功時返回終止的子進程的PID。
    • 如果指定了 WNOHANG 且沒有子進程退出,返回0。
    • 如果出錯,返回-1,并設置 errno

2.5 示例代碼

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>int main() {pid_t pid = fork();if (pid < 0) {perror("fork failed");exit(1);} else if (pid == 0) {// 子進程printf("Child process is running\n");sleep(2);printf("Child process is exiting\n");exit(42);} else {// 父進程int status;printf("Parent process is waiting for child\n");wait(&status);if (WIFEXITED(status)) {printf("Child exited with status %d\n", WEXITSTATUS(status));} else {printf("Child did not exit normally\n");}}return 0;
}

3、進程程序替換

在Linux中,進程程序替換是指將一個進程當前執行的程序替換為另一個全新的程序。這個過程是通過 exec 系列函數來實現的。進程程序替換后,進程的PID、父進程、文件描述符等信息保持不變,但進程的代碼段、數據段、堆棧等會被新程序的內容替換。

exec 系列函數是Linux系統調用的一部分,它們的作用是加載并執行一個新的程序,替換當前進程的地址空間。執行成功后,原程序的代碼將不再運行,而是由新程序從頭開始執行。


3.1 exec 系列函數

exec 系列函數有多個變體,它們的核心功能相同,但在參數傳遞方式和行為上略有不同。exec系列函數只有失敗返回值(-1),沒有成功返回值

以下是常用的 exec 函數:

3.1.1 execl()
int execl(const char *path, const char *arg, ..., (char *) NULL);
  • 功能: 加載并執行指定路徑的程序。

  • 參數:

    • path: 要執行的程序的完整路徑。
    • arg: 程序的命令行參數,第一個參數通常是程序名,最后一個參數必須是 NULL
  • 示例:

    execl("/bin/ls", "ls", "-l", NULL);
    

    這行代碼會執行 /bin/ls 程序,并傳遞 -l 參數。


3.1.2 execlp()
int execlp(const char *file, const char *arg, ..., (char *) NULL);
  • 功能: 類似于 execl(),但會在 PATH 環境變量中查找可執行文件。
  • 參數:
    • file: 要執行的程序名(不需要完整路徑)。
    • arg: 程序的命令行參數,最后一個參數必須是 NULL
  • 示例:
    execlp("ls", "ls", "-l", NULL);
    
    這行代碼會在 PATH 中查找 ls 并執行。

3.1.3 execle()
int execle(const char *path, const char *arg, ..., (char *) NULL, char *const envp[]);
  • 功能: 加載并執行指定路徑的程序,并允許指定環境變量。
  • 參數:
    • path: 要執行的程序的完整路徑。
    • arg: 程序的命令行參數,最后一個參數必須是 NULL
    • envp: 自定義的環境變量數組,必須以 NULL 結尾。
  • 示例:
    char *envp[] = {"USER=test", "PATH=/bin", NULL};
    execle("/bin/ls", "ls", "-l", NULL, envp);
    

3.1.4 execv()
int execv(const char *path, char *const argv[]);
  • 功能: 加載并執行指定路徑的程序,參數通過數組傳遞。
  • 參數:
    • path: 要執行的程序的完整路徑。
    • argv: 命令行參數數組,必須以 NULL 結尾。
  • 示例:
    char *argv[] = {"ls", "-l", NULL};
    execv("/bin/ls", argv);
    

3.1.5 execvp()
int execvp(const char *file, char *const argv[]);
  • 功能: 類似于 execv(),但會在 PATH 環境變量中查找可執行文件。
  • 參數:
    • file: 要執行的程序名(不需要完整路徑)。
    • argv: 命令行參數數組,必須以 NULL 結尾。
  • 示例:
    char *argv[] = {"ls", "-l", NULL};
    execvp("ls", argv);
    

3.1.6 execvpe()
int execvpe(const char *file, char *const argv[], char *const envp[]);
  • 功能: 類似于 execvp(),但允許指定環境變量。
  • 參數:
    • file: 要執行的程序名(不需要完整路徑)。
    • argv: 命令行參數數組,必須以 NULL 結尾。
    • envp: 自定義的環境變量數組,必須以 NULL 結尾。
  • 示例:
    char *argv[] = {"ls", "-l", NULL};
    char *envp[] = {"USER=test", "PATH=/bin", NULL};
    execvpe("ls", argv, envp);
    

3.2 exec 系列函數的特點

  1. 替換當前進程:

    • exec 系列函數會用新程序替換當前進程的地址空間,包括代碼段、數據段、堆棧等。
    • 進程的PID、父進程、文件描述符等信息保持不變。
  2. 不創建新進程:

    • exec 不會創建新進程,它只是替換當前進程的內容。
  3. 成功時不返回:

    • 如果 exec 執行成功,它不會返回,因為原程序的代碼已經被替換。
    • 如果 exec 失敗,它會返回 -1,并設置 errno
  4. 文件描述符的繼承:

    • 默認情況下,exec 會保留進程打開的文件描述符(除非顯式設置 FD_CLOEXEC 標志)。

3.3 示例代碼

  • 實例1:

? 以下是一個完整的示例,展示如何使用 fork()exec() 創建子進程并替換程序:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>int main() {pid_t pid = fork();if (pid < 0) {perror("fork failed");exit(1);} else if (pid == 0) // 子進程{printf("子進程正在執行\n");// 替換為 ls 程序char *argv[] = {"ls", "-l", NULL};execvp("ls", argv);//如果進程替換成功,則下面的代碼不會執行,如果進程替換失敗(例如命令錯誤、路徑錯誤等原因導致錯誤),則會執行下面的語句perror("hello world\n");exit(1);} else // 父進程{int status;wait(&status); // 等待子進程結束printf("父進程檢測到子進程退出\n");}return 0;
}

程序運行結果:
在這里插入圖片描述

  • 實例2:

    test1.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <sys/types.h>int main() {pid_t pid = fork();if (pid < 0) {perror("fork failed");exit(1);}   else if (pid == 0) // 子進程{   printf("子進程正在執行\n");// 替換為 ls 程序//char *argv[] = {"ls", "-l", NULL};//execvp("ls", argv);//execl("/usr/bin/ls","/usr/bin/ls","-ln","-a",NULL);execl("./test2","test2",NULL);//如果進程替換成功,則下面的代碼不會執行perror("hello world\n");exit(1);}   else // 父進程{   int status;wait(&status); // 等待子進程結束printf("父進程檢測到子進程退出\n");}   return 0;
}

test2.c

#include<stdio.h>int main(){printf("這是test2\n");return 0;
}

將test1.c編譯成可執行文件后,執行結果如下:

在這里插入圖片描述

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

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

相關文章

Android - Handler使用post之后,Runnable沒有執行

問題&#xff1a;子線程創建的Handler。如果 post 之后&#xff0c;在Handler.removeCallbacks(run)移除了&#xff0c;下次再使用Handler.postDelayed(Runnable)接口或者使用post時&#xff0c;Runnable是沒有執行。導致沒有收到消息。 解決辦法&#xff1a;只有主線程創建的…

魚皮面試鴨30天后端面試營

day1 1. MySQL的索引類型有哪些? MySQL里的索引就像是書的目錄&#xff0c;能幫數據庫快速找到你要的數據。以下是各種索引類型的通俗解釋&#xff1a; 按數據結構分 B樹索引&#xff1a;最常用的一種&#xff0c;數據像在一棵樹上分層存放&#xff0c;能快速定位范圍數據…

【核心算法篇十二】《深入解剖DeepSeek多任務學習:共享表示層的24個設計細節與實戰密碼 》

引言:為什么你的模型總在"精神分裂"? 想象你訓練了一個AI實習生: 早上做文本分類時準確率90%下午做實體識別卻把"蘋果"都識別成水果公司晚上做情感分析突然開始輸出亂碼這就是典型的任務沖突災難——模型像被不同任務"五馬分尸"。DeepSeek通…

DeepSeek應用——與PyCharm的配套使用

目錄 一、配置方法 二、使用方法 三、注意事項 1、插件市場無continue插件 2、無結果返回&#xff0c;且在本地模型報錯 記錄自己學習應用DeepSeek的過程&#xff0c;使用的是自己電腦本地部署的私有化蒸餾模型...... &#xff08;舉一反三&#xff0c;這個不單單是可以用…

2025最新智能優化算法:改進型雪雁算法(Improved Snow Geese Algorithm, ISGA)求解23個經典函數測試集,MATLAB

一、改進型雪雁算法 雪雁算法&#xff08;Snow Geese Algorithm&#xff0c;SGA&#xff09;是2024年提出的一種新型元啟發式算法&#xff0c;其靈感來源于雪雁的遷徙行為&#xff0c;特別是它們在遷徙過程中形成的獨特“人字形”和“直線”飛行模式。該算法通過模擬雪雁的飛行…

vscode通過ssh連接服務器實現免密登錄+刪除

文章目錄 參考&#xff1a; 1、 vscode通過ssh連接服務器實現免密登錄刪除&#xff08;吐血總結&#xff09;

MySQL 主從復制原理及其工作過程

一、MySQL主從復制原理 MySQL 主從復制是一種將數據從一個 MySQL 數據庫服務器&#xff08;主服務器&#xff0c;Master&#xff09;復制到一個或多個 MySQL 數據庫服務器&#xff08;從服務器&#xff0c;Slave&#xff09;的技術。以下簡述其原理&#xff0c;主要包含三個核…

【趙渝強老師】Spark RDD的緩存機制

Spark RDD通過persist方法或cache方法可以將計算結果的緩存&#xff0c;但是并不是這兩個方法被調用時立即緩存&#xff0c;而是觸發后面的action時&#xff0c;該RDD才會被緩存在計算節點的內存中并供后面重用。下面是persist方法或cache方法的函數定義&#xff1a; def pers…

設計模式相關知識點

目錄 設計模式 設計模式 代碼設計原則 設計模式 設計模式 干掉if...else&#xff0c;最好用的3種設計模式&#xff01; | 小傅哥 bugstack 蟲洞棧 代碼設計原則-CSDN博客 23種設計模式-CSDN博客 策略模式&#xff08;Strategy Pattern&#xff09;-CSDN博客 責任鏈模式…

ShenNiusModularity項目源碼學習(9:項目結構)

ShenNiusModularity源碼主要有11個project&#xff08;其實還有officialweb、test兩個文件夾&#xff0c;大致有4、5個project&#xff0c;但看著跟主要項目代碼沒太大關系&#xff0c;暫時不管&#xff09;&#xff0c;這11個project的依賴關系如下圖所示&#xff0c;其中最下…

ubuntu22.4搭建單節點es8.1

下載對應的包 elasticsearch-8.1.1-linux-x86_64.tar.gz 創建es租戶 groupadd elasticsearc useradd elasticsearch -g elasticsearch -p elasticsearch chmod uw /etc/sudoers chmod -R elasticsearch:elasticsearch elasticsearch 修改配置文件 vim /etc/sysctl.conf vm…

Docker 部署 ollama + DeepSeek

拉取并運行 Ollama Docker 鏡像 使用以下命令從 Docker Hub 拉取 Ollama 鏡像并運行容器&#xff1a; docker run -d -p 11434:11434 --name ollama ollama/ollama -d&#xff1a;以守護進程模式運行容器&#xff0c;即讓容器在后臺運行。-p 11434:11434&#xff1a;將容器內…

解決DeepSeek服務器繁忙的有效方法

全球42%的企業遭遇過AI工具服務器過載導致內容生產中斷&#xff08;數據來源&#xff1a;Gartner 2025&#xff09;。當競品在凌晨3點自動發布「智能家居安裝指南」時&#xff0c;你的團隊可能正因DeepSeek服務器繁忙錯失「凈水器保養教程」的流量黃金期?。147SEO智能調度系統…

Discuz! X3.5 根目錄權限設置

在 Discuz! X3.5 中,根目錄的權限設置是確保網站安全性和功能正常運行的關鍵。如果權限設置不當,可能會導致文件無法訪問、安全問題(如文件被篡改)或功能異常。以下是關于 Discuz! X3.5 根目錄權限設置的詳細說明和建議: 1. 根目錄位置 Discuz! X3.5 的根目錄通常是網站的…

【C++八股】內存對?

內存對齊是指編譯器按照特定規則安排數據在內存中的存儲位置&#xff0c;以提高程序的執行效率和可移植性。 內存對齊的原因&#xff1a; 1. 性能優化&#xff1a; 現代處理器通常要求數據在內存中按照特定的邊界對齊&#xff0c;以提高內存訪問效率。 如果數據未對齊&#x…

【有啥問啥】DeepSeek 技術原理詳解

DeepSeek 技術原理詳解 DeepSeek 是一款具有突破性技術的大型語言模型&#xff0c;其背后的技術原理涵蓋了多個方面&#xff0c;以下是對其主要技術原理的詳細介紹&#xff1a; 架構創新 多頭潛在注意力機制&#xff08;MLA&#xff09; 傳送門鏈接: DeepSeek V3中的Multi-…

ML.NET庫學習008:使用ML.NET進行心臟疾病預測模型開發

文章目錄 ML.NET庫學習008&#xff1a;使用ML.NET進行心臟疾病預測模型開發1. 項目主要目的和原理2. 項目概述實現的主要功能&#xff1a;主要流程步驟&#xff1a;關鍵技術&#xff1a; 3. 主要功能和步驟數據加載與路徑處理模型訓練與評估模型保存與加載 4. 代碼中的數據結構…

FFmpeg 全面知識大綱梳理

1. FFmpeg 簡介 FFmpeg 是什么: 一個開源的多媒體處理框架,用于處理音頻、視頻和流媒體。支持多種格式和編解碼器。提供命令行工具和庫(如 libavcodec, libavformat, libavfilter 等)。主要功能: 格式轉換編解碼流媒體處理音視頻剪輯、合并、分離添加濾鏡、特效壓縮與優化…

人工智能基礎之數學基礎:01高等數學基礎

函數 極限 按照一定次數排列的一列數:“&#xff0c;“,…,"…&#xff0c;其中u 叫做通項。 對于數列{Un}如果當n無限增大時&#xff0c;其通項無限接近于一個常數A&#xff0c;則稱該數列以A為極限或稱數列收斂于A&#xff0c;否則稱數列為發散&#xff0c; 極限值 左…

從零搭建微服務項目Base(第5章——SpringBoot項目LogBack日志配置+Feign使用)

前言&#xff1a; 本章主要在原有項目上添加了日志配置&#xff0c;對SpringBoot默認的logback的配置進行了自定義修改&#xff0c;并詳細闡述了xml文件配置要點&#xff08;只對日志配置感興趣的小伙伴可選擇直接跳到第三節&#xff09;&#xff0c;并使用Feign代替原有RestT…