linux 10訊號底層實現機制程序替換

2021-09-29 21:23:37 字數 4337 閱讀 8593

1.非同步執行:兩個以上的程序或執行緒,執行互不影響,同時向下執行,當某個時刻,乙個程序或執行緒會通過系統機制通知其他程序或執行緒。

(非阻塞狀態)

2.同步執行:乙個程序或執行緒的執行需要依賴其他的程序或執行緒執行的條件(阻塞狀態)

3.阻塞:條件未準備好,程序在這停下,一直等著

4.非阻塞:條件準備好,程序在這沒停下。

1.函式:int kill(pid_t pid,int sigtype);

pid_t pid:指定將那個訊號傳送給程序

pid>0:指定接收訊號程序的pid

pid == 0:將訊號傳送給當前程序組中所有的程序

pid == -1:將訊號傳送給系統上所有的程序(有許可權傳送)

pid < -1:將訊號傳送給程序id為-pid組內所有的程序

sigtype:傳送的訊號型別

2.傳送的過程

例子:kill(1234,sigint):其中sigint==2;

呼叫底層函式:sys_kill(1234,2);

傳送訊號的函式:

///向指定任務(*p)傳送訊號(sig),許可權為priv

static _inline int

send_sig (

long sig ,

struct task_struct *p,

int priv)

;

p->signal |= (1訊號觸發中斷機制,會有中斷處理程式來處理,接著會呼叫訊號處理函式,訊號處理函式通過signal函式來註冊**實現:

int sys_signal(int signum,long handler, long restorer)

注:sa_restorer 為恢復過程指標,用於儲存原返回的過程指標流程圖講解過程:

當中斷機制處理起來時,在pcb,陣列中呼叫訊號處理函式,sigaction中記錄要找到的值,在呼叫signal函式。

我們來思考乙個問題:

p->signal |= (1<

**實現:

結果:發現如果連續收到n個相同的訊號,就收訊號的程序會將所有的訊號都會合併成乙個訊號!

同時得到以下結論:如果第乙個訊號正在處理,則第二個訊號會等待第乙個訊號處理完成

結果我們發現:訊號響應方式一旦修改,後續接受訊號一直沿用,直到程序終止或再次修改

訊號處理程式分成兩部分:

上部分:識別訊號

下部分:處理訊號

結果:

第一次接收到訊號和第二次接收到訊號之間將響應方式修改。

在第一次修改的訊號處理函式中修改訊號的響應方式。

當乙個程序呼叫一種 exec 函式時,該程序執行的程式完全替換為新程式,而新程式從其 main 函式開始執行。

呼叫 exec 並不建立新程序, 前後的程序 id 並未改變, 只是用磁碟上的乙個新程式替換當前程序的正文段、資料段、堆段和棧段

接下來我們乙個個的看看:

(1) 函式原型: int execl(const char * path, const char * arg, …);

(2) 這裡的 path 是可執行程式的路徑 取路徑名作為引數

(3) arg 是所要替換程式的引數

(4) 返回值: 成功沒有返回值,失敗返回 -1

#include #include #include int main(void)

printf("hahaha!\n");

return 0;

}

(1) 函式原型:

int execlp(const char * file, const char * arg, …);

(2) 這裡 file 引數可以是乙個 可執行程式名,並且可以不用指定全路徑,它會自動在 path 中的乙個找到該可執行檔案,如果該檔案不是由連線編譯器產生的機器可執行檔案,則就認為該檔案是乙個 shell 指令碼,於是試著呼叫 /bin/sh, 並以該 filename 作為 shell 的輸入, 取檔名作為引數

(3) arg 還是可執行程式的引數

(4) 返回值: 成功返回

#include #include #include int main(void)

printf("hahaha!\n");

return 0;

}

(1) 函式原型:

int execle(const char * path, const char * arg, …, char * const envp);

(2)這裡的最後乙個引數是乙個自己構建的環境,是乙個字串指標陣列,取路徑名作為引數

// filename: process_exec.c 

#include #include #include int main(void)

; int res = execle("./exec_test", "./exec_test", null, env);

if(res == -1)

printf("hahaha!\n");

return 0;

}

// filename: test_exec.c

#include #include int main()

程式編譯結果如下:

aaaa = aaaa

(1) 函式原型:

int execv(const char * path, char * const ar**);

(2) 這和 execl 函式一樣,區別就是,execl 函式的第二個引數為可變引數列表,而 execv 函式的第二個引數為字串指標陣列。取路徑名作為引數

#include #include #include int main(void)

; int res = execv("/usr/bin/ls", arg);

if(res == -1)

printf("hahaha!\n");

return 0;

}

(1) 函式原型:

int execvp(const char * file, char * const ar**);

(2) 與函式 execlp 一樣,取檔名作為引數

#include #include #include int main(void)

; int res = execvp("ls", arg);

if(res == -1)

printf("hahaha!\n");

return 0;

}

(1) 函式原型:

int execve(const char * file, char * const ar**, char * const envp);

(2) 與函式 execle 函式一樣, 取路徑名作為引數

#include #include #include int main(void)

; char * env = ;

int res = execve("./exec_test", arg, env);

if(res == -1)

printf("hahaha!\n");

return 0;

}

這也是乙個程序替換函式,依賴呼叫程序來完成這項工作。呼叫程序可以使用檔案描述符驗證所需要的檔案並且無競爭地執行該檔案。

Linux10 使用者通訊 登入 限制

mesg命令有兩種,執行mesg n命令後,可以拒絕接受除了root外所有資訊,執行mesg y後復原。wall write all 給所有使用者發資訊。wall後直接加要發的資訊就可以傳送出去,此時包括傳送者在內的所有人都會收到資訊,還會顯示發訊息的使用者名稱和發訊息的時間。輸入內容 最後一行要以...

STL的底層實現機制

1.vector 底層資料結構為陣列 支援快速隨機訪問 2.list 底層資料結構為雙向鍊錶,支援快速增刪 3.deque 底層資料結構為乙個 控制器和多個緩衝區,詳細見stl原始碼剖析p146,支援首尾 中間不能 快速增刪,也支援隨機訪問 deque是乙個雙端佇列 double ended que...

Binder機制及底層實現

1 程序間的記憶體空間是程序私有的 2 程序間和核心的空間是互通的 3 程序1空間 核心空間 程序2空間 binder跨程序通訊 ipc 的原理就是利用了這個可共享的核心空間將程序私有的空間進行關聯的。而binder就是這個通道。使用步驟 1.服務端註冊服務 1 server端向binder驅動發起...