欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

進程、輕量級進程(LWP)、線程

系統 1911 0

轉載自:http://blog.chinaunix.net/u2/78225/showart_1761586.html

?

進程、輕量級進程(LWP)、線程

進程、輕量級進程(LWP)、線程
  • 進程:程序執行體,有生命期,用來分配資源的實體
  • 線程:分配CPU的實體。
    • ??用戶空間實現,一個線程阻塞,所有都阻塞。
    • ??內核實現,不會所用相關線程都阻塞。用LWP實現,用線程組表示這些線程邏輯上所屬的進程。
進程描述符
  • 進程描述符(簡稱pd, process descriptors),結構體是:task_struct
    • ??數據較多,存放在kenerl的動態內存空間。
    • ??pd的引用放在thread_info中,
      • ? ?thread_info與內核棧,放在一個8K空間(它的地址8K對齊)。內核程序使用的棧空間很小。
      • ? ?thread_info在底部,內核棧在頂部向下增長。
        • ? ? 好處:多CPU時方便,每個CPU根據自己的棧指針就可以找到當前的pd (以后用current表示當前CPU運行的進程描述符)。
          • ? ???esp(內核棧指針)低8位置零,就是thread_info地址。
      • ? ?每進程有自己的thread_info, (分配釋放函數: alloc_thread_info, free_thread_info)
  • 描述符的內容
    • ??相關的ID (一個4元素數組)
      • ? ?進程ID (PID)
        • ? ? PID按創建順序連續增長,到最大值后從最小值開始。
        • ? ? 0號進程:交換進程(swapper)
        • ? ? 有PID可用位圖,表示那一個PID可用,至少占一個頁。
      • ? ?線程組ID(tgid),用LWP實現多線程支持
        • ? ? 多進程時,進程id,就是線程組id, 也就是組長的pid(LWP)。 getpid() 取的是線程組的id(tgid), 也是組長的pid.
        • ? ? 單線程時,pid = gid。所以getpid,也是真正的pid.
      • ? ?進程組ID(pgrp)。
      • ? ?回話的ID(session).
        • ? ? 組ID,都是組長的PID。FIXME: 但pb也有各組長的PID
          • ? ???線程組長:tgid
          • ? ???進程組長:signal->pgrp ,
          • ? ???會話長:signal->session
      • ? ?管理ID數據結構——哈希表管理 (利用id找到所用相關的pd,方便)。
        • ? ? 一個哈希表數組(pid_hash),存放四個哈希表, 每一個表代表一類id (pid, tgid, pgrp, session)
        • ? ? 每個哈希表的由數組(索引為哈希值)和二維鏈表(嵌入到進程描述符內的pids中)實現
          • ? ???第一維鏈表:哈希沖突鏈表。
          • ? ???第二維鏈表:要查找的值相同的鏈表, 叫per-PID list(同一組的所有線程,同一組的所有進程,同一會話的所有進程);
      • ? ?進程組ID(pgrp), 回話ID(session)在共享信號的數據結構里。因為同一進程內的所有LWP,這兩個ID都是一樣的
  • ?
    • ??家族關系:由pd里的鏈表(下級)和pd指針(上級)實現
      • ? ?關系:
        • ? ? 親生父親:創建自己的進程,或是托孤進程(創建自己的進程死了)。
        • ? ? 父親:自己死時要發信號告知的。一般是親生父親,有時是監控自己的進程 (調用ptrace)
        • ? ? 孩子:
        • ? ? 兄弟:
      • ? ?監控(自己起的名字,類似于監護。由于管理方式相同,也歸為家族關系)
        • ? ? 監控的進程列表:ptrace_children
        • ? ? 被監控的其他進程:ptrace_list (類似于被監控的兄弟)
      • ? ?在鏈表里為了管理方便:
        • ? ? 最大兒子的兄弟是父親
        • ? ? 最小兒子的弟弟也是父親
        • ? ? 父親保管最大兒子,和最小兒子
  • ?
    • ??進程資源及資源限制:
      • ? ?CPU相關:
        • ? ? 占用CPU總時間
        • ? ? 用戶的最大進程數
      • ? ?內存相關:
        • ? ? 進程地址空間
        • ? ? 鎖住內存大小
        • ? ? 進程頁數 (只有記錄,沒有限制)
        • ? ? 堆大小,棧大小
      • ? ?資源相關:
        • ? ? 文件:
          • ? ???core dump大小
          • ? ???最大文件大小
          • ? ???打開文件個數
        • ? ? 進程同步與通信
          • ? ???鎖數目,
          • ? ???懸掛信號數據
          • ? ???在消息列隊中占的大小
      • ? ?相關數據結構 和 處理流程
        • ? ? pd->sigal->rlim 是一個 表示進程資源使用情況以及限制的結構 的數組。
        • ? ? 表示進程資源使用情況以及限制的結構:包含當前值,最大值兩個數值。
      • ? ?只有超級用戶才能增大資源限制。
      • ? ?一般用戶登陸時:
        • ? ? kernel創建root進程,減少limit,
        • ? ? 建一個 shell子進程,繼承limit.
        • ? ? 把shell進程的用戶,改成登陸的那個用戶
  • ?
    • ??進程狀態(state)
      • ? ?運行,TASK_RUNNING
        • ? ? 組織pd的結構:就緒進程鏈:
          • ? ???一個CPU一組鏈表,每個鏈表表示一種優先級。
      • ? ?阻塞
        • ? ? 可中斷阻塞,TASK_INTERRUPTIBLE
          • ? ???可被硬件中斷,“釋放資源”事件,信號喚醒。
        • ? ? 不可中斷阻塞,TASK_UNINTERRUPTIBLE
          • ? ???可被硬件中斷,“釋放資源”事件,喚醒。
          • ? ???但不能被信號喚醒。可用于驅動程序中。
        • ? ? 組織pb的結構:等待列隊: 每一類事件一個列隊,用內嵌鏈表實現(雖然沒列出內嵌鏈表節點)
          • ? ???列隊頭:
            • ? ?? ?自旋鎖:防止有一個主函數和中斷函數同時操作列隊。
          • ? ???列隊節點:
            • ? ?? ?獨占標志:表示該進程是否要獨占資源 (不再喚醒別的進程)
            • ? ?? ?指向pd的指針
            • ? ?? ?用于喚醒進程的回調函數。(提供進程的執行機會,是否操作等待列隊由用戶決定)
      • ? ?停止
        • ? ? 停止TASK_STOPPED
          • ? ???被信號停止
        • ? ? 追蹤TASK_TRACED
          • ? ???該進程被一個調試進程監控以后,收到任何一個信號就進入該狀態
        • ? ? 組織pb的結構:FIXME: 信號的等待列隊?
      • ? ?退出
        • ? ? 退出_僵尸EXIT_ZOMBIE
          • ? ???進程終止,資源沒有被回收(父進程要用,沒有調wait系列函數)
        • ? ? 退出_死亡EXIT_DEAD
          • ? ???進程終止,資源正在被回收(父進程要用,沒有調wait系列函數)。
          • ? ???一旦資源回收完成,進程描述符也就被回收了。
          • ? ???它防止該進程再次被wait.
        • ? ? 組織pb的結構:不掛到隊列上,只在家族關系中,等待父進程收回資源
程控制
  • 阻塞(current阻塞到某個列隊上):
    • ??基本流程
      • ? ?臨時生成一個列隊節點,初始化。
      • ? ?改變current的狀態,放入節點,掛到列隊上。
      • ? ?調度 (=====》至此,阻塞完成。 一旦被別的進程喚醒====》從調度函數中返回)
      • ? ?從等待列隊上摘除節點。
    • ??變化:
      • ? ?將掛列隊、調度、從列隊刪除三步拆開,便于靈活處理。
      • ? ?可中斷的、限時、獨占的函數類似。只不過進程狀態、調度函數、獨占標志不同。
      • ? ?非獨占的從列隊開始添加,獨占的從末尾添加。(但一個列隊內既有獨占的,又有非獨占的等待進程,很少見)
  • 喚醒:
    • ??基本流程
      • ? ?喚醒一個進程:調用節點里的回調函數
      • ? ?喚醒的時候從列隊開頭依次喚醒,直到喚醒一個獨占的后停止。
    • ??變化
      • ? ?是否只喚醒可中斷的進程. (_interruptible后綴)
      • ? ?喚醒的獨占進程的數目(1個,多個(_nr后綴),所有(_all后綴))
      • ? ?喚醒后是否不檢查優先級,馬上給予CPU (有_sync的不檢查優先級)。
  • 進程切換
    • ??切換pgd (全局頁目錄),此章不討論。
    • ??切換內核棧,硬件上下文
      • ? ?硬件上下文,就是CPU的寄存器。
        • ? ? 一部分(大多數CPU寄存器(除了通用寄存器))在pd中保存(task_struct->thread, 類型是thread_struct),
        • ? ? 一部分(通用寄存器)保存在內核棧中.
      • ? ?原來用硬件指令()保存CPU信息。后來改成軟件(一個個MOV指令)
        • ? ? 容易控制,可以挑選信息保存,便于優化。不保存的做其他用(如:進程間傳遞)
          • ? ?? ?? ? far jmp:跳至目標進程的TSSD。而linux是每個CPU一個TSS,不是每進程一個
        • ? ? 對于一些寄存器(ds、es)可以檢查值。
        • ? ? 與用硬件指令保存時間差不多。
    • ??switch_to 宏
      • ? ?三個參數:
        • ? ? prev: 要換走的進程,一般是當前進程
        • ? ? next: 要換到的進程。
        • ? ? last: 傳出參數。當前進程再次被換到時,最后一個占用CPU的進程。(prev指向的進程 就是 next指向的進程 的last)
      • ? ?步驟:
        • ? ? 棧切換, 完成后就是在新進程的上執行了:
          • ? ???保存prev(放在eax)
          • ? ???eflags,ebp入內核棧;
          • ? ???保存并裝載新的esp (舊的esp放到prev->thread.esp,新的esp是next->thread.esp)
            • ? ?? ?此時current就是新的esp所指的thread_info內的task指針
        • ? ? 設置返回地址:
          • ? ???prev進程以后得到執行時的__switch_to的返回地址: __switch_to后的第一條指令, 放入prev->thread.eip,
          • ? ???準備next進程的從__switch_to返回的地址: next->thread.eip入棧.
        • ? ? 調用__switch_to ()函數,該函數動作如下:
          • ? ???更新CPU的相關信息(tss和gdt):
            • ? ?? ?存next->thread.esp0(內核棧低)到本地TSS.esp0中。
            • ? ?? ?所在CPU的全局段表里的TLS段, 設成next進程的.
            • ? ?? ?更新tss的I/O位圖.
          • ? ???更新CPU的寄存器(pd->thread (tss) 與 CPU寄存器交換數據):
            • ? ?? ?保存FPU, MMX, XMM寄存器, 先不裝載以后需要時通過中斷裝載(TODO: )
            • ? ?? ?保存prev的fs, gs寄存器. 裝載next的
            • ? ?? ?裝載next的debug寄存器(debug寄存器一個8個, 進程切換時只需6個)
          • ? ???返回
            • ? ?? ?prev放入eax (prev就是新進程的last)
            • ? ?? ?ret
        • ? ? ret返回的地址: (__switch_to之前被存入棧中, __switch_to ret時進入eip)
          • ? ???如果是next新進程, next->thread.eip是iret_from_fork.
          • ? ???如果next不是新進程:
            • ? ?? ?彈出ebp, elfags
            • ? ?? ?把eax放入last變量 (prev就是next進程的last)
  • 任務狀態段(一個存CPU狀態的數組,tss_struct init_tss[])
    • ? ? 每個CPU用段上的一個元素。(FIXME: 用于:用戶模式要進入內核模式時,設置相應寄存器)
      • ? ?? ?TSS上存內核棧地址。CPU上的程序從用戶模式轉到內核模式,設置esp。
      • ? ?? ?TSS存I/O端口許可位圖。用戶模式程序用到I/O時,檢查有無權限
      • ? ?? ?所以,進程切換時,要保存的寄存器在pd->thread中。
        • ? ?? ???thread_struct不是thread_info。thread_info中只有少量的數據或指針, 用于通過esp快速定位數據
    • ? ? 進程切換時,更新TSS上的信息。
      • ? ?? ?CPU控制單元再從TSS上取需要的信息。
      • ? ?? ?即反應了CPU的當前進程情況,又不需要維護所有進程的狀態數據。
    • ? ? TSS的描述符在GDT里。
      • ? ?? ?TSSD:任務狀態段描述符 (其實應該叫任務狀態描述符,每個TSSD,表示一個CPU的狀態, FIXME: :具體以源碼為準)
      • ? ?? ?CPU原始設計,每個進程一個TSS元素。
      • ? ?? ?linux設計,每個CPU一個TSS元素。
      • ? ?? ?cpu里的tr寄存器,保存著自己的TSSD(即init_ttss[cpu_id]),不用總上gdt里去取。

您對本貼的看法: 鮮花[0] 臭蛋[0]
積分兌換專區 | IT節能和TPC-E活動獲獎名單 | 致電800-858-2903,了解DELL如何為你量身訂制筆記本 | 送2G U盤 | 站長如何獲得資金?
ninesunqian ?? 帥哥
俠客 UID:698749 注冊:2008-4-29 最后登錄: 2008-12-09 帖子: 49 精華:0 可用積分:85 (白手起家) 信譽積分:100 專家積分:0 (本版:0) 空間積分:1 推廣積分:0 狀態: ...離線...
[ 資料 ] [ 站內短信 ] [ Blog ]
2樓 發表于 2008-9-28 09:05?
進程創建: clone, fork, vfork系統調用
  • ??clone系統調用
    • ? ?參數:
      • ? ? 執行函數(fn), 參數(arg)
      • ? ? flags|死亡時給父進程發的信號 (clone_flags): 以下介紹clone_flags
        • ? ???資源共享
          • ? ?? ?段,頁,打開文件共享:
            • ? ?? ? 頁表(不是頁, CLONE_VM),
            • ? ?? ? 打開文件(clone_files),
            • ? ?? ? 建一個新tls段(clone_settls)
          • ? ?? ?路徑和權限設置:
            • ? ?? ? clone_fs: 共享根目錄, 當前目錄, 創建文件初始權限.
            • ? ?? ? clone_newns: 新的根路徑, 自己的視野看文件系統
          • ? ?? ?線程通信
            • ? ?? ? clone_sighand: 信號處理action, 阻塞和懸掛的信號
            • ? ?? ? clone_sysvsem: 共享undoable信號量操作
        • ? ???進程關系
          • ? ?? ?同父: clone_parent 創建進程與新進程是兄弟 (同父), 新進程不是創建進程的子進程
            • ? ?? ? 為了方便期間, 以下討論暫時不考慮這一因素(它很容易實現), 認為創建進程就是父進程
          • ? ?? ?同一個線程組: clone_thread. 屬于同一個進程(線程組)
          • ? ?? ?都被trace: clone_ptrace
          • ? ?? ?子進程不被trace: clone_untrace (內核設置, 覆蓋clone_ptrace)
        • ? ???返回tid
          • ? ?? ?向父進程返回tid: clone_parent_settid
          • ? ?? ?向子進程返回tid: clone_child_settid
        • ? ???子進程的狀態:
          • ? ?? ?子進程開始就stop: clone_stopped
        • ? ???進程死亡或exec通知:
          • ? ?? ?啟動內核機制: 如果子進程死亡或exec, 它自己空間內的tid(*ctid)清零, 并喚醒等待子進程死亡的進程.
      • ? ? 賦給子進程的資源
        • ? ???子進程的棧(父進程alloc的內存地址)
        • ? ???線程局部倉庫段(tls)
      • ? ? 返回子進程tid的地址
        • ? ???父進程用戶空間內的地址
        • ? ???子進程用戶空間的地址
  • ??clone, fork, vfork實現方式
    • ??大致相同:
      • ? ? 系統調用服務例程sys_clone, sys_fork, sys_vfork三者最終都是調用do_fork函數完成.
        • ? ? do_fork的參數與clone系統調用的參數類似, 不過多了一個regs(內核棧保存的用戶模式寄存器). 實際上其他的參數也都是用regs取的
    • ? ?區別在于:
      • ? ? clone:
        • ? ???clone的API外衣, 把fn, arg壓入用戶棧中, 然后引發系統調用. 返回用戶模式后下一條指令就是fn.
        • ? ???sysclone: parent_tidptr, child_tidptr都傳到了 do_fork的參數中
        • ? ???sysclone: 檢查是否有新的棧, 如果沒有就用父進程的棧 (開始地址就是regs.esp)
      • ? ? fork, vfork:
        • ? ???服務例程就是直接調用do_fork, 不過參數稍加修改
        • ? ???clone_flags:
          • ? ?? ?sys_fork: SIGCHLD|0;
          • ? ?? ?sys_vfork: SIGCHLD| (clone_vfork | clone_vm)
        • ? ???用戶棧: 都是父進程的棧.
        • ? ???parent_tidptr, child_ctidptr都是NULL.
  • 具體實現函數do_fork() (內核函數)的工作流程:
    • ??分配PID, 確定子進程到底是否traced.
      • ? ?分配空閑的PID
      • ? ?確定clone_ptrace位. (確定子進程到底要不要被trace, 而不是參數所說的希望被trace)
        • ? ? 設置該位: 參數已設該位, 且創建線程被trace中
        • ? ? 清除該位: 父進程沒有被trace, 或 clone_untrace已經設置.
    • ??復制進程描述符(copy_process)
      • ? ?檢查clone_flags是否兼容, 是否安全
        • ? ? clone_newns 與 clone_fs 互斥
        • ? ? clone_sighand 是 clone_thread 的必要條件: 線程必須共享信號處理
        • ? ? clone_vm 是 clone_sighand 的必要條件 : 共享信號處理, 首先要共享信號處理的代碼(在進程頁面里)
        • ? ? 附加的安全檢查: security_task_create(clone_flags)
      • ? ?復制進程描述符
        • ? ? 在父進程的thread_info里保存浮點寄存器: __unlazy_fpu()
        • ? ? 分配新的進程pd(alloc_task_struct), 并拷貝父進程pd
        • ? ? 分配新的thread_info(alloc_thread_info), 并拷貝父進程的thread_info.
        • ? ? 新的thread_info和新分配的pd 相互引, 新pd的引用計數設為2 (表示:新pd有用, 且不是僵尸進程)
      • ? ?相關計數加1: (此處先相關計數檢查, 都通過后再都加1)
        • ? ? 檢查并增加: 用戶擁有進程數, 系統總共進程數.
          • ? ???一般來說, 所有進程的thread_info總和, 不超過物理內存的1/8
        • ? ? 新進程的可執行格式的引用計數(FIXME: pd里標有可執行個數嗎)
        • ? ? 系統執行fork總數.
      • ? ?進程pd的關鍵域的設置(順序與源碼可能不一致):
        • ? ? 進程關系
          • ? ???設置父子關系 (parent, real_parent, 考慮被trace的情況)
          • ? ???設置新pd的PID
          • ? ???設置tgid, 線程組長的pd(pd->group_leader). (根據是不是線程組長, 即clone_thread位是否為0)
          • ? ???加入PID哈希表(pid, tgid, 如果是進程組長加入pgid和sid表),(調attach_pid())
          • ? ???拷貝tid到父進程的用戶空間(parent_tidptr)
        • ? ? 拷貝資源(如果clone_flags沒標明共享):
          • ? ???文件,目錄,內存:copy_files, copy_mm, copy_namespace,
          • ? ???進程通信: copy_signal, copy_sighand, copy_semundo
        • ? ? 設置子進程的內核棧(thread_info), 內核態相關寄存器(thread_struct, 不知道這個結構的具體用處): copy_thread()
          • ? ???子進程的thread_struct:
            • ? ?? ?esp, esp0 - 內核棧頂, 內核棧底
            • ? ?? ?eip - ret_from_fork()的地址 (用戶態切到內核態的第一條指令)
            • ? ?? ?I/O許可位圖 - 如果父進程有, 就拷貝一份過來
            • ? ?? ?TLS - 如果用戶空間提供了TLS段, 拷貝過來
          • ? ???設置子進程的內核棧:
            • ? ?? ?child_regs.esp = 傳入的棧地址參數;
            • ? ?? ?child_regs.eax = 0, 給用戶態的返回值是0
            • ? ?? ?清除thread_info中的, TIF_SYSCALL_TRACE位, 防止運行ret_from_fork時, 系統通知調試進程
            • ? ?? ?設置子進程的thread_info的cpuid
        • ? ? 設置調度信息(sched_fork())
          • ? ???設置task_running狀態,
          • ? ???初始化調度參數(時間片),
          • ? ???子進程禁止內核搶占(thread_info.preempt_cout = 1)
        • ? ? 其他:
          • ? ???如果沒有被trace,pd->ptrace = 0;
          • ? ???設置pd->exit_signal:
            • ? ?? ?有clone_thread位: 設為參數clone_flags中的退出信號
            • ? ?? ?沒有clone_thread位: 設為-1 (表示進程終止時, 該LWP不給父進程發信號)
          • ? ???pd->flags: 清除PF_SUPERPRIV , 設置PF_FORKNOEXEC
          • ? ???大內核鎖 pd->lock_depth = -1
          • ? ???exec次數: pd->did_exec = 0
          • ? ???拷貝child_tidptr到pd->set_child_tid. 以備子進程開始執行時, 把tid放到自己內存空間的child_tidptr
      • ? ?返回pd
    • ??設置父子進程的運行狀態, 調度信息
      • ? ?設置子進程的狀態.
        • ? ? 掛信號: 如果創建出來的是停止(clone_stopped)或被trace(pd->ptrace里有PT_PTRACE位)的進程, 懸掛一個SIGSTOP信號.
          • ? ???只有debugger發出SIGCONT信號后, 才能進入運行狀態
        • ? ? 設狀態,入列隊:如果有clone_stopped位, 子進程設為stopped狀態; 否則調用wake_up_new_task(), 把子進程加入就緒列隊:
          • ? ???調整父進程和子進程的調度參數 (主要是時間片)
          • ? ???如果父子在同一CPU上運行, 且頁表不同享, 子進程在插在父進程前
            • ? ?? ?子進程很可能exec, 不與父進程共享頁. 這樣防止父進程無用的copy on write.
          • ? ???如果不同CPU上運行, 或者共享頁表, 子進程放在列隊最后
      • ? ?如果父進程處于被調試狀態, 程通知調試器
        • ? ? 當前進程給debugger進程發信號, 告知自己創建了子進程; 并停止自己(進入traced狀態), 使debugger運行.
          • ? ???子進程的pid保存在current->ptrace_message中, 供debugger用
          • ? ???調試器發信號, 使父進程繼續后, 再進行下一步; 否則父進程一直處于traced狀態
      • ? ?設置父進程狀態
        • ? ? 如果有clone_vfork, 把自己放到一個等待列隊.
          • ? ???內核處理完系統調用后, 會執行調度, 這樣就阻塞父進程了.
          • ? ???直到子進程釋放了它的內存地址空間, 即子進程終止或exec新程序, 用信號喚醒父進程.
    • ??返回子進程的pid.
    • ??子進程被調度后,執行pd.thread.eip(ret_from_fork). 調用關系(=>): ret_from_fork=>schedule_tail=>finish_task_switch.
      • ? ?schedule_tail的另一件事就是: 把pid保存到地址pd->set_child_tid (創建進程使的parent_tidptr)
      • ? ?finish_task_switch的動作是: 裝載內核棧保存的寄存器(regs->eax為0),返回到用戶態。系統調用返回值就是eax(0)
  • 內核線程:
    • ??只運行于kernel模式,只能訪問大于3G的空間。而普通進程在內核模式時,能訪問整個4G空間
    • ??創建方法, 類似于clone
      • ? ?準備返回地址fn: 構造一個regs. 里面有fn, args, __KERNEL_CS等. regs->eip是匯編函數kernel_thread_helper
      • ? ?do_fork (flags|CLONE_VM|clone_untraced, 0, &regs, 0, NULL, NULL)
        • ? ? 創建線程, 與父進程共享頁. 用上步構造的regs初始化新程的內核棧
      • ? ?新線程被調度后. 由ret_from_fork, 用regs恢復寄存器, 開始執行kernel_thread_helper
      • ? ?kernel_thread_helper: 把args壓入棧, call fn(args, fn都寄存器中)
    • ??典型的內核線程:
      • ? ?進程0: 所有進程的祖先
        • ? ? 編譯時存在.
          • ? ???pd, 內核棧: init_task, init_thread_union
          • ? ???資源: init_mm, init_files, init_fs.??信號: init_signals, init_sighand
          • ? ???頁表: swapper_gd_dir
        • ? ? 功能
          • ? ???初始化系統數據,
            • ? ?? ?多CPU系統中, 開始時BIOS禁用其他CPU.
            • ? ?? ?初始化系統數據后, 進程0拷貝自己到其他CPU的調度列隊上, 啟動其他CPU, 所有的PID都是0.
          • ? ???使能中斷
          • ? ???創建內核線程1, (函數是init)
          • ? ???進入idle
      • ? ?進程1:
        • ? ? init函數 exec可執行文件init, 使內核線程變成了普通進程.
        • ? ? 管理其他進程, 稱為托孤進程
      • ? ?其他內核線程:
        • ? ? 執行工作列隊:
          • ? ???ksoftirqd: 執行 softlets
          • ? ???kblockd: 執行工作列隊 kblockd_workqueue, 定期激活塊設備驅動
          • ? ???keventd (又叫events): 處理工作列隊 keventd_wq
        • ? ? 管理資源:
          • ? ???kapmd: 電源管理
          • ? ???kswapd: 交換進程, 用于回收內存資源
          • ? ???pdflush: flush臟的磁盤緩存
進程銷毀
  • 進程終止
    • ??系統調用
      • ? ?整個進程終止: exit_group(), 由do_group_exit處理系統調用. c函數 exit()也是用的這系統調用
      • ? ?某個線程終止: _exit(), 由do_exit處理. C函數中用到此系統調用的API: pthread_exit
    • ??do_group_exit流程: (整個組內至少有一個線程調用它, 用于整組協調)
      • ? ?檢查線程組的退出過程是否啟動: 檢查signal_group_exit(線程組內的公共數據)是否非零. 如果沒有啟動, 執行一下操作來啟動退出過程:
        • ? ? 設置啟動標志signal_group_exit.
        • ? ? 存儲終止碼(exit_group的參數), 在current->signal->group_exit_cold
        • ? ? 向其他線程發SIG_KILL信號, (它們收到信號后, 調do_exit())
      • ? ?調用do_exit, 使本線程退出
    • ??do_exit流程:
      • ? ?設置線程的終止標志, 退出碼
        • ? ? 設置PF_EXITING, 標明要被終止
        • ? ? 設置pd->exit_code
          • ? ???系統調用參數
          • ? ???或是內核提供的錯誤碼, 表示異常終止
      • ? ?釋放資源:
        • ? ? 刪除該進程的定時器
        • ? ? 去除對資源的引用:
          • ? ???exit_mm, __exit_files;
          • ? ???__exit_fs(root路徑,工作路徑, 創建文件權限), exit_namespace(掛載的文件系統的視野);
          • ? ???exit_thread(thread_struct), exit_sem,
      • ? ?如果這個線程的函數實現了一種可執行格式, 可執行格式數的引用計數--; FIXME: 還沒看到這塊兒, 湊合翻譯的不一定對
      • ? ?改變父子關系, 并向父進程發信號, 改變自己的狀態(exit_notify)
        • ? ? 托付終止線程創建的子進程:
          • ? ???如果終止線程還有同組線程: 終止線程創建的子進程, 作為與同組線程的子進程.
          • ? ???否則: 終止線程創建的子進程, 作為孤兒進程, 由init進程托管
        • ? ? 向父進程發信號
          • ? ???exit_signal有意義 && 最后線程 :??發exit_signal
          • ? ???否則:
            • ? ?? ?被trace : 發SIGCHLD
            • ? ?? ?沒被trace : 不發信號
        • ? ? 僵尸自己或直接死亡,??并設置PF_DEAD位
          • ? ???exit_signal沒意義 && 沒被trace : 直接死亡 (這種情況沒有發信號)
            • ? ?? ?變成EXIT_DEAD狀態,
            • ? ?? ?release_task() (后面介紹). pd引用計數變為1, 不會馬上釋放
          • ? ???否則: 僵尸
            • ? ?? ?exit_signal有意義 || 被trace : 僵尸
          • ? ???整理"僵尸"與"發臨僵尸信號"的關系:
            • ? ?? ?將發信號的條件中"最后線程"去掉, 可簡化為(exit_signal有意義)||(被trace) == (發信號)
            • ? ?? ?可得出后: (發信號) == (僵尸)
            • ? ?? ?又可推出: (沒有trace && exit_signal有意義 && 不是最后進程) == (僵尸了,但沒法信號) , 這種情況在移除死進程時, 會給其父進程發信號 (FIXME: 待驗證)
      • ? ?調度. 調度函數會忽略僵尸進程, 但會減少僵尸進程的pd的使用計數; 會檢查PF_DEAD位, 把它變成exit_dead狀態
  • 進程移除 TODO:

進程、輕量級進程(LWP)、線程


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 国产视频91在线 | 中文字幕国产一区 | 亚洲国产天堂久久精品网 | 久久天堂网 | 久草国产电影 | 中文字幕日本视频 | 人人爱人人草 | 国产亚洲成av人在线观看导航 | 国产欧美一区二区 | 黄色网一级片 | 天天插天天狠天天透 | 国产乱精品一区二区三区 | 亚洲一区二区三区四区精品 | 亚洲在线一区 | 四虎影音| avtt国产| 亚洲成人精品 | 精品欧美乱码久久久久久1区2区 | 久久道 | 日本久久高清视频 | 五月婷婷开心综合 | 国产黄色一级毛片 | 91久久极品| 丁香花成人另类小说 | 欧美一区二区三区成人精品 | 日韩精品视频免费在线观看 | 男女男精品视频免费观看 | 亚洲视频不卡 | 日韩在线免费看网站 | 999久久久精品视频在线观看 | 精品午夜久久网成年网 | 黄色片免费在线 | 欧美精品成人一区二区三区四区 | 国内精品免费一区二区三区 | 国产在线一区二区三区 | 香港三级午夜理伦三级 | 91精品国产91久久久久久 | www操com| 午夜影院福利社 | 欧美在线精品一区二区在线观看 | 日本综合欧美一区二区三区 |