【Linux系統編程】信號

目錄

    • 1、信號
      • 1.1、什么是信號
      • 1.2、進程對信號的處理
      • 1.3、信號的生命周期
      • 1.4、信號處理流程
      • 1.5、信號的發送
    • 2、kill()、raise()函數 發送信號
    • 3、alarm函數 鬧鐘信號
    • 4、pause函數 掛起信號、暫停
    • 5、singal 函數 捕獲信號
      • 5.1、為什么返回值是上一次的處理方式
      • 5.2、練習
    • 6、sigaction 函數 捕獲信號(推薦使用)
    • 7、setitimer() 鬧鐘信號
    • 8、sigset_t相關函數 信號集
    • 9、sigprocmask 函數 設置信號屏蔽
    • 10、sigpending 函數

1、信號

1.1、什么是信號

信號(signal):信號機制是進程之間相互傳遞消息的一種方法,信號全稱為軟中斷信號,也稱作軟中斷。信號用來通知進程發生了異步事件。

信號事件的發生有兩個來源:
硬件來源,比如我們按下了鍵盤或者其它硬件;
軟件來源,最常用發送信號的系統函數是kill(), raise(), alarm()和setitimer()等函數,軟件來源還包括一些非法運算等操作。
注意:信號只是用來通知某進程發生了什么事件,并不給該進程傳遞任何數據。
kill -l:
在這里插入圖片描述

1.2、進程對信號的處理

在這里插入圖片描述
進程可以通過三種方式來響應和處理一個信號:

  • 1、忽略信號:忽略某個信號,對該信號不做任何處理,就像未發生過一樣。
  • 2、捕捉信號:是類似中斷的處理程序,對于需要處理的信號,進程可以指定處理函數,由該函數來處理
  • 3、執行缺省操作:對該信號的處理保留系統的默認值,這種缺省操作,對大部分的信號的缺省操作是使得進程終止

常見的信號:
在這里插入圖片描述
處理動作的字母含義如下
A 缺省的動作是終止進程
B 缺省的動作是忽略此信號
C 缺省的動作是終止進程并進行內核映像轉儲(dump core)
D 缺省的動作是停止進程
E 信號不能被捕獲
F 信號不能被忽略

停止進程:只是暫停了進程的執行,進程仍然存在于內存中,隨時可以恢復其執行1。
終止進程:進程被徹底結束,其資源被釋放,不再占用系統內存1
在終端中停止進程
按下 Ctrl+Z 可以停止當前前臺進程。

$ sleep 100
^Z
[1]+  Stopped                 sleep 100

使用 jobs 命令查看停止的進程:

$ jobs
[1]+  Stopped                 sleep 100

使用 fg 命令恢復進程:

$ fg 1
sleep 100

在這里插入圖片描述

1.3、信號的生命周期

從信號(Signal)發送到信號處理函數的執行是一個完整的信號生命周期
在這里插入圖片描述

1.4、信號處理流程

在這里插入圖片描述

1.5、信號的發送

除了內核和超級用戶,并不是每個進程都可以向其他的進程發送信號。

一般的進程只能向具有相同uid和gid的進程發送信號,或向相同進程組中的其他進程發送信號。

常用的發送信號的函數有kill()raise ()alarm()setitimer()abort() 等。

2、kill()、raise()函數 發送信號

kill函數同讀者熟知的kill系統命令一樣,可以發送信號給進程或進程組(實際上,kill系統命令只是kill函數的一個用戶接口)。
kill –l 命令查看系統支持的信號列表
命令:man 2 kill
kill可以向指定的進程發送信號
在這里插入圖片描述

在這里插入圖片描述
命令:man 2 raise
raise只能向本進程發送信號
在這里插入圖片描述

在這里插入圖片描述

#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>int main()
{int i;for (i = 0; i < 3; i++){printf("i = %d\n",i);sleep(1);if (i == 1){if (kill(getpid(),SIGINT) < 0)         //向指定進程發送信號{perror("kill signal error");}// if (raise(SIGINT) < 0)          //只能向本進程發送信號// {//     perror("raise error");// }}}}
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>void sigfun(int sig)
{printf("parent work start\n");sleep(1);printf("parent work over\n");
}int main()
{pid_t pid = fork();if(pid < 0){perror("fork error");return -1;}else if(pid == 0){sleep(1); //讓父進程先執行printf("child process start\n");kill(getppid(),SIGINT);printf("chiild process over\n");}else if(pid > 0){printf("parent process start\n");signal(SIGINT,sigfun);wait(NULL);printf("parent process over\n");}
}

3、alarm函數 鬧鐘信號

在這里插入圖片描述
alarm()也稱為鬧鐘函數,它可以在進程中設置一個定時器。當定時器指定的時間到時,內核就向進程發送SIGALRM信號。
在這里插入圖片描述

#include <stdio.h>
#include <signal.h>
#include <unistd.h>int main()
{int res = alarm(5);printf("res = %d\n",res);sleep(1);res = alarm(7);printf("res = %d\n",res);  //返回上一個定時器剩余時間int i = 0;while(1){printf("i = %d\n",i++);sleep(1);}
}

4、pause函數 掛起信號、暫停

pause() 進程掛起直到收到信號為止,并以缺省的方式處理此信號
在這里插入圖片描述

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>int main()
{pid_t pid = fork();if(pid < 0){perror("fork error");return -1;}else if(pid == 0){printf("child process send signal\n");sleep(3);kill(getppid(),SIGINT);   //向父進程發送信號}else if(pid > 0){printf("parent process start\n");pause();//進程掛起 (暫停),等待被信號觸發,會以系統默認方式處理信號printf("parent over\n");}
}

5、singal 函數 捕獲信號

在這里插入圖片描述
在這里插入圖片描述
出錯時返回SIG_ERR

函數說明:當指定的信號signum到達時就會跳轉到參數handler函數中執行。handler函數的參數接收的是信號值(比如SIGINT是2)

附加說明 在信號發生跳轉到handler處理函數執行后,系統會自動將此處理函數換回原來系統預設的處理方式,如果要改變此操作請改用sigaction()。
比如這個例子

#include <stdio.h>
#include <signal.h>
#include <unistd.h>// 信號處理函數
void handle_signal(int signum) {printf("接收到信號: %d\n", signum);
}int main() {// 注冊信號處理函數if (signal(SIGINT, handle_signal) == SIG_ERR) {perror("signal 注冊失敗");return 1;}printf("程序運行中,按下 Ctrl+C 發送 SIGINT 信號...\n");// 無限循環,等待信號while (1) {sleep(1);}return 0;
}

第二次 按下 ctrl + c 會以系統默認方式中止,
也有例外
如果你的程序在第二次按下 Ctrl+C 時沒有中止,是因為 signal() 的行為在 glibc 實現中不會恢復為默認行為。
如果你希望明確控制信號處理行為,建議使用 sigaction() 替代 signal()
在這里插入圖片描述

#include <stdio.h>
#include <signal.h>
#include <unistd.h>void sigfun(int signum)
{if (signum == SIGINT){printf("is SIGINT\n");}elseprintf("is other signal\n");}
int main()
{// signal(SIGINT,SIG_IGN);  //以忽略方式處理signal(SIGINT,SIG_DFL);  //以缺省方式處理#if 1void (*fun_res)(int) = signal(SIGINT,sigfun);   //自定義信號處理方式printf("fun_res = %p\n",fun_res);  //第一次返回值為NULLfun_res = signal(SIGINT,sigfun);printf("fun_res = %p sigfun = %p\n",fun_res,sigfun);  //第二次返回上一次的處理方式#endifint i = 0;while(i < 5){printf("i = %d\n",i++);sleep(1);}
}

5.1、為什么返回值是上一次的處理方式

#include <stdio.h>
#include <signal.h>
#include <unistd.h>//為什么返回值是上一次signal處理方式
// 鏈式處理(Chaining)是一種常見的技術,
// 它允許程序員在自定義信號處理函數中調用之前的處理函數。
// 這種技術通常用于在自定義處理邏輯中保留系統默認行為或之前設置的行為。// 保存之前的信號處理函數
void (*old_handler)(int);// 自定義信號處理函數
void custom_handler(int signum)
{printf("Custom handler: Received signal %d\n", signum);// 調用之前的信號處理函數// if (old_handler != SIG_ERR) {//     printf("Calling old handler...\n");//     old_handler(signum);// }// 調用之前的信號處理函數(如果存在且不是默認行為)if (old_handler != SIG_ERR && old_handler != SIG_DFL) {printf("Calling old handler...\n");old_handler(signum);} else {printf("Old handler is SIG_DFL or invalid, skipping...\n");}
}int main()
{// 保存之前的信號處理函數old_handler = signal(SIGINT, custom_handler);if (old_handler == SIG_ERR) {perror("signal");return 1;}printf("Press Ctrl+C to trigger the custom handler...\n");// 無限循環,等待信號while (1) {sleep(1);}return 0;
}

5.2、練習

創建一個子進程,父進程每隔2秒向子進程發送一個不同的信號(SIGINT,SIGQUIT,SIGALRM), 子進程注冊相應的信號處理
函數,處理接收到信號,在信號處理函數里面打印信號名稱,子進程接收到3個信號后結束

// 創建一個子進程,父進程每隔2秒向子進程發送一個不同的信號(SIGINT,SIGQUIT,SIGALRM),
// 子進程注冊相應的信號處理
// 函數,處理接收到信號,在信號處理函數里面打印信號名稱,子進程接收到3個信號后結束#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>void sigfun(int sig)
{printf("is SIGINT\n");
}void sigfun2(int sig)
{printf("is SIGQUIT\n");
}void sigfun3(int sig)
{printf("is SIGALRM\n");
}int main()
{signal(SIGINT,sigfun);signal(SIGQUIT,sigfun2);signal(SIGALRM,sigfun3);pid_t pid = fork();if(pid < 0){perror("fork error");return -1;}else if(pid == 0 ){int num = 0;while (1){num++;pause();if(num == 3)exit(0);}}else if(pid > 0){int sigs[] = {SIGINT,SIGQUIT,SIGALRM};for (int i = 0; i < 3; i++){sleep(2);kill(pid,sigs[i]);}wait(NULL);}}

6、sigaction 函數 捕獲信號(推薦使用)

頭文件

 #include <signal.h>

函數定義

int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);

參數:

  • signum:要捕獲的信號編號(例如 SIGINT、SIGTERM 等)。
  • act:指向 struct sigaction 結構體的指針,用于指定新的信號處理行為。
  • oldact:指向 struct sigaction 結構體的指針,用于保存之前的信號處理行為(可以為 NULL)。

返回值:
成功時返回 0,失敗時返回 -1 并設置 errno。

struct sigaction 結構體

struct sigaction {void     (*sa_handler)(int);         // 信號處理函數void     (*sa_sigaction)(int, siginfo_t *, void *); // 高級信號處理函數sigset_t sa_mask;                    // 信號屏蔽集int      sa_flags;                   // 標志位void     (*sa_restorer)(void);       // 已棄用,通常為 NULL
};
#include <stdio.h>
#include <signal.h>
#include <unistd.h>void sigfun(int sig)
{printf("is SIGINT(signfun)\n");
}void sigfun2(int sig)
{printf("is SIGINT(signfun2)\n");
}int main()
{struct sigaction newact = {0};newact.sa_handler = sigfun;     // 設置信號處理函數// sigemptyset(&newact.sa_mask);      // 清空信號屏蔽集// newact.sa_flags = 0;               // 默認標志sigaction(SIGINT,&newact,NULL);struct sigaction oldact = {0};newact.sa_handler = sigfun2;sigaction(SIGINT,&newact,&oldact);printf("oldact = %p signal = %p\n",oldact.sa_handler,sigfun);int i = 0;while (i <5){printf("i = %d\n",i++);sleep(1);}printf("-----------------------\n");//恢復信號處理方式newact.sa_handler = SIG_DFL;sigaction(SIGINT,&newact,NULL);i = 0;while (i <5){printf("i = %d\n",i++);sleep(1);}}

7、setitimer() 鬧鐘信號

alarm()只會產生一次鬧鐘信號
setitimer()循環產生鬧鐘信號

頭文件

#include <sys/time.h>

函數定義

int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value);

參數說明

  • which: 指定定時器類型,可以是 ITIMER_REALITIMER_VIRTUALITIMER_PROF
  • new_value: 指向 struct itimerval 結構的指針,用于設置新的定時器值。
  • old_value: 指向 struct itimerval 結構的指針,用于存儲舊的定時器值。如果不需要舊的定時器值,可以傳入
    NULL。

ITIMER_REAL: 真實時間定時器,觸發 SIGALRM 信號。

ITIMER_VIRTUAL: 進程的用戶態 CPU 時間定時器,觸發 SIGVTALRM 信號。

ITIMER_PROF: 進程的用戶態和內核態 CPU 時間定時器,觸發 SIGPROF 信號。
struct itimerval 結構

struct itimerval {struct timeval it_interval; /* 定時器間隔 */struct timeval it_value;   /* 當前定時器值 */
};struct timeval {time_t      tv_sec;        /* 秒 */suseconds_t tv_usec;       /* 微秒 */
};

返回值

  • 成功時返回 0,失敗時返回 -1 并設置 errno。
#include <stdio.h>
#include <sys/time.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>void sigfun(int sig)
{printf("SIGALRM\n");
}int main()
{//用于捕捉信號signal(SIGALRM,sigfun);struct itimerval newtime = {0};newtime.it_interval.tv_sec = 1; //間隔時間newtime.it_value.tv_sec = 3;  //第一次發送信號時間setitimer(ITIMER_REAL,&newtime,NULL);   int i;for ( i = 0; i < 5; i++){printf("i = %d\n",i);sleep(1);}}

8、sigset_t相關函數 信號集

在這里插入圖片描述

typedef struct {unsigned long __bits[__SIGSET_NWORDS];
} sigset_t;

頭文件

#include <signal.h>

函數定義

//初始化一個空的信號集,即清除所有信號。
int sigemptyset(sigset_t *set);
//初始化一個包含所有信號的信號集
int sigfillset(sigset_t *set);
//將指定信號添加到信號集中
int sigaddset(sigset_t *set, int signum);
//從信號集中刪除指定信號。
int sigdelset(sigset_t *set, int signum);
//檢查指定信號是否在信號集中。
int sigismember(const sigset_t *set, int signum);

sigemptyset函數
功能:初始化一個空的信號集,即清除所有信號。

參數:
set:指向信號集的指針。

返回值:

  • 成功時返回 0。
  • 失敗時返回 -1,并設置 errno。

sigfillset函數
功能:初始化一個包含所有信號的信號集。

參數:
set:指向信號集的指針。

返回值:

  • 成功時返回 0。
  • 失敗時返回 -1,并設置 errno。

sigaddset函數
功能:將指定信號添加到信號集中。

參數:
set:指向信號集的指針。
signum:要添加的信號編號(如 SIGINT)。

返回值:

  • 成功時返回 0。
  • 失敗時返回 -1,并設置 errno。

sigdelset函數
功能:從信號集中刪除指定信號。

參數:
set:指向信號集的指針。
signum:要刪除的信號編號(如 SIGINT)。

返回值:
成功時返回 0。
失敗時返回 -1,并設置 errno。

sigismember函數
功能:檢查指定信號是否在信號集中。

參數:
set:指向信號集的指針。
signum:要檢查的信號編號(如 SIGINT)。

返回值:
如果信號在信號集中,返回 1。
如果信號不在信號集中,返回 0。
失敗時返回 -1,并設置 errno。

#include <stdio.h>
#include <signal.h>//打印一個字節里每一位的值
void printb(char byte)
{for (int i = 0; i < 8; i++){printf("%d",byte & 1 << 7 - i ? 1 : 0);}printf(" "); //8位空一格}//打印某一塊區域所有字節的數據
//dest區域的首地址     size區域的大小
void printmem(void *dest,size_t size)
{//從高字節向低字節輸出int i = 0;for ( i = 0; i < size; i++){printb(((char *)dest)[size -1 -i]);//每八個字節換一行if ((i + 1)%8 == 0)printf("\n");         }}int main()
{sigset_t set = {0};   //聲明一個信號集結構體//填充整個信號集if(sigfillset(&set) < 0){perror("sigfillset error");return -1;}//清空信號集if (sigemptyset(&set) < 0){perror("sigemptyset error");return -1;}//添加信號if(sigaddset(&set,SIGINT) < 0){perror("sigaddset error");return -1;}if(sigaddset(&set,SIGQUIT) < 0){perror("sigaddset error");return -1;}// printmem(&set,sizeof(set));//刪除信號if(sigdelset(&set,SIGQUIT) < 0){perror("sigdelset error");return -1;}printmem(&set,sizeof(set));//查詢信號是否存在int res = sigismember(&set,SIGQUIT);if (res == 1){printf("set have SIGINT\n");}else if (res == 0)printf("set not have SIGINT\n");else if (res < 0){perror("sigismember error");return -1;}}

9、sigprocmask 函數 設置信號屏蔽

信號屏蔽 不等于 信號忽略
信號忽略:忽略并丟掉
信號屏蔽:暫時不處理,放入隊列中,后面再從隊列中取出處理
在這里插入圖片描述

頭文件

#include <signal.h>

函數定義

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

參數說明

  • how:指定如何修改信號屏蔽字,可以是以下值之一

    • SIG_BLOCK:將 set 中的信號添加到當前信號屏蔽字中(阻塞這些信號)。
    • SIG_UNBLOCK:從當前信號屏蔽字中移除 set 中的信號(解除阻塞這些信號)。
    • SIG_SETMASK:將當前信號屏蔽字替換為 set 中的信號集。
  • set:指向sigset_t類型的信號集,表示要修改的信號集。如果為 NULL,則忽略此參數。

  • oldset:指向sigset_t 類型的信號集,用于保存修改前的信號屏蔽字。如果為 NULL,則不保存。

注意
SIG_BLOCK:用于臨時阻塞某些信號,不影響其他已阻塞的信號。

SIG_SETMASK:用于完全替換信號屏蔽字,適合需要精確控制信號屏蔽字的場景。

#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>void sigfun(int sig)
{printf("is SIGINT\n");
}
int main()
{//注冊對SIGINT信號的捕捉signal(SIGINT,sigfun);//初始化信號集sigset_t set = {0};sigemptyset(&set);  //先清空sigaddset(&set,SIGINT); //再添加//設置信號屏蔽//這里SIG_if(sigprocmask(SIG_SETMASK,&set,NULL) < 0){perror("sigprocmask error");return -1;}int i;for(i = 0; i < 5; i++){printf("i = %d\n",i);sleep(1);}//解除屏蔽,信號會被觸發if(sigprocmask(SIG_UNBLOCK,&set,NULL) < 0){perror("sigprocmask error");return -1;}}

10、sigpending 函數

頭文件

#include <signal.h>

函數定義

int sigpending(sigset_t *set);

功能
用于檢查當前進程中被阻塞(屏蔽)但尚未處理的信號的函數。

參數

set:一個指向 sigset_t 類型的指針,用于存儲當前被阻塞且未處理的信號集。

返回值

  • 成功:返回 0。
  • 失敗:返回 -1,并設置 errno 以指示錯誤。
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>void sigfun(int sig)
{printf("is SIGINT\n");
}int main()
{//注冊對SIGINT信號的捕捉signal(SIGINT,sigfun);//初始化信號集sigset_t set = {0};sigemptyset(&set);  //先清空sigaddset(&set,SIGINT); //再添加//設置信號屏蔽if(sigprocmask(SIG_SETMASK,&set,NULL) < 0){perror("sigprocmask error");return -1;}int i;for(i = 0; i < 5; i++){printf("i = %d\n",i);sleep(1);}//獲取屏蔽信號的信號集sigset_t PendSet = {0};if (sigpending(&PendSet) < 0){perror("sigpending error");return -1;}int res = sigismember(&PendSet,SIGINT);if(res == 1)printf("have SIGINT\n");else if(res == 0)printf("not have SIGINT\n");else if(res < 0){perror("sigismember error");return -1;}}

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

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

相關文章

實用小工具——快速獲取數據庫時間寫法

最近我遇到了一個比較棘手的問題&#xff1a;在工作中&#xff0c;各個項目所使用的數據庫類型各不相同。這導致我習慣性地使用Oracle的SQL語句進行編寫&#xff0c;但每次完成后都會遇到報錯&#xff0c;最終才意識到項目的數據庫并非Oracle。為了避免這種情況&#xff0c;我需…

數據類型及sizeof,進制轉換

其實數據類型可以講很多內容&#xff0c;這里看情況需要講多久吧。 本篇基本都是理論。 目錄 數據類型的分類 基本數據類型 構造數據類型 指針類型 空類型 計算數據類型或變量所占用的內存字節數 基本語法 進制轉換 二進制 二進制的概念 二進制與十進制的轉換 十六進…

pjsip dtmf發送和接收(pjsua)

DTMF(雙音多頻,Dual-Tone Multi-Frequency)是一種用于電話系統的信號技術,通過組合兩個不同頻率的音頻信號來表示數字和符號。以下是DTMF的主要使用背景和應用場景: 電話撥號 DTMF最常見的用途是電話撥號。當用戶按下電話鍵盤上的數字或符號時,電話會生成兩個特定頻率的音…

落雪音樂Pro 8.8.6 | 內置8條音源,無需手動導入,純凈無廣告

洛雪音樂Pro版內置多組穩定音源接口&#xff0c;省去手動導入的繁瑣操作&#xff0c;安裝即可暢聽海量音樂。延續原版無廣告的純凈體驗&#xff0c;支持歌單推薦與音源切換&#xff0c;滿足個性化聽歌需求。此版本僅支持在線播放&#xff0c;無法下載音樂&#xff0c;且與原版不…

mac安裝navicat及使用

0.刪除舊的 sudo rm -Rf /Applications/Navicat\ Premium.app sudo rm -Rf /private/var/db/BootCaches/CB6F12B3-2C14-461E-B5A7-A8621B7FF130/app.com.prect.NavicatPremium.playlist sudo rm -Rf ~/Library/Caches/com.apple.helpd/SDMHelpData/Other/English/HelpSDMIndexF…

【Unity】 HTFramework框架(六十二)Agent編輯器通用智能體(AI Agent)

更新日期&#xff1a;2025年3月14日。 Github源碼&#xff1a;[點我獲取源碼] Gitee源碼&#xff1a;[點我獲取源碼] 索引 編輯器通用智能體AIAgent類Friday&#xff08;星期五&#xff09;啟用智能體設置智能體類型開放智能體權限智能體交互資源優化批處理運行代碼聯網搜索休閑…

EverArt MCP 服務器安裝調試筆記 -cline

EverArt MCP 服務器安裝調試筆記 問題描述 用戶在使用 EverArt MCP 服務器時遇到報錯&#xff1a;“MCP error -1: Connection closed”。 調試過程 檢查配置文件 cline_mcp_settings.json: 確認 everart 服務器的配置信息&#xff0c;包括 command、args 和 env 是否正確。…

MFC中使用Create或CreateDialog創建對話框失敗,GetLastError錯誤碼為1813(找不到映像文件中指定的資源類型)

文章目錄 創建對話框失敗示例、原因分析及解決方案示例代碼錯誤原因解決方案 AFX_MANAGE_STATE(AfxGetStaticModuleState())作用一、功能1. 模塊狀態切換2. 自動狀態恢復 二、為什么要用該函數&#xff1f;三、必須使用該宏的典型場景1. MFC 擴展 DLL&#xff08;Extension DLL…

php進程管理

php-fpm(fastcgi process manager)是PHP 的FastCGI管理器&#xff0c;管理PHP的FastCGI進程&#xff0c;提升PHP應用的性能和穩定性 php-fpm是一個高性能的php FastCGI管理器&#xff0c;提供了更好的php進程管理方式&#xff0c;可以有效的控制內存和進程&#xff0c;支持平滑…

《MySQL數據庫從零搭建到高效管理|表的增刪改查(基礎)》

目錄 引言&#xff1a; 一、表的操作 1.1 創建學生表 1.2 查看表結構 1.3 刪除表 1.4 修改表名 1.5 添加字段 1.6 修改字段 1.7 刪除字段 1.8 小結 二、CRUD 2.1 新增&#xff08;Create&#xff09;數據 2.2 查詢&#xff08;Retrieve&#xff09;數據 2.3 修改&…

建筑管理(2): 施工承包模式,工程監理,質量監督

文章目錄 一. 施工承包模式1. 施工總承包模式1.1 施工總承包的特點1.2 施工總承包模式中的承包方 2. 平行承包模式3. 聯合體與合作體承包模式 二. 工程監理1. 強制實行監理的工程范圍1.1 國家重點建設工程1.2 大中型公用事業工程(重點)1.3 成片開發建設的住宅小區工程1.4 必須實…

Spring Boot與Apache Ignite集成:構建高性能分布式緩存和計算平臺

1. 前言 1.1 什么是Apache Ignite Apache Ignite是一個高性能的分布式內存計算平臺,支持內存緩存、分布式計算、流處理和機器學習等功能。它提供了低延遲的數據訪問和強大的計算能力,適用于需要高性能和可擴展性的應用。 1.2 為什么選擇Apache Ignite 高性能:Ignite利用內…

REST 請求返回 Invalid Credentials

REST 請求返回 “Invalid Credentials”&#xff08;無效憑據&#xff09;&#xff0c;通常表示身份驗證失敗。可能的原因和解決方案如下&#xff1a; 可能的原因 & 解決方案 用戶名或密碼錯誤 確保使用正確的用戶名和密碼。如果 API 需要 Base64 編碼的 Authorization 頭…

C++Primer學習(6.7 函數指針——難!)

6.7 函數指針 (這一章節比較難) 函數指針指向的是函數而非對象。和其他指針一樣&#xff0c;函數指針指向某種特定類型。函數的類型由它的返回類型和形參類型共同決定&#xff0c;與函數名無關。例如: //比較兩個 string 對象的長度 bool lengthCompare(const string &,co…

高級java每日一道面試題-2025年2月26日-框架篇[Mybatis篇]-Mybatis是如何將sql執行結果封裝為目標對象并返回的?都有哪些映射形式 ?

如果有遺漏,評論區告訴我進行補充 面試官: Mybatis是如何將sql執行結果封裝為目標對象并返回的?都有哪些映射形式 ? 我回答: 在Java高級面試中討論MyBatis如何將SQL執行結果封裝為目標對象并返回的過程時&#xff0c;我們可以從過程細節和映射形式兩個方面來綜合解答這個問…

react(一):特點-基本使用-JSX語法

初識React React是一個用于構建用戶界面的 JavaScript 庫&#xff0c;由 Facebook 開發和維護。 官網文檔&#xff1a;React 官方中文文檔 特點 1.聲明式編程 2.組件化開發 3.多平臺適配 開發依賴 開發React必須依賴三個庫&#xff1a; 1.react&#xff1a;包含react所必…

【Python+HTTP接口】POST請求不同請求頭構造

1、{‘Content-Type’: ‘application/json’} import requestsbody {"name1": "value1","name2": "value2"} requests.post(urlurl, databody)2、{“Content-Type”: “application/x-www-form-urlencoded; charsetUTF-8”} impor…

Java常用API:String與ArrayList的設計哲學與實踐應用

在Java編程中&#xff0c;API&#xff08;應用程序編程接口&#xff09;是開發者最強大的工具之一。它們封裝了復雜的底層邏輯&#xff0c;提供了簡潔的調用方式。本文將聚焦Java中兩個最常用的API——String和ArrayList&#xff0c;從底層原理到實際應用&#xff0c;結合深度思…

Python的字符串優雅優化策略:特定編碼 -> Unicode碼點 -> UTF-8(可自定義)

Python利用唯一uni-pot中介打理&#xff0c;任意制式輸出&#xff08;首選uyf-8&#xff09;。 筆記模板由python腳本于2025-03-14 23:37:04創建&#xff0c;本篇筆記適合喜歡探究字符串編碼細節的coder翻閱。 【學習的細節是歡悅的歷程】 博客的核心價值&#xff1a;在于輸出思…

linux 時間同步(阿里云ntp服務器)

1、安裝ntp服務 rootlocalhost ~]# yum -y install ntp 已加載插件&#xff1a;fastestmirror, langpacks Loading mirror speeds from cached hostfile* base: mirrors.nju.edu.cn* centos-sclo-rh: mirrors.nju.edu.cn* centos-sclo-sclo: mirrors.huaweicloud.com* epel: m…