電子產(chǎn)業(yè)一站式賦能平臺(tái)

PCB聯(lián)盟網(wǎng)

搜索
查看: 21|回復(fù): 0
收起左側(cè)

一文讀懂什么是進(jìn)程

[復(fù)制鏈接]

277

主題

277

帖子

2400

積分

三級(jí)會(huì)員

Rank: 3Rank: 3

積分
2400
跳轉(zhuǎn)到指定樓層
樓主
什么是程序?程序:可執(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è)程序

進(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è)線(xiàn)程組中所有的線(xiàn)程使用和線(xiàn)程組組長(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)回收。



查看進(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è)成員,包括線(xiàn)程信息、棧信息、調(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ù)

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è)新的線(xiàn)程或進(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:指向新線(xiàn)程/進(jìn)程入口點(diǎn)函數(shù)的指針
child_stack:子進(jìn)程/線(xiàn)程的棧指針
flags:用于指定創(chuàng)建新線(xiàn)程/進(jìn)程的選項(xiàng)
arg:傳遞給新線(xiàn)程/進(jìn)程入口點(diǎn)函數(shù)的參數(shù)
...:可選參數(shù),包括ptid、newtls和ctid
返回值:成功時(shí)返回新線(xiàn)程/進(jìn)程的PID(對(duì)于線(xiàn)程,返回0表示成功),失敗時(shí)返回-1。

kthread_create
kthread_create函數(shù)用于創(chuàng)建一個(gè)新的內(nèi)核線(xiàn)程,該線(xiàn)程在內(nèi)核空間中運(yùn)行,可以執(zhí)行內(nèi)核級(jí)別的任務(wù)。
通過(guò)調(diào)用kthread_create函數(shù),可以在Linux內(nèi)核中創(chuàng)建一個(gè)新的內(nèi)核線(xiàn)程,用于執(zhí)行后臺(tái)任務(wù)、定時(shí)任務(wù)等內(nèi)核級(jí)別的工作。內(nèi)核線(xiàn)程與用戶(hù)空間的線(xiàn)程有所不同,它們?cè)趦?nèi)核空間中運(yùn)行,可以訪(fǎng)問(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)核線(xiàn)程結(jié)構(gòu)體的指針)
參數(shù):threadfn:指向內(nèi)核線(xiàn)程函數(shù)的指針,即內(nèi)核線(xiàn)程的入口點(diǎn)函數(shù)
data:傳遞給內(nèi)核線(xiàn)程函數(shù)的參數(shù)
namefmt:內(nèi)核線(xiàn)程的名稱(chēng)格式字符串
...:可變參數(shù),用于指定內(nèi)核線(xiàn)程的調(diào)度優(yōu)先級(jí)等其他選項(xiàng)
功能:
返回值:成功時(shí)返回指向新創(chuàng)建內(nèi)核線(xiàn)程的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àn)程的選項(xiàng),包括是否共享地址空間、文件描述符等。
stack_start:新進(jìn)程/線(xiàn)程的棧起始地址。
stack_size:新進(jìn)程/線(xiàn)程的棧大小。
parent_tidptr:指向父進(jìn)程/線(xiàn)程的線(xiàn)程ID的指針。
child_tidptr:指向子進(jìn)程/線(xiàn)程的線(xià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)核線(xiàn)程(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)核線(xiàn)程,因?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())

發(fā)表回復(fù)

本版積分規(guī)則


聯(lián)系客服 關(guān)注微信 下載APP 返回頂部 返回列表