linux系統程式設計:程序原語
程序原語
1. 程序(Process)是計算機中的程式關於某資料集合上的一次執行活動,是系統進行資源分配和排程的基本單位,是作業系統結構的基礎。
2. 程序環境
在libc中定義的全域性變數environ指向環境變量表,environ沒有包含在任何標頭檔案中,所以在使用時要用extern宣告。用以下程式碼可以檢視當前程序的所有環境變數的資訊。
#include <stdio.h>
int main(void)
{
extern char **environ;
int i;
for(i = 0; environ[i] != NULL; i++)
printf ("%s\n", environ[i]);
return 0;
}
執行結果用鍵值對的形式展示環境變數的資訊。幾個常見的環境變數解釋:
PATH:可執行檔案的搜尋路徑。
SHELL:當前使用的shell。
HOME:當前使用者的主目錄路徑。
3. 程序狀態
4種主要的程序狀態:執行、就緒、掛起、終止。
4. 程序原語
在liunx中使用函式fork建立新的程序。
#include <unistd.h>
pid_t fork(void);
函式特點:呼叫一次,返回兩次。
在父程序中,返回建立的子程序的pid;在子程序中返回0;出錯,返回-1。
一個建立子程序的例項:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
void sys_err(char *s)
{
perror(s);
exit(1);
}
int main(void)
{
pid_t pid;
pid = fork();
if (pid < 0)
sys_err("fork");
else if (pid > 0)
{
/* parent process */
printf("I am parent,my pid is %d, my parent pid is %d\n", getpid(), getppid());
sleep(1); //休眠1秒,防止父程序過早退出
}
else
{
/* child process */
printf("I am child,my pid is %d, my parent pid is %d\n", getpid(), getppid());
}
return 0;
}
//I am child, my pid is 15057, my parent pid is 15056
//I am parent, my pid is 15056, my parent pid is 5292
#include <unistd.h>
#include <sys/types.h> //定義了pid_t、uid_t、gid_t
pid_t getpid(void); //獲取當前程序的pid
pid_t getppid(void); //獲取當前程序父程序的pid
uid_t getuid(void); //返回實際使用者id
uid_t geteuid(void); //返回有效使用者id
gid_t getgid(void); //返回實際使用者組id
gid_t getegid(void); //返回有效使用者組id
所有id都是正數。
父程序和子程序的關係:
1.子程序複製了父程序的PCB(除了pid)和程式碼段以及資料區。
2.用fork建立子程序後執行的是和父程序相同的程式(但有可能執行不同的程式碼分支),子程序往往要呼叫一種exec函式以執行另一個程式。當程序呼叫一種exec函式時,該程序的使用者空間程式碼和資料完全被新程式替換,從新程式的啟動例程開始執行。呼叫exec並不建立新程序,所以呼叫exec前後該程序的id並未改變。
5. exec族
#include <unistd.h>
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ..., char *const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);
只需弄懂了execl的使用,其它的舉一反三了:path指出了新可執行程式的路徑,後面的arg,即是提供的引數。
使用execl函式更改程式的執行:
//show.c
#include <stdio.h>
int main(int argc, char **argv)
{
int i = 0;
while(i < argc)
printf("%s\n", argv[i++]);
return 0;
}
//app.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
if(argc < 2)
{
fprintf(stderr, "usage:app newapp ...");
exit(1);
}
printf("zhangxiang\n");
//$ argv[1] zx [email protected]
execl(argv[1], "zx", "[email protected]", NULL); //NULL用於指明引數列表的結束
printf("David\n");
return 0;
}
$ gcc show.c -o show
$ gcc app.c -o app
$ app show
zhangxiang
zx
[email protected]126.com
執行printf(“zhangxiang\n”);了後,程式的程式碼段被替換,所以原程式的printf(“David\n”);不會被執行。
l 命令列引數列表
p 搜素file時使用path變數
v 使用命令列引數陣列
e 使用環境變數陣列,不使用程序原有的環境變數,設定新載入程式執行的環境變數
這些函式如果呼叫成功則載入新的程式從啟動程式碼開始執行,不再返回,如果調用出錯則返回-1,所以exec函式只有出錯的返回值而沒有成功的返回值。
6. wait()、waitpid()
殭屍程序::子程序退出,父程序沒有回收子程序資源(PCB),則子程序變成殭屍程序。
孤兒程序:父程序先於子程序結束,則子程序成為孤兒程序,子程序的父程序成為1號程序init程序,稱為init程序領養孤兒程序。
子程序結束後,PCB仍然滯留在記憶體。父程序可以通過子程序的PCB來獲知子程序的退出狀態:正常退出時的退出碼、不正常退出時,是被哪個訊號終止的。
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
函式說明:
引數status為傳出引數,用於記錄退出狀態。
當沒有子程序退出時,wait呼叫會阻塞當前程序。
成功,返回子程序的pid;
失敗,返回-1;
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(void)
{
pid_t pid, wpid;
pid = fork();
if(0 == pid)
{
printf("in child\n");
sleep(2);
printf("child exit\n");
}
else if(pid > 0)
{
while(1)
{
wpid = wait(NULL);
printf("in parent %d\n", wpid);
sleep(1);
}
}
else
{
perror("fork");
exit(1);
}
return 0;
}
//in child
//child exit
//in parent 27909
//in parent -1
//in parent -1
//^c
wait()會使父程序阻塞,為了不阻塞,需使用waitpid()
#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *status, int options);
函式說明:
pid指明瞭需回收哪個子程序的PCB;
通過指定options的值,更改函式執行狀態。(特別地,指定WNOHANG,將不會阻塞)。
指定WNOHANG,非阻塞後。若沒有程序退出,返回0,其它同wait。
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(void)
{
pid_t pid, wpid;
pid = fork();
if(0 == pid)
{
printf("in child\n");
sleep(2);
printf("child exit\n");
}
else if(pid > 0)
{
while(1)
{
wpid = waitpid(0, NULL, WNOHANG);
printf("in parent %d\n", wpid);
sleep(1);
}
}
else
{
perror("fork");
exit(1);
}
return 0;
}
//in parent 0
//in child
//in parent 0
//child exit
//in parent 28700
//in parent -1
//in parent -1
//^c
相關推薦
linux系統程式設計:程序原語
程序原語 1. 程序(Process)是計算機中的程式關於某資料集合上的一次執行活動,是系統進行資源分配和排程的基本單位,是作業系統結構的基礎。 2. 程序環境 在libc中定義的全域性變數environ指
linux系統程式設計之程序(八):守護程序詳解及建立,daemon()使用
一,守護程序概述 Linux Daemon(守護程序)是執行在後臺的一種特殊程序。它獨立於控制終端並且週期性地執行某種任務或等待處理某些發生的事件。它不需要使用者輸入就能執行而且提供某種服務,不是對整個系統就是對某個使用者程式提供服務。Linux系統的大多數伺服器就是通過守護程序實現的。常見的守護程序包括系
linux系統程式設計之程序(四):程序退出exit,_exit區別即atexit函式
一,程序終止有5種方式: 正常退出: 從main函式返回 呼叫exit 呼叫_exit 異常退出: 呼叫abort 由訊號終止 二,exit和_exit區別: 關於_exit(): #include <unistd.h>
linux系統程式設計之程序(二):程序生命週期與PCB(程序控制塊)
本節目標: 程序狀態變遷程序控制塊程序建立程序撤消終止程序的五種方法 一,程序狀態變遷 程序的三種基本狀態 就緒(Ready)狀態 當程序已分配到除CPU以外的所有必要的資源,只要獲得處理機便可立即執行,這時的程序狀態稱為就緒狀態。 執行(Running)狀態 當程序已獲得
linux系統程式設計-回收程序
孤兒程序和殭屍程序的概念 孤兒程序:父程序先於子程序結束,則子程序成為孤兒程序,此時init程序變成子程序的父程序,稱為init程序領養孤兒程序。 殭屍程序:程序終止,父程序尚未回收,子程序殘留資源(PCB)存放於核心中,變成殭屍(Zombie)程序
Linux系統程式設計之程序
1、程序控制塊=程序描述符(PCB) 程序狀態(4/5種):就緒(初始化),執行,掛起(=等待), 停止 PBC成員: 1、程序id 2、程序狀態 3、程序切換需要儲存和恢復的CPU暫存器 4、描述虛擬地址空間資訊 5、描述控制終端的資訊 6、當
Linux系統程式設計:標準IO和檔案IO的區別
首先了解下什麼是標準IO以及檔案IO。 標準IO:標準I/O是ANSI C建立的一個標準I/O模型,是一個標準函式包和stdio.h標頭檔案中的定義,具有一定的可移植性。標準IO庫處理很多細節。例如快取分配,以優化長度執行IO等。標準的IO提供了三種類型的快取。
Linux系統程式設計1.程序
1. 程序的概念 Linux作業系統是面向多使用者的,在同一時間可以有許多使用者向作業系統發出各種命令。在現代作業系統中,都有程式和程序的概念。 通俗的講:程式是一個包含可以執行程式碼的檔案,是一個靜態的檔案;而程序是一個開始執行但還沒有結束的程式例
linux系統程式設計之程序(一)
本節目標:什麼是程式什麼是程序程序資料結構程序與程式區別與聯絡一,什麼是程式?程式是完成特定任務的一系列指令集合二,什麼是程序?從使用者的角度來看程序是程式的一次動態執行過程從作業系統的核心來看,程序是作業系統分配的記憶體、CPU時間片等資源的基本單位。程序是資源分配的最小單位每一個程序都有自己獨立的地址空間
Linux系統程式設計_程序
程式 vs. 程序: 程式,是指編譯好的二進位制檔案,是靜態概念,在磁碟上,不佔用系統資源(cpu、記憶體、開啟的檔案、裝置、鎖….); 程序,是一個抽象的動態概念,與作業系統原理聯絡緊密。程序是活躍的程式,佔用系統資源。在記憶體中執行。(程式執行起來,產
linux系統程式設計之程序的環境變數
環境變數: 環境變數,是指在作業系統中用來指定作業系統執行環境的一些引數。通常具備以下特徵: ① 字串(本質) ② 有統一的格式:名=值[:值] ③ 值用來描述程序環境資訊。 儲存形式:與命令列引數類似。char *[]陣列,陣列名environ,內部儲存
Linux系統程式設計——程序間通訊:共享記憶體
概述 共享記憶體是程序間通訊中最簡單的方式之一。共享記憶體允許兩個或更多程序訪問同一塊記憶體,就如同 malloc() 函式向不同程序返回了指向同一個實體記憶體區域的指標。當一個程序改變了這塊地址中的內容的時候,其它程序都會察覺到這個更改。 共享記憶體的特點: 1)共
Linux系統程式設計——程序間通訊:訊息佇列
概述 訊息佇列提供了一種在兩個不相關的程序之間傳遞資料的簡單高效的方法,其特點如下: 1)訊息佇列可以實現訊息的隨機查詢。訊息不一定要以先進先出的次序讀取,程式設計時可以按訊息的型別讀取。 2)訊息佇列允許一個或多個程序向它寫入或者讀取訊息。 3)與無名管道、命名管道一
Linux系統程式設計——程序間通訊:管道(pipe)
管道的概述 管道也叫無名管道,它是是 UNIX 系統 IPC(程序間通訊) 的最古老形式,所有的 UNIX 系統都支援這種通訊機制。 無名管道有如下特點: 1、半雙工,資料在同一時刻只能在一個方向上流動。 2、資料只能從管道的一端寫入,從另一端讀出。
Linux系統程式設計——程序間通訊:訊號中斷處理
什麼是訊號? 訊號是 Linux 程序間通訊的最古老的方式。訊號是軟體中斷,它是在軟體層次上對中斷機制的一種模擬,是一種非同步通訊的方式 。訊號可以導致一個正在執行的程序被另一個正在執行的非同步程序中斷,轉而處理某一個突發事件。 “中斷”在我們生活中經常遇到,譬如,我正在
Linux系統程式設計——程序替換:exec 函式族
在 Windows 平臺下,我們可以通過雙擊執行可執行程式,讓這個可執行程式成為一個程序;而在 Linux 平臺,我們可以通過 ./ 執行,讓一個可執行程式成為一個程序。 但是,如果我們本來就執行著一個程式(程序),我們如何在這個程序內部啟動一個外部程式,由核心將這個外部程式
Linux系統程式設計——程序的控制:結束程序、等待程序結束
結束程序 首先,我們回顧一下 C 語言中 continue, break, return 的作用: continue: 結束本次迴圈 break: 跳出整個迴圈,或跳出 switch() 語句 return: 結束當前函式 而我們可以通過 exit() 或 _exit() 來結束當前程序。
Linux系統程式設計---程序替換
程序替換 我們知道,在 Windows 平臺下,我們可以通過雙擊執行可執行程式,讓這個可執行程式成為一個程序;而在 Linux 平臺,我們可以通過 ./ 執行,讓一個可執行程式成為一個程序。 但是,如果我們本來就執行著一個程式(程序),我們如何在這個程序內部啟動一個外部程式,由核
Linux系統程式設計---程序等待
程序等待 1.為什麼需要程序等待 我們知道,子程序退出,父程序如果不管不顧,那麼子程序就可能變為殭屍程序,進而佔用系統資源,造成記憶體洩漏, 另外,程序一旦變成殭屍狀態,那就刀槍不入,“殺人不眨眼”的kill-9也無能為力,因為誰也辦法殺死一個已經死去的程序。
Linux系統程式設計---程序終止
程序終止 程序的退出有三種場景: 程式碼執行完畢,結果正確 程式碼執行完畢,結果不正確 程式碼異常終止 程序退出方法 從main返回 呼叫exit函式 呼叫_exit函式 ctrl + c :x訊號終止