理解程序建立 可執行檔案的載入和程序執行程序切換

2021-09-13 19:18:16 字數 3133 閱讀 6316

1.程序的概念

程序是程式的乙個執行例項,是正在執行的程式,是能分配處理器並由處理器執行的實體。作業系統使用資料結構來代表處理不同的實體,這個資料結構就是通常所說的程序描述符或程序控制塊(pcb)。 在linux作業系統下這就是task_struct結構 ,在/include/linux/sched.h原始檔中實現。

2.理解task_struct資料結構

**鏈結

volatile long state; //表示程序狀態

void *stack; //程序所屬堆疊指標

unsigned int rt_priority;//程序優先順序

int exit_state;//退出時狀態

pid_t pid;//程序號,作為程序的全域性識別符號

pid_t tgid;//程序組號

struct task_struct __rcu *real_parent;//父程序

struct list_head children;//子程序

struct list_head sibling;//兄弟程序

struct task_struct *group_leader;//所屬程序組的主程序

do_fork主要做了以下工作:

1.呼叫copy_process,將當期程序複製乙份出來為子程序,並且為子程序設定相應地上下文資訊;

2.初始化vfork的完成處理資訊(如果是vfork呼叫);

3.呼叫wake_up_new_task,將子程序放入排程器的佇列中,此時的子程序就可以被排程程序選中,得以執行;

4.如果是vfork呼叫,需要阻塞父程序,直到子程序執行exec。

1.執行以下**

rm menu -rf

git clone

cd menu //修改makefile裡的路徑

mv test_fork.c test.c

make rootfs

2.在qemu中gdb

打斷點:

執行結果

程序的建立的系統呼叫clone fork vfork都是呼叫do_fork實現的,而do_fork在做了一些引數檢查之後。呼叫了copy_process函式,copy_process函式在進行安全性檢查之後,使用dup_task_struct複製父程序的結構體。對新程序描述符的一些標誌資訊和時間資訊進行初始化,之後將父程序的所有程序資訊拷貝到子程序空間,包括io、檔案、記憶體資訊等。然後,設定新程序的pid,將新程序加入程序排程佇列中。子程序的eax設定為0,父程序則返回新程序的pid,所以在fork呼叫中,子程序返回的是0,父程序返回的是新程序的pid。

程式的編譯鏈結過程需要經歷如下步驟:

elf檔案格式包括三種主要的型別:可執行檔案、可重定向檔案、共享庫。

1.可執行檔案(應用程式)可執行檔案包含了**和資料,是可以直接執行的程式。

2.可重定向檔案(.o)可重定向檔案又稱為目標檔案,它包含了**和資料(這些資料是和其他重定位檔案和共享的object檔案一起連線時使用的)。

.o檔案參與程式的連線(建立乙個程式)和程式的執行(執行乙個程式),它提供了乙個方便有效的方法來用並行的視角看待檔案的內容,這些.o檔案的活動可以反映出不同的需要。

linux下,我們可以用gcc -c編譯原始檔時可將其編譯成.o格式。

3.共享檔案(*.so)也稱為動態庫檔案,它包含了**和資料(這些資料是在連線時候被聯結器ld和執行時動態聯結器使用的)。動態聯結器可能稱為ld.so.1,libc.so.1或者 ld-linux.so.1。

分別在sys_execve、do_execve() 、do_execve_common()、exec_binprm()、search_binary_handler()、load_elf_binary()、start_thread()設定斷點

斷點 do _execve處,可以看出其呼叫do_execve_common()函式。

我們先對schedule,pick_next_task,context_switch和__switch_to設定斷點,觀察程式執行的情況。

由以上跟蹤結果可以得知,在進行程序間的切換時,各處理函式的呼叫順序如下:pick_next_task -> context_switch -> __switch_to 。由此可以得出,當程序間切換時,首先需要呼叫pick_next_task函式挑選出下乙個將要被執行的程式;然後再進行程序上下文的切換,此環節涉及到「保護現場」及「現場恢復」;在執行完以上兩個步驟後,呼叫__switch_to進行程序間的切換。

通過系統呼叫,使用者空間的應用程式就會進入核心空間,由核心代表該程序執行於核心空間,這就涉及到上下文的切換,使用者空間和核心空間具有不同的位址對映,通用或專用的暫存器組,而使用者空間的程序要傳遞很多變數、引數給核心,核心也要儲存使用者程序的一些暫存器、變數等,以便系統呼叫結束後回到使用者空間繼續執行,所謂的程序上下文,就是乙個程序在執行的時候,cpu的所有暫存器中的值、程序的狀態以及堆疊中的內容,當核心需要切換到另乙個程序時,它需要儲存當前程序的所有狀態,即儲存當前程序的程序上下文,以便再次執行該程序時,能夠恢復切換時的狀態,繼續執行。 同理,硬體通過觸發訊號,導致核心呼叫中斷處理程式,進入核心空間。這個過程中,硬體的一些變數和引數也要傳遞給核心,核心通過這些引數進行中斷處理,中斷上下文就可以理解為硬體傳遞過來的這些引數和核心需要儲存的一些環境,主要是被中斷的程序的環境。

linux核心載入可執行檔案

使用gdb跟蹤分析乙個execve系統呼叫核心處理函式 sys execve 驗證您對linux系統 載入可執行程式所需處理過程的理解 登陸實驗樓虛擬機器 增加 s s啟動引數開啟除錯模式 qemu kernel linux 3.18.6 arch x86 boot bzimage initrd r...

UNIX LINUX 平台可執行檔案載入過程

本文討論了 unix linux 平台下三種主要的可執行檔案格式 a.out assembler and link editor output 彙編器和鏈結編輯器的輸出 coff common object file format 通用物件檔案格式 elf executable and linkin...

linux可執行檔案的載入和執行之一 1

可執行檔案的載入和執行 execve系統呼叫可以呼叫乙個可執行檔案完全代替當前的程序,它在libc中的封裝有幾個api int execl const charp a t h n a m e,const char a rg 0,char 0 int execv const charp a t h n...