|
什么是程序?程序:可執(zhí)行文件或者包含一堆可運(yùn)行CPU指令的和數(shù)據(jù)
什么是進(jìn)程?進(jìn)程 = 程序 + 執(zhí)行
進(jìn)程是執(zhí)行中的程序,除了可執(zhí)行代碼外還包含進(jìn)程的活動(dòng)信息和數(shù)據(jù),比如用來(lái)存放函數(shù)變量、局部變量、返回值的用戶(hù)棧,存放進(jìn)程相關(guān)數(shù)據(jù)的數(shù)據(jù)段,內(nèi)核中進(jìn)程間切換的內(nèi)核棧,動(dòng)態(tài)分配的堆。
進(jìn)程是系統(tǒng)分配資源的基本單位(內(nèi)存、CPU時(shí)間片)
進(jìn)程是用來(lái)實(shí)現(xiàn)多進(jìn)程并發(fā)執(zhí)行的一個(gè)實(shí)體,實(shí)現(xiàn)對(duì)CPU的虛擬化,讓每個(gè)進(jìn)程感覺(jué)都擁有一個(gè)CPU,核心技術(shù)就是上下文切換和進(jìn)程調(diào)度。
早期操作系統(tǒng)程序都是單個(gè)運(yùn)行的,CPU利用率低下,為了提高CPU的利用率,加載多個(gè)程序到內(nèi)存并發(fā)運(yùn)行,在單核CPU中這種屬于偽并發(fā)。
其實(shí)在同一時(shí)間只運(yùn)行一個(gè)程序
0q2ntwqaodt640133689456.png (38.24 KB, 下載次數(shù): 4)
下載附件
保存到相冊(cè)
0q2ntwqaodt640133689456.png
6 天前 上傳
進(jìn)程控制塊描述符進(jìn)程控制塊描述符task_struct主要包含:
進(jìn)程狀態(tài)(state):表示進(jìn)程當(dāng)前的狀態(tài),比如運(yùn)行、睡眠、停止等。
/* Used in tsk->__state: */
#define TASK_RUNNING 0x00000000
#define TASK_INTERRUPTIBLE 0x00000001
#define TASK_UNINTERRUPTIBLE 0x00000002
#define __TASK_STOPPED 0x00000004
#define __TASK_TRACED 0x00000008
/* Used in tsk->exit_state: */
#define EXIT_DEAD 0x00000010
#define EXIT_ZOMBIE 0x00000020
#define EXIT_TRACE (EXIT_ZOMBIE | EXIT_DEAD)
進(jìn)程調(diào)度信息(sched_info):包括進(jìn)程的調(diào)度策略、優(yōu)先級(jí)等信息
int on_rq;
int prio;
int static_prio;
int normal_prio;
unsigned int rt_priority;
struct sched_entity se;
struct sched_rt_entity rt;
struct sched_dl_entity dl;
struct sched_dl_entity *dl_server;
const struct sched_class *sched_class;on_rq:表示進(jìn)程是否在就緒隊(duì)列中,即是否正在等待被調(diào)度執(zhí)行。
prio:表示進(jìn)程的動(dòng)態(tài)優(yōu)先級(jí)。
static_prio:表示進(jìn)程的靜態(tài)優(yōu)先級(jí)。
normal_prio:表示進(jìn)程的普通優(yōu)先級(jí)。
rt_priority:表示實(shí)時(shí)進(jìn)程的優(yōu)先級(jí)。
se:sched_entity 結(jié)構(gòu)體,用于普通進(jìn)程的調(diào)度實(shí)體。
rt:sched_rt_entity 結(jié)構(gòu)體,用于實(shí)時(shí)進(jìn)程的調(diào)度實(shí)體。
dl:sched_dl_entity 結(jié)構(gòu)體,用于周期性實(shí)時(shí)進(jìn)程的調(diào)度實(shí)體。
dl_server:指向調(diào)度該進(jìn)程的周期性實(shí)時(shí)進(jìn)程的指針。
sched_class:指向調(diào)度類(lèi)(sched_class)的指針,用于確定進(jìn)程的調(diào)度策略和行為。
進(jìn)程標(biāo)識(shí)符(pid):唯一標(biāo)識(shí)一個(gè)進(jìn)程的數(shù)字標(biāo)識(shí)符,內(nèi)核使用bitmap保證進(jìn)程分配唯一的pid。
一個(gè)線程組中所有的線程使用和線程組組長(zhǎng)相同的pid,它會(huì)被存進(jìn)tgid中
使用getpid()系統(tǒng)調(diào)用獲取pid
pid_t pid;
pid_t tgid;進(jìn)程堆棧(stack):用于保存進(jìn)程的函數(shù)調(diào)用棧信息。
void *stack;引用計(jì)數(shù)(usage):用于跟蹤進(jìn)程的引用計(jì)數(shù),確保在不再需要時(shí)能夠正確釋放資源。
refcount_t usage;進(jìn)程標(biāo)志位(flags):存儲(chǔ)進(jìn)程的各種標(biāo)志位信息,比如是否在運(yùn)行、是否被掛起等。
unsigned int flags;多處理器支持字段(on_cpu、wake_entry):用于處理多處理器環(huán)境下的調(diào)度和喚醒操作。
#ifdef CONFIG_SMP
int on_cpu;
struct __call_single_node wake_entry;
unsigned int wakee_flips;
unsigned long wakee_flip_decay_ts;
struct task_struct *last_wakee;
/*
* recent_used_cpu is initially set as the last CPU used by a task
* that wakes affine another task. Waker/wakee relationships can
* push tasks around a CPU where each wakeup moves to the next one.
* Tracking a recently used CPU allows a quick search for a recently
* used CPU that may be idle.
*/
int recent_used_cpu;
int wake_cpu;
#endif進(jìn)程間家庭關(guān)系
/*
* Pointers to the (original) parent process, youngest child, younger sibling,
* older sibling, respectively. (p->father can be replaced with
* p->real_parent->pid)
*/
/* Real parent process: */
struct task_struct __rcu *real_parent;
/* Recipient of SIGCHLD, wait4() reports: */
struct task_struct __rcu *parent;
/*
* Children/sibling form the list of natural children:
*/
struct list_head children;
struct list_head sibling;
struct task_struct *group_leader;
進(jìn)程的5種狀態(tài)創(chuàng)建態(tài)(New):當(dāng)進(jìn)程剛被創(chuàng)建時(shí),處于創(chuàng)建態(tài)。在這個(gè)階段,操作系統(tǒng)正在為進(jìn)程分配資源和初始化進(jìn)程控制塊等信息。
就緒態(tài)(Ready):進(jìn)程已經(jīng)準(zhǔn)備好運(yùn)行,但由于還未獲得處理器資源,暫時(shí)無(wú)法執(zhí)行。進(jìn)程在就緒隊(duì)列中等待被調(diào)度執(zhí)行。
運(yùn)行態(tài)(Running):進(jìn)程正在執(zhí)行指令,占用 CPU 資源。在任意時(shí)刻,每個(gè) CPU 上只能有一個(gè)進(jìn)程處于運(yùn)行態(tài)。
阻塞態(tài)(Blocked):進(jìn)程由于等待某種事件(如 I/O 操作完成、信號(hào)量變?yōu)榉橇愕龋┒鴷簳r(shí)無(wú)法繼續(xù)執(zhí)行,進(jìn)入阻塞態(tài)。在等待期間,進(jìn)程不占用 CPU 資源。
終止態(tài)(Terminated):進(jìn)程執(zhí)行完畢或被操作系統(tǒng)終止后,進(jìn)入終止態(tài)。在終止態(tài)下,進(jìn)程的資源被釋放,但仍保留進(jìn)程控制塊等信息,直到被操作系統(tǒng)回收。
d0umtjrlsti640133689556.png (125.38 KB, 下載次數(shù): 5)
下載附件
保存到相冊(cè)
d0umtjrlsti640133689556.png
6 天前 上傳
查看進(jìn)程狀態(tài)
static void show_task(struct task_struct *volatile tsk)
{
unsigned int p_state = READ_ONCE(tsk->__state);
char state;
/*
* Cloned from kdb_task_state_char(), which is not entirely
* appropriate for calling from xmon. This could be moved
* to a common, generic, routine used by both.
*/
state = (p_state == TASK_RUNNING) ? 'R' :
(p_state & TASK_UNINTERRUPTIBLE) ? 'D' :
(p_state & TASK_STOPPED) ? 'T' :
(p_state & TASK_TRACED) ? 'C' :
(tsk->exit_state & EXIT_ZOMBIE) ? 'Z' :
(tsk->exit_state & EXIT_DEAD) ? 'E' :
(p_state & TASK_INTERRUPTIBLE) ? 'S' : '?';
printf("%16px %16lx %16px %6d %6d %c %2d %s
", tsk,
tsk->thread.ksp, tsk->thread.regs,
tsk->pid, rcu_dereference(tsk->parent)->pid,
state, task_cpu(tsk),
tsk->comm);
}
init_task
初始化了 init_task 結(jié)構(gòu)體的各個(gè)成員,包括線程信息、棧信息、調(diào)度優(yōu)先級(jí)、CPU 信息、內(nèi)存管理、信號(hào)處理、文件系統(tǒng)等等。
這些成員變量記錄了進(jìn)程的狀態(tài)、資源分配、調(diào)度信息等重要內(nèi)容。
struct task_struct init_task __aligned(L1_CACHE_BYTES) = {
.__state = 0,
.stack = init_stack,
.usage = REFCOUNT_INIT(2),
.flags = PF_KTHREAD,
.prio = MAX_PRIO - 20,
.static_prio = MAX_PRIO - 20,
.normal_prio = MAX_PRIO - 20,
.policy = SCHED_NORMAL,
.cpus_ptr = &init_task.cpus_mask,
.user_cpus_ptr = NULL,
.cpus_mask = CPU_MASK_ALL,
.nr_cpus_allowed= NR_CPUS,
.mm = NULL,
.active_mm = &init_mm,
.faults_disabled_mapping = NULL,
.restart_block = {
.fn = do_no_restart_syscall,
},
.se = {
.group_node = LIST_HEAD_INIT(init_task.se.group_node),
},
.rt = {
.run_list = LIST_HEAD_INIT(init_task.rt.run_list),
.time_slice = RR_TIMESLICE,
},
.tasks = LIST_HEAD_INIT(init_task.tasks),
.ptraced = LIST_HEAD_INIT(init_task.ptraced),
.ptrace_entry = LIST_HEAD_INIT(init_task.ptrace_entry),
.real_parent = &init_task,
.parent = &init_task,
.children = LIST_HEAD_INIT(init_task.children),
.sibling = LIST_HEAD_INIT(init_task.sibling),
.group_leader = &init_task,
RCU_POINTER_INITIALIZER(real_cred, &init_cred),
RCU_POINTER_INITIALIZER(cred, &init_cred),
.comm = INIT_TASK_COMM,
.thread = INIT_THREAD,
.fs = &init_fs,
.files = &init_files,
.signal = &init_signals,
.sighand = &init_sighand,
.nsproxy = &init_nsproxy,
.pending = {
.list = LIST_HEAD_INIT(init_task.pending.list),
.signal = {{0}}
},
.blocked = {{0}},
.alloc_lock = __SPIN_LOCK_UNLOCKED(init_task.alloc_lock),
.journal_info = NULL,
INIT_CPU_TIMERS(init_task)
.pi_lock = __RAW_SPIN_LOCK_UNLOCKED(init_task.pi_lock),
.timer_slack_ns = 50000, /* 50 usec default slack */
.thread_pid = &init_struct_pid,
.thread_node = LIST_HEAD_INIT(init_signals.thread_head),
INIT_PREV_CPUTIME(init_task)
};
EXPORT_SYMBOL(init_task);
進(jìn)程創(chuàng)建函數(shù)
vp4u0flqegz640133689656.png (33.24 KB, 下載次數(shù): 4)
下載附件
保存到相冊(cè)
vp4u0flqegz640133689656.png
6 天前 上傳
fork
fork函數(shù)用于創(chuàng)建一個(gè)新的進(jìn)程,新進(jìn)程是調(diào)用進(jìn)程(父進(jìn)程)的副本。
函數(shù)名稱(chēng):fork
頭文件:#include
返回類(lèi)型:pid_t(進(jìn)程ID類(lèi)型)
參數(shù):無(wú)參數(shù)
返回值:在父進(jìn)程中,fork返回新創(chuàng)建子進(jìn)程的進(jìn)程ID(PID),在子進(jìn)程中,fork返回0。如果出現(xiàn)錯(cuò)誤,fork返回-1。
通過(guò)調(diào)用fork函數(shù),父進(jìn)程會(huì)創(chuàng)建一個(gè)子進(jìn)程,子進(jìn)程會(huì)繼承父進(jìn)程的數(shù)據(jù)、堆棧、文件描述符等信息,但是它們各自有獨(dú)立的內(nèi)存空間。
vfork
vfork函數(shù)用于創(chuàng)建一個(gè)新的進(jìn)程,但與fork不同的是,vfork保證子進(jìn)程先運(yùn)行,調(diào)用do_fork時(shí)比f(wàn)ork多了兩個(gè)標(biāo)志位,
CLONE_VFORK和CLONE_VM,分別代表父進(jìn)程被掛起,直到子進(jìn)程釋放資源和父子進(jìn)程運(yùn)行在相同的內(nèi)存空間。
函數(shù)名稱(chēng):vfork
頭文件:#include
返回類(lèi)型:pid_t(進(jìn)程ID類(lèi)型)
參數(shù):無(wú)參數(shù)
返回值:在父進(jìn)程中,vfork返回新創(chuàng)建子進(jìn)程的進(jìn)程ID(PID),在子進(jìn)程中,vfork返回0。如果出現(xiàn)錯(cuò)誤,vfork返回-1。
clone
clone函數(shù)用于創(chuàng)建一個(gè)新的線程或進(jìn)程,可以指定不同的選項(xiàng)來(lái)控制創(chuàng)建的行為
int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ... /* pid_t *ptid, unsigned long newtls, pid_t *ctid */ );
函數(shù)名稱(chēng):clone
頭文件:#include
返回類(lèi)型:int
參數(shù):
fn:指向新線程/進(jìn)程入口點(diǎn)函數(shù)的指針
child_stack:子進(jìn)程/線程的棧指針
flags:用于指定創(chuàng)建新線程/進(jìn)程的選項(xiàng)
arg:傳遞給新線程/進(jìn)程入口點(diǎn)函數(shù)的參數(shù)
...:可選參數(shù),包括ptid、newtls和ctid
返回值:成功時(shí)返回新線程/進(jìn)程的PID(對(duì)于線程,返回0表示成功),失敗時(shí)返回-1。
kthread_create
kthread_create函數(shù)用于創(chuàng)建一個(gè)新的內(nèi)核線程,該線程在內(nèi)核空間中運(yùn)行,可以執(zhí)行內(nèi)核級(jí)別的任務(wù)。
通過(guò)調(diào)用kthread_create函數(shù),可以在Linux內(nèi)核中創(chuàng)建一個(gè)新的內(nèi)核線程,用于執(zhí)行后臺(tái)任務(wù)、定時(shí)任務(wù)等內(nèi)核級(jí)別的工作。內(nèi)核線程與用戶(hù)空間的線程有所不同,它們?cè)趦?nèi)核空間中運(yùn)行,可以訪問(wèn)內(nèi)核數(shù)據(jù)結(jié)構(gòu)和執(zhí)行特權(quán)操作。
struct task_struct *kthread_create(int (*threadfn)(void *data), void *data, const char namefmt[], ...);
函數(shù)名稱(chēng):kthread_create
返回類(lèi)型:struct task_struct *(指向內(nèi)核線程結(jié)構(gòu)體的指針)
參數(shù):threadfn:指向內(nèi)核線程函數(shù)的指針,即內(nèi)核線程的入口點(diǎn)函數(shù)
data:傳遞給內(nèi)核線程函數(shù)的參數(shù)
namefmt:內(nèi)核線程的名稱(chēng)格式字符串
...:可變參數(shù),用于指定內(nèi)核線程的調(diào)度優(yōu)先級(jí)等其他選項(xiàng)
功能:
返回值:成功時(shí)返回指向新創(chuàng)建內(nèi)核線程的task_struct結(jié)構(gòu)體指針,失敗時(shí)返回NULL。
do_fork
fork/vfork/clone/kthread_create底層都是通過(guò)調(diào)用do_fork創(chuàng)建進(jìn)程
long do_fork(unsigned long clone_flags,unsigned long stack_start, unsigned long stack_size,int __user *parent_tidptr,int __user *child_tidptr)
{
return _do_fork(clone_flags, stack_start, stack_size,
parent_tidptr, child_tidptr, 0);
}
clone_flags:用于指定創(chuàng)建新進(jìn)程/線程的選項(xiàng),包括是否共享地址空間、文件描述符等。
stack_start:新進(jìn)程/線程的棧起始地址。
stack_size:新進(jìn)程/線程的棧大小。
parent_tidptr:指向父進(jìn)程/線程的線程ID的指針。
child_tidptr:指向子進(jìn)程/線程的線程ID的指針。
子進(jìn)程不會(huì)繼承的一些主要屬性和資源:
進(jìn)程ID(PID):子進(jìn)程會(huì)有自己獨(dú)立的進(jìn)程ID,不會(huì)繼承父進(jìn)程的PID。
父進(jìn)程ID(PPID):子進(jìn)程的父進(jìn)程ID會(huì)被設(shè)置為創(chuàng)建它的父進(jìn)程的PID,而不是繼承父進(jìn)程的PPID。
信號(hào)處理器:子進(jìn)程不會(huì)繼承父進(jìn)程設(shè)置的信號(hào)處理器,它們會(huì)有各自獨(dú)立的信號(hào)處理器。
文件鎖:子進(jìn)程不會(huì)繼承父進(jìn)程設(shè)置的文件鎖。
定時(shí)器:子進(jìn)程不會(huì)繼承父進(jìn)程設(shè)置的定時(shí)器。
共享內(nèi)存和信號(hào)量:子進(jìn)程不會(huì)繼承父進(jìn)程的共享內(nèi)存和信號(hào)量。
資源限制:子進(jìn)程不會(huì)繼承父進(jìn)程設(shè)置的資源限制,如文件打開(kāi)數(shù)限制等。
execve:
功能:execve系統(tǒng)調(diào)用用于加載并執(zhí)行一個(gè)新的程序,替換當(dāng)前進(jìn)程的映像(代碼和數(shù)據(jù))為新程序的映像。
參數(shù):execve接受三個(gè)參數(shù),分別是要執(zhí)行的程序路徑、命令行參數(shù)數(shù)組和環(huán)境變量數(shù)組。
返回值:如果execve執(zhí)行成功,則不會(huì)返回,因?yàn)楫?dāng)前進(jìn)程的映像已被替換為新程序的映像;如果出現(xiàn)錯(cuò)誤,則返回-1。
特點(diǎn):execve會(huì)將當(dāng)前進(jìn)程的映像替換為新程序的映像,新程序開(kāi)始執(zhí)行時(shí),會(huì)繼承當(dāng)前進(jìn)程的PID等信息,但不會(huì)保留原有進(jìn)程的任何狀態(tài)。
寫(xiě)時(shí)復(fù)制技術(shù)在傳統(tǒng)的unix操作系統(tǒng)中,創(chuàng)建新進(jìn)程時(shí)會(huì)復(fù)制父進(jìn)程所擁有的資源,但是子進(jìn)程不一定需要父進(jìn)程的全部資源。
在現(xiàn)代的操作系統(tǒng)中采用了寫(xiě)時(shí)復(fù)制copy on write,COW技術(shù),在創(chuàng)建子進(jìn)程時(shí)只需要復(fù)制進(jìn)程的地址空間頁(yè)表,
只讀共享進(jìn)程地址空間,當(dāng)父子進(jìn)程其中一方需要修改頁(yè)面數(shù)據(jù)時(shí),觸發(fā)缺頁(yè)異常,此時(shí)才會(huì)從復(fù)制內(nèi)容。
終止進(jìn)程1.程序主動(dòng)主動(dòng)調(diào)用exit退出
2.進(jìn)程收到SIGKILL信號(hào)
kill -15 PID # 發(fā)送SIGTERM信號(hào)
kill -9 PID # 發(fā)送SIGKILL信號(hào)
3.觸發(fā)內(nèi)核異常
4.收到不能處理的信號(hào)
僵尸進(jìn)程和孤兒進(jìn)程僵尸進(jìn)程:
定義:當(dāng)一個(gè)進(jìn)程終止,但其父進(jìn)程沒(méi)有及時(shí)處理該進(jìn)程的終止?fàn)顟B(tài)信息(稱(chēng)為SIGCHLD信號(hào)),導(dǎo)致該進(jìn)程的進(jìn)程描述符仍然存在,但進(jìn)程已經(jīng)終止,此時(shí)該進(jìn)程就成為僵尸進(jìn)程。
特點(diǎn):僵尸進(jìn)程不占用系統(tǒng)資源,但會(huì)占用進(jìn)程表中的一個(gè)條目。
解決方法:父進(jìn)程應(yīng)該及時(shí)處理SIGCHLD信號(hào),通過(guò)調(diào)用wait()或waitpid()等系統(tǒng)調(diào)用來(lái)回收子進(jìn)程的資源,防止子進(jìn)程變成僵尸進(jìn)程。
孤兒進(jìn)程:
定義:當(dāng)一個(gè)進(jìn)程的父進(jìn)程提前終止,而該進(jìn)程本身還在運(yùn)行,此時(shí)該進(jìn)程成為孤兒進(jìn)程。
特點(diǎn):孤兒進(jìn)程會(huì)被init進(jìn)程(PID為1)接管,init進(jìn)程會(huì)成為孤兒進(jìn)程的新父進(jìn)程。
影響:孤兒進(jìn)程的父進(jìn)程終止后,孤兒進(jìn)程會(huì)繼續(xù)運(yùn)行,直到自己終止或被init進(jìn)程接管。
0號(hào)進(jìn)程**0、1號(hào)進(jìn)程代碼來(lái)源0.11版本內(nèi)核**
0號(hào)進(jìn)程通常指的是內(nèi)核線程(kernel thread)或者是調(diào)度進(jìn)程(scheduler process),其PID為0。這個(gè)進(jìn)程在系統(tǒng)啟動(dòng)時(shí)就已經(jīng)存在,并且在整個(gè)系統(tǒng)運(yùn)行期間都存在。
0號(hào)進(jìn)程通常被稱(chēng)為內(nèi)核線程,因?yàn)樗趦?nèi)核空間運(yùn)行,不屬于用戶(hù)空間的任何進(jìn)程。它在系統(tǒng)中扮演著重要的角色,負(fù)責(zé)系統(tǒng)的調(diào)度、內(nèi)存管理、I/O操作等核心功能。由于它是內(nèi)核的一部分,因此沒(méi)有對(duì)應(yīng)的用戶(hù)空間程序,也不會(huì)被用戶(hù)直接創(chuàng)建或終止。
在Linux系統(tǒng)中,0號(hào)進(jìn)程通常是系統(tǒng)中所有進(jìn)程的祖先,即所有進(jìn)程的父進(jìn)程。當(dāng)一個(gè)進(jìn)程的父進(jìn)程終止時(shí),該進(jìn)程會(huì)成為孤兒進(jìn)程,并被0號(hào)進(jìn)程(init進(jìn)程,PID為1)接管。
sched_init(); // 初始化0進(jìn)程
void sched_init(void)
{
int i;
struct desc_struct * p;
if (sizeof(struct sigaction) != 16)
panic("Struct sigaction MUST be 16 bytes");
set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss)); // 設(shè)置TSS
set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.ldt)); // 設(shè)置LDT
p = gdt+2+FIRST_TSS_ENTRY; // 獲取TSS
for(i=1;ia=p->b=0;
p++;
p->a=p->b=0;
p++;
}
/* Clear NT, so that we won't have troubles with that later on */
__asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl"); // 清空NT
ltr(0); // 掛載TSS到TR寄存器
lldt(0); // 掛載LDTR寄存器
// 設(shè)置定時(shí)器模式、以及設(shè)置高低位組成一個(gè)周期
outb_p(0x36,0x43); /* binary, mode 3, LSB/MSB, ch 0 */
outb_p(LATCH & 0xff , 0x40); /* LSB */
outb(LATCH >> 8 , 0x40); /* MSB */
set_intr_gate(0x20,&timer_interrupt); // 開(kāi)啟定時(shí)器中斷
outb(inb_p(0x21)&~0x01,0x21); // 允許時(shí)鐘中斷
set_system_gate(0x80,&system_call); // 設(shè)置系統(tǒng)調(diào)用的入口
}
1號(hào)進(jìn)程在Linux系統(tǒng)中,1號(hào)進(jìn)程通常指的是init進(jìn)程,其PID為1。init進(jìn)程是系統(tǒng)中所有進(jìn)程的祖先進(jìn)程,是系統(tǒng)啟動(dòng)時(shí)由內(nèi)核創(chuàng)建的第一個(gè)用戶(hù)級(jí)進(jìn)程。init進(jìn)程負(fù)責(zé)系統(tǒng)的初始化、進(jìn)程的管理和系統(tǒng)的關(guān)機(jī)等任務(wù)。
void main(void) /* This really IS void, no error here. */
{ /* The startup routine assumes (well, ...) this */
mem_init(main_memory_start,memory_end); // 初始化內(nèi)存映射
trap_init(); // 初始化中斷捕獲
blk_dev_init(); // 塊設(shè)備初始化
chr_dev_init(); // 字符設(shè)備初始化
tty_init(); // 終端初始化
time_init(); // 時(shí)間初始化
sched_init(); // 初始化0進(jìn)程
buffer_init(buffer_memory_end); // 緩沖區(qū)初始化
hd_init(); // 初始化硬盤(pán)
floppy_init(); // 初始化軟盤(pán)
sti(); // 開(kāi)啟全局中斷
move_to_user_mode(); // 將進(jìn)程0特權(quán)調(diào)到3級(jí)
if (!fork()) { /* we count on this going ok */
init(); // 子進(jìn)程進(jìn)行初始化
}
void init(void)
{
int pid,i; // pid用于fork
setup((void *) &drive_info); // 配置系統(tǒng),包括磁盤(pán)、文件系統(tǒng)
(void) open("/dev/tty0",O_RDWR,0); // 打開(kāi)tty文件,此時(shí)是標(biāo)準(zhǔn)輸入設(shè)備文件
(void) dup(0); // 從tty復(fù)制句柄,打開(kāi)標(biāo)準(zhǔn)輸出設(shè)備文件
(void) dup(0); // 繼續(xù)復(fù)制句柄,打開(kāi)標(biāo)準(zhǔn)錯(cuò)誤輸出設(shè)備
printf("%d buffers = %d bytes buffer space
\r",NR_BUFFERS,
NR_BUFFERS*BLOCK_SIZE);
printf("Free mem: %d bytes
\r",memory_end-main_memory_start);
if (!(pid=fork())) { // 到這里就要啟動(dòng)進(jìn)程2了
// fs/open.c
close(0); // 進(jìn)程2關(guān)閉輸入
if (open("/etc/rc",O_RDONLY,0)) // 使用/etc/rc替換輸入設(shè)備,加載一些開(kāi)機(jī)需要執(zhí)行的東西
_exit(1); // 替換失敗就寄了
// do_execve(fs/exec.c)
execve("/bin/sh",argv_rc,envp_rc); // 執(zhí)行shell,參數(shù)分別是shell執(zhí)行參數(shù)(="NULL")其環(huán)境變量(="/")
// 由于輸入已經(jīng)改成了/etc/rc文件了,所以這里在運(yùn)行/etc/rc的內(nèi)容
_exit(2);
}
if (pid>0) // 進(jìn)程1暫停工作,等待子進(jìn)程工作完成(子進(jìn)程只有進(jìn)程2)
while (pid != wait(&i)) // 暫不深入wait -> 補(bǔ)充: 進(jìn)程2退出了,回到了這里,pid = 2
/* nothing */;
while (1) {
if ((pid=fork()) |
|