學號245
再中1235行我們可以看到乙個很長的tast_struct結構體的定義。下圖是部分截圖:
程序管理是作業系統提供的最基本的功能之一,為了描述程序,用程序控制塊pcb來唯一地定義乙個程序。tast_struct中定義了程序的標識、程序的狀態、程序的排程策略等。如:狀態state用-1、0、>0表示三種狀態。其中,各部分依次是:程序的底層資訊、指向記憶體區域描述符的指標、程序相關的tty裝置、當前目錄、指向檔案描述符的指標、接收到的訊號。
fort
、vfort
、clone
都可以用來建立乙個新的程序,但其實他們都是呼叫了do_fork
函式實現的。
long do_fork(unsigned long clone_flags,
1624 unsigned long stack_start,
1625 unsigned long stack_size,
1626 int __user *parent_tidptr,
1627 int __user *child_tidptr)
1628
1650
1651 p = copy_process(clone_flags, stack_start, stack_size,
1652 child_tidptr, null, trace);
1653 /*
1654 * do this prior waking up the new thread - the thread pointer
1655 * might get invalid after that point, if the thread exits quickly.
1656 */
1657 if (!is_err(p))
1674
1675 wake_up_new_task(p);
1676
1677 /* forking complete and child started to run, tell ptracer */
1678 if (unlikely(trace))
1679 ptrace_event_pid(trace, pid);
1680
1681 if (clone_flags & clone_vfork)
1685
1686 put_pid(pid);
1687 } else
1690 return nr;
1691}
從**中可以看出,do_fork
呼叫了copy_process
建立程序,這個函式又很長,大概400行左右。
它做了這麼幾件事:
複製當前的tast_struct;
初始化程序,並將狀態設為task_running;
複製父程序的所有資訊;
呼叫copy_thread
初始化子程序的核心棧;
為新的程序分配設定新的pid;
linux環境下,fork系統呼叫將會建立乙個與當前task完全一樣的新task,直到應用程式呼叫exec*系列的glibc庫函式最終呼叫execve
系統呼叫之後,linux核心才開始真正裝載elf可執行檔案(映像檔案)。execve核心入口為sys_execve
,隨之呼叫do_execve
將查詢這個可執行檔案,如果找到則讀取elf可執行檔案的前128個位元組,然後呼叫search_binary_handle
通過elf檔案頭中的e_ident得到可執行檔案的magic number,判斷出這是乙個什麼型別的可執行檔案,並呼叫不同可執行檔案的裝載處理程式,對於elf可執行檔案而言,其裝載處理程式為load_elf_binary
,這個函式將會把execve系統呼叫的返回位址修改為elf可執行檔案的入口點,對於靜態鏈結得到的elf檔案即檔案頭中定義的e_entry,對於動態鏈結得到的elf可執行檔案則是動態鏈結器。一步一步返回到sys_execve
之後,因為返回位址已經被修改為了elf程式入口位址了,所以系統呼叫返回到使用者態之後,eip指令暫存器將直接跳轉到elf程式入口位址,程式開始執行,裝載完成。
過程如下:
fork -> execve() -> sys_execve() -> do_execve()核心執行程序切換由兩步組成:
切換全域性目錄以安裝乙個新的位址空間;
切換核心態堆疊和硬體上下文,因為硬體上下文提供了核心執行新程序所需要的所有資訊,包含cpu暫存器。
switch_to()
/* context switching is now performed out-of-line in switch_to.s */
extern struct task_struct *__switch_to(struct task_struct *,
struct task_struct *);
#define switch_to(prev, next, last)\
do while (0)
其中呼叫了__switch_to
函式:
__switch_to
__switch_to(
struct task_struct *prev_p,
struct task_struct *next_p)
在switch_to
函式中,prev
和next
是輸入引數,假設核心決定暫停程序a而啟用程序b,在schedule
函式中,prev
指向a的描述符,而next指向b的程序描述符。switch_to
巨集一旦使a暫停,a的執行流就被凍結。
程序管理是作業系統提供的最基本的功能之一,通過do_fork
建立新程序。當核心需要切換到另乙個程序時候,需要儲存當前程序的所有狀態,即當前程序的上下文,這樣當再次執行該程序時候,能夠恢復之前的狀態繼續執行。
程式和程序
程式 或者狹義上講可執行檔案 是乙個靜態的概念,它就是一些預先編譯好的指令合資料集合的乙個檔案 程序則是乙個動態的概念,它是程式執行時的乙個過程,很多時候把動態庫叫做執行時 runtime 也有一定的含義。有人做過乙個很有意思的比喻,說把程式和程序的概念跟做菜相比較的話,那麼程式就是菜譜,計算機的c...
linux程式管理和程序(1)
什麼是程序 乙個程式被載入到記憶體中執行,那麼在記憶體中的那個資料就被稱為程序,所有系統上面跑的資料都以程序的型別存在。在linux系統中,觸發任何乙個事件,系統都會定義為乙個程序,並且給予這個程序乙個id,稱為pid,同時觸發這個程序的使用者與相關屬性關係,給予這個pid一組有效的許可權設定。舉個...
linux程式守護程序(shell)
使用shell每秒檢測一次程式是否在執行,如果沒有執行則自動啟動程式 bin bash 配置檔案路徑 configfile 1 config settings.ini slash restartlog daemon shopt s expand aliases alias datetime date...