日韩欧美国产极速不卡一区,国产手机视频在线观看尤物,国产亚洲欧美日韩蜜芽一区,亚洲精品国产免费,亚洲二区三区无码中文,A大片亚洲AV无码一区二区三区,日韩国语国产无码123

您好,歡迎來到維庫電子市場(chǎng)網(wǎng) 登錄 | 免費(fèi)注冊(cè)

Linux
閱讀:29025時(shí)間:2010-12-21 16:39:24

  Linux是一套免費(fèi)使用和自由傳播的操作系統(tǒng),它主要用于基于Intel系列CPU的計(jì)算機(jī)上。這個(gè)系統(tǒng)是由全世界各地的成千上萬的程序員設(shè)計(jì)和實(shí)現(xiàn)的,其目的是建立不受任何商品化軟件的版權(quán)制約的、全世界都能自由使用的Unix兼容產(chǎn)品。

實(shí)時(shí) 架構(gòu)簡(jiǎn)介

  實(shí)時(shí)系統(tǒng)指系統(tǒng)的計(jì)算正確性不僅取決于計(jì)算的邏輯正確性,還取決于產(chǎn)生結(jié)果的時(shí)間。如果未滿足系統(tǒng)的時(shí)間約束,則認(rèn)為系統(tǒng)失效。換句話說,系統(tǒng)面對(duì)變化的負(fù)載(從最小到最壞的情況)時(shí)必須確定性地保證滿足時(shí)間要求。

  注意,實(shí)時(shí)性與速度關(guān)系不大:它與可預(yù)見性有關(guān)。例如,使用快速的現(xiàn)代處理器時(shí),Linux 可以提供 20 μ 微秒的典型中斷響應(yīng),但有時(shí)候響應(yīng)會(huì)變得很長。這是一個(gè)基本的問題:并不是 Linux 不夠快或效率不夠高,而是因?yàn)樗荒芴峁┐_定性。

  當(dāng)中斷到達(dá)時(shí)(event),CPU 發(fā)生中斷并轉(zhuǎn)入中斷處理。執(zhí)行一些工作以確定發(fā)生了什么事件,然后執(zhí)行少量工作分配必需的任務(wù)以處理此事件(上下文切換)。中斷到達(dá)與分發(fā)必需任務(wù)之間的時(shí)間(假設(shè)分配的是優(yōu)先級(jí)的任務(wù))稱為響應(yīng)時(shí)間。對(duì)于實(shí)時(shí)性要求,響應(yīng)時(shí)間應(yīng)是確定的并應(yīng)當(dāng)在已知的最壞情況的時(shí)間內(nèi)完成。因此,對(duì)于某些高安全性的場(chǎng)合,操作系統(tǒng)應(yīng)快速地分配任務(wù),并且不允許其他非實(shí)時(shí)處理進(jìn)行干擾。晚一秒鐘響應(yīng)比沒有響應(yīng)的情況更糟糕。

  除為中斷處理提供確定性外,實(shí)時(shí)處理也需要支持周期性間隔的任務(wù)調(diào)度。大量控制系統(tǒng)要求周期性采樣與處理。某個(gè)特定任務(wù)必須按照固定的周期(p)執(zhí)行,從而確保系統(tǒng)的穩(wěn)定性。在某些控制場(chǎng)合下,為了保持控制系統(tǒng)的正常工作,傳感器的采樣與控制必須按照一定的周期間隔。這意味著必須搶占其他處理,以便特定任務(wù)能按照期望的周期執(zhí)行。

  能夠在指定的期限完成實(shí)時(shí)任務(wù)(即便在最壞的處理負(fù)載下也能如此)的操作系統(tǒng)稱為硬實(shí)時(shí) 系統(tǒng)。但并不是任何情況下都需要硬實(shí)時(shí)支持。如果操作系統(tǒng)在平均情況下能支持任務(wù)的執(zhí)行期限,則稱它為軟實(shí)時(shí) 系統(tǒng)。硬實(shí)時(shí)系統(tǒng)指超過截止期限后將造成災(zāi)難性后果(例如展開氣囊過晚或制動(dòng)壓力產(chǎn)生的滑行距離過長)的系統(tǒng)。軟實(shí)時(shí)系統(tǒng)超過截止期限后并不會(huì)造成系統(tǒng)整體失�。ㄈ鐏G失視頻中的一幀)。

  Linux 架構(gòu)支持通過以下幾種方式實(shí)現(xiàn)硬實(shí)時(shí)。

  1. 瘦內(nèi)核方法

  瘦內(nèi)核(或微內(nèi)核)方法使用了第二個(gè)內(nèi)核作為硬件與 Linux 內(nèi)核間的抽象接口。非實(shí)時(shí) Linux 內(nèi)核在后臺(tái)運(yùn)行,作為瘦內(nèi)核的一項(xiàng)低優(yōu)先級(jí)任務(wù)托管全部非實(shí)時(shí)任務(wù)。實(shí)時(shí)任務(wù)直接在瘦內(nèi)核上運(yùn)行。

  瘦內(nèi)核主要用于(除了托管實(shí)時(shí)任務(wù)外)中斷管理。瘦內(nèi)核截取中斷以確保非實(shí)時(shí)內(nèi)核無法搶占瘦內(nèi)核的運(yùn)行。這允許瘦內(nèi)核提供硬實(shí)時(shí)支持。

  雖然瘦內(nèi)核方法有自己的優(yōu)勢(shì)(硬實(shí)時(shí)支持與標(biāo)準(zhǔn) Linux 內(nèi)核共存),但這種方法也有缺點(diǎn)。實(shí)時(shí)任務(wù)和非實(shí)時(shí)任務(wù)是獨(dú)立的,這造成了調(diào)試?yán)щy。而且,非實(shí)時(shí)任務(wù)并未得到 Linux 平臺(tái)的完全支持(瘦內(nèi)核執(zhí)行稱為瘦 的一個(gè)原因)。

  使用這種方法的例子有 RTLinux。

  2. 超微內(nèi)核方法

  瘦內(nèi)核方法依賴于包含任務(wù)管理的最小內(nèi)核,而超微內(nèi)核法對(duì)內(nèi)核進(jìn)行更進(jìn)一步的縮減。通過這種方式,它不像是一個(gè)內(nèi)核而更像是一個(gè)硬件抽象層(HAL)。超微內(nèi)核為運(yùn)行于更別的多個(gè)操作系統(tǒng)提供了硬件資源共享。

  這種方法和運(yùn)行多個(gè)操作系統(tǒng)的虛擬化方法有一些相似之處。使用這種方法的情況下,超微內(nèi)核在實(shí)時(shí)和非實(shí)時(shí)內(nèi)核中對(duì)硬件進(jìn)行抽象。這與 hypervisor 從客戶(guest)操作系統(tǒng)對(duì)裸機(jī)進(jìn)行抽象的方式很相似。

  3. 資源內(nèi)核法

  這種方法為內(nèi)核增加一個(gè)模塊,為各種資源提供預(yù)留(reservation)。這種機(jī)制保證了對(duì)時(shí)分復(fù)用(time-multiplexed)系統(tǒng)資源的訪問(CPU、網(wǎng)絡(luò)或磁盤帶寬)。這些資源擁有多個(gè)預(yù)留參數(shù),如循環(huán)周期、需要的處理時(shí)間(也就是完成處理所需的時(shí)間),以及截止時(shí)間。

  資源內(nèi)核提供了一組應(yīng)用程序編程接口(API),允許任務(wù)請(qǐng)求這些預(yù)留資源。然后資源內(nèi)核可以合并這些請(qǐng)求,使用任務(wù)定義的約束定義一個(gè)調(diào)度,從而提供確定的訪問(如果無法提供確定性則返回錯(cuò)誤)。通過調(diào)度算法,內(nèi)核可以處理動(dòng)態(tài)的調(diào)度負(fù)載。

  資源內(nèi)核法實(shí)現(xiàn)的一個(gè)示例是 CMU 公司的 Linux/RK,它把可移植的資源內(nèi)核集成到 Linux 中作為一個(gè)可加載模塊。這種實(shí)現(xiàn)演化成商用的 TimeSys Linux/RT 產(chǎn)品。

常用命令

  Linux的系統(tǒng)管理主要在控制終端下進(jìn)行,通過使用命令行的方式進(jìn)行管理。Linux的文件命令可以完成各種復(fù)雜的工作,例如對(duì)目錄進(jìn)行復(fù)制、移動(dòng)和鏈接,搜索和查找文件和目錄,閱讀、顯示或打印文件內(nèi)容等操作。Linux操作系統(tǒng)提供的命令很多,但用戶日常使用的命令卻很有限。一些在日常工作中最常用的Linux命令:

  熟練使用文件管理命令

  熟練使用磁盤管理命令

  熟練使用文件搜索和壓縮/解壓縮命令

  熟練使用系統(tǒng)管理命令

  區(qū)分Linux命令和DOS命令

與DOS命令

  Linux系統(tǒng)下的shell命令要比Windows下的DOS命令重要得多,因?yàn)橥耆梢圆皇褂肈OS命令而在Windows系統(tǒng)下完成所有的操作,但是在Linux系統(tǒng)下,很多shell命令在X Window圖形窗口下是無法完成的,并且shell命令要比DOS命令更強(qiáng)大,相對(duì)也較復(fù)雜。

  兩者的區(qū)別主要有以下幾點(diǎn)。

  DOS的文件名必須遵循7.3規(guī)則,而Linux則支持ext3文件系統(tǒng),可以支持長文件名,并且可以使用更多的“.”和字符。例如,abc.123.c在Linux系統(tǒng)下是一個(gè)合法的文件名。在Linux系統(tǒng)下,英文字母的大小寫是不一樣的。這個(gè)規(guī)則對(duì)于shell命令也是有效的。Linux下的文件如果是以“.”作為文件名的個(gè)字符,將會(huì)被認(rèn)為是隱藏文件,使用ls命令是看不到這類文件的(用ls –a可以看到隱藏文件)。

  Linux系統(tǒng)下的路徑是用“/”分隔開的,而DOS下則用“\”分隔。Linux系統(tǒng)沒有定義可執(zhí)行文件的擴(kuò)展名必須為.exe、.com、.bat等。用戶使用命令ls –F可看到有的文件名后加了一個(gè)*號(hào),那么這個(gè)文件就是可執(zhí)行文件。

  對(duì)于命令參數(shù)的應(yīng)用也有不同之處。DOS下的參數(shù)和命令之間用“/”分隔,而在Linux系統(tǒng)下,命令和參數(shù)之間用“-”分隔,例如ls –l和dir/w。關(guān)于Linux與DOS的異同見表所示。

Linux命令與DOS命令的比較

  注:

  a  Gedit是圖形化文本編輯器,也可以使用其他文本編輯器來代替Gedit,例如Emacs和vi等。

  b  這個(gè)命令為DOS文件系統(tǒng)下格式化軟盤的命令。

  c  某些命令還可以使用info。

  d  more分頁器也可以用來在文件中逐頁查看。

  e  mv命令可以轉(zhuǎn)移文件或重新命名同一目錄下的文件。如果想重新命名文件,可把這個(gè)文件“轉(zhuǎn)移”到同一目錄中的新名稱。

進(jìn)程創(chuàng)建

  在 Linux 內(nèi)核內(nèi),進(jìn)程是由相當(dāng)大的一個(gè)稱為 task_struct 的結(jié)構(gòu)表示的。此結(jié)構(gòu)包含所有表示此進(jìn)程所必需的數(shù)據(jù),此外,還包含了大量的其他數(shù)據(jù)用來統(tǒng)計(jì)(accounting)和維護(hù)與其他進(jìn)程的關(guān)系(父和子)。下面給出了 task_struct 的一小部分。task_struct 位于 ./linux/include/linux/sched.h。

  struct task_struct {

  volatile long state;

  void *stack;

  unsigned int flags;

  int prio, static_prio;

  struct list_head tasks;

  struct mm_struct *mm, *active_mm;

  pid_t pid;

  pid_t tgid;

  struct task_struct *real_parent;

  char comm[TASK_COMM_LEN];

  struct thread_struct thread;

  struct files_struct *files;

  ...

  };

  在task_struct中,可以看到幾個(gè)預(yù)料之中的項(xiàng),比如執(zhí)行的狀態(tài)、堆棧、一組標(biāo)志、父進(jìn)程、執(zhí)行的線程(可以有很多)以及開放文件。對(duì)其做簡(jiǎn)單聲明如下

  <1> state 變量是一些表明任務(wù)狀態(tài)的比特位。最常見的狀態(tài)有:

  1.TASK_RUNNING 表示進(jìn)程正在運(yùn)行,或是排在運(yùn)行隊(duì)列中正要運(yùn)行

  2.TASK_INTERRUPTIBLE 表示進(jìn)程正在休眠

  3.TASK_UNINTERRUPTIBLE 表示進(jìn)程正在休眠但不能叫醒

  4.TASK_STOPPED 表示進(jìn)程停止

  注:這些標(biāo)志的完整列表可以在 ./linux/include/linux/sched.h 內(nèi)找到。

  <2> flags 定義了很多指示符,表明進(jìn)程是否正在被創(chuàng)建(PF_STARTING)或退出(PF_EXITING),或是進(jìn)程當(dāng)前是否在分配內(nèi)存(PF_MEMALLOC)。

  <3> 每個(gè)進(jìn)程都會(huì)被賦予優(yōu)先級(jí)(稱為 static_prio),但進(jìn)程的實(shí)際優(yōu)先級(jí)是基于加載以及其他幾個(gè)因素動(dòng)態(tài)決定的。優(yōu)先級(jí)值越低,實(shí)際的優(yōu)先級(jí)越高。

  <4> tasks 字段提供了鏈接列表的能力。它包含一個(gè) prev 指針(指向前一個(gè)任務(wù))和一個(gè) next 指針(指向下一個(gè)任務(wù))。

  <5> 進(jìn)程的地址空間由 mm 和 active_mm 字段表示。mm 代表的是進(jìn)程的內(nèi)存描述符,而 active_mm 則是前一個(gè)進(jìn)程的內(nèi)存描述符(為改進(jìn)上下文切換時(shí)間的一種優(yōu)化)。

  <6> 可執(zhí)行程序的名稱(不包含路徑)占用 comm(命令)字段。

  <7> thread_struct 則用來標(biāo)識(shí)進(jìn)程的存儲(chǔ)狀態(tài)。此元素依賴于 Linux 在其上運(yùn)行的特定架構(gòu),在 ./linux/include/asm-i386/processor.h 內(nèi)有這樣的一個(gè)例子。在此結(jié)構(gòu)內(nèi),可以找到該進(jìn)程自執(zhí)行上下文切換后的存儲(chǔ)(硬件注冊(cè)表、程序計(jì)數(shù)器等)。

  在很多情況下,進(jìn)程都是動(dòng)態(tài)創(chuàng)建并由一個(gè)動(dòng)態(tài)分配的 task_struct 表示。當(dāng)然 init 進(jìn)程例外,它總是存在并由一個(gè)靜態(tài)分配的 task_struct 表示。

  Linux 內(nèi)所有進(jìn)程的分配有兩種方式。種方式是通過一個(gè)哈希表,由 PID 值進(jìn)行哈希計(jì)算得到;第二種方式是通過雙鏈循環(huán)表。循環(huán)表非常適合于對(duì)任務(wù)列表進(jìn)行迭代。由于列表是循環(huán)的,沒有頭或尾;但是由于 init_task 總是存在,所以可以將其用作繼續(xù)向前迭代的一個(gè)錨點(diǎn)。

  任務(wù)列表無法從用戶空間訪問,但該問題很容易解決,方法是以模塊形式向內(nèi)核內(nèi)插入代碼。例如通過如下代碼,它會(huì)迭代任務(wù)列表并會(huì)提供有關(guān)每個(gè)任務(wù)的少量信息(name、pid 和 parent 名)。

  struct task_struct *task = &init_task;

  /* Walk through the task list, until we hit the init_task again */

  do {

  printk( KERN_INFO "*** %s [%d] parent %s\n",

  task->comm, task->pid, task->parent->comm );

  } while ( (task = next_task(task)) != &init_task );

  注意,還可以標(biāo)識(shí)當(dāng)前正在運(yùn)行的任務(wù)。Linux 維護(hù)一個(gè)稱為 current 的符號(hào),代表的是當(dāng)前運(yùn)行的進(jìn)程(類型是 task_struct)。為此可使用如下代碼:

  printk( KERN_INFO, "Current task is %s [%d]”, current->comm, current->pid );

  Linux創(chuàng)建用戶空間進(jìn)程的情況與內(nèi)核空間進(jìn)程類似。二者底層機(jī)制是一致的,因?yàn)樽罱K都會(huì)依賴于一個(gè)名為 do_fork 的函數(shù)來創(chuàng)建新進(jìn)程。

  在創(chuàng)建內(nèi)核線程時(shí),內(nèi)核會(huì)調(diào)用一個(gè)名為 kernel_thread 的函數(shù)(參見 ./linux/arch/i386/kernel/process.c),此函數(shù)執(zhí)行某些初始化后會(huì)調(diào)用 do_fork。

  在用戶空間,一個(gè)程序會(huì)調(diào)用 fork,這會(huì)導(dǎo)致對(duì)名為 sys_fork 的內(nèi)核函數(shù)的系統(tǒng)調(diào)用(參見 ./linux/arch/i386/kernel/process.c)。

  do_fork 是進(jìn)程創(chuàng)建的基礎(chǔ)。可以在 ./linux/kernel/fork.c 內(nèi)找到 do_fork 函數(shù)(以及相關(guān)函數(shù) copy_process)。

  do_fork 函數(shù)首先調(diào)用 alloc_pidmap,該調(diào)用會(huì)分配一個(gè)新的 PID。接下來,do_fork 檢查調(diào)試器是否在跟蹤父進(jìn)程。如果是,在 clone_flags 內(nèi)設(shè)置 CLONE_PTRACE 標(biāo)志以做好執(zhí)行 fork 操作的準(zhǔn)備。之后 do_fork 函數(shù)還會(huì)調(diào)用 copy_process,向其傳遞這些標(biāo)志、堆棧、注冊(cè)表、父進(jìn)程以及分配的 PID。

  新的進(jìn)程在 copy_process 函數(shù)內(nèi)作為父進(jìn)程的一個(gè)副本創(chuàng)建。此函數(shù)能執(zhí)行除啟動(dòng)進(jìn)程之外的所有操作,啟動(dòng)進(jìn)程在之后進(jìn)行處理。copy_process 內(nèi)的步是驗(yàn)證 CLONE 標(biāo)志以確保這些標(biāo)志是一致的。如果不一致,就會(huì)返回 EINVAL 錯(cuò)誤。接下來,詢問 Linux Security Module (LSM) 看當(dāng)前任務(wù)是否可以創(chuàng)建一個(gè)新任務(wù)。

  接下來,調(diào)用 dup_task_struct 函數(shù)(./linux/kernel/fork.c ),這會(huì)分配一個(gè)新 task_struct 并將當(dāng)前進(jìn)程的描述符復(fù)制到其內(nèi)。在新的線程堆棧設(shè)置好后,一些狀態(tài)信息也會(huì)被初始化,并且會(huì)將控制返回給 copy_process�?刂苹氐� copy_process 后,除了其他幾個(gè)限制和安全檢查之外,還會(huì)執(zhí)行一些常規(guī)管理,包括在新 task_struct 上的各種初始化。之后,會(huì)調(diào)用一系列復(fù)制函數(shù)來復(fù)制此進(jìn)程的各個(gè)方面,比如復(fù)制開放文件描述符(copy_files)、復(fù)制符號(hào)信息(copy_sighand 和 copy_signal)、復(fù)制進(jìn)程內(nèi)存(copy_mm)以及最終復(fù)制線程(copy_thread)。

  之后,這個(gè)新任務(wù)會(huì)被指定給一個(gè)處理程序,同時(shí)對(duì)允許執(zhí)行進(jìn)程的處理程序進(jìn)行額外的檢查(cpus_allowed)。新進(jìn)程的優(yōu)先級(jí)從父進(jìn)程的優(yōu)先級(jí)繼承后,執(zhí)行一小部分額外的常規(guī)管理,而且控制也會(huì)被返回給 do_fork。在此時(shí),新進(jìn)程存在但尚未運(yùn)行。do_fork 函數(shù)通過調(diào)用 wake_up_new_task 來修復(fù)此問題。此函數(shù)(./linux/kernel/sched.c )初始化某些調(diào)度程序的常規(guī)管理信息,將新進(jìn)程放置在運(yùn)行隊(duì)列之內(nèi),然后將其喚醒以便執(zhí)行。,一旦返回至 do_fork,此 PID 值即被返回給調(diào)用程序,進(jìn)程完成。

設(shè)備號(hào)之操作

  在Linux設(shè)備驅(qū)動(dòng)中,設(shè)備號(hào)設(shè)一個(gè)很重要的概念和變量。不論是主設(shè)備號(hào),還是次設(shè)備號(hào),在設(shè)備驅(qū)動(dòng)中都占據(jù)了很重要的地位。那么他在Kernel中是如何操作的?這個(gè)數(shù)據(jù)結(jié)構(gòu)都是通過那些函數(shù)可以很容易的在我們寫Linux設(shè)備驅(qū)動(dòng)模塊時(shí)被我們所使用呢?

  在include/linux/type.h文件中我們能看到一個(gè)關(guān)于dev_t的定義如下:

  ...

  typedef __u32 __kernel_dev_t;

  typedef __kernel_fd_set fd_set;

  typedef __kernel_dev_t dev_t;

  ...

  從這個(gè)定義中我們能看到dev_t是一個(gè)無符號(hào)的32位的整型。

  首先我們需要說明的是,在linux中主次設(shè)備號(hào)是放置在一個(gè)無符號(hào)的32位的整型中,那么這32位整型對(duì)于主次設(shè)備號(hào)如何分配呢?

  從源代碼中我們可以看到,主設(shè)備號(hào)占據(jù)12個(gè)位,次設(shè)備好占據(jù)20位。這在一定的時(shí)期內(nèi),主次設(shè)備號(hào)是完全可以滿足系統(tǒng)需要的。

  同時(shí)在include/linux/kdev_t.h文件中我們能發(fā)現(xiàn)很多函數(shù)或者宏定義的操作都是針對(duì)dev_t的。

  具體可以看到我們經(jīng)常用到的MAJOR(dev)、MINOR(dev)、MKDEV(ma,mi)。

  下面我們就具體分析下這三個(gè)我們經(jīng)常用到的宏定義:

  #define MINORBITS 20

  #define MINORMASK ((1U << MINORBITS) - 1)

  #define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS))

  從這個(gè)宏定義中我們可以看到其把無符號(hào)的32位的整型做位操作運(yùn)算:右移20位。

  在C語言中如果是右移,那么左邊補(bǔ)0,這樣在這32位的整型中通過這個(gè)操作就只保留了原先第19位到31位的有效值,而這也正是我們所需要的。

  下面我們看下MINOR這個(gè)宏定義:

  #define MINOR(dev) ((unsigned int) ((dev) & MINORMASK))

  要明白這個(gè)宏定義的具體是多少,我們需要首先明白宏定義MINORMASK是什么?

  我們從前面的宏定義中,我們看到:

  #define MINORMASK ((1U << MINORBITS) - 1)

  MINORMASK 是1U也就是1左移位20個(gè)字節(jié),二進(jìn)制的話就是10000000000000000000,也就是1后面帶20個(gè)0。

  然后在減1呢,就成了二進(jìn)制11111111111111111111,也就是20個(gè)1,十六進(jìn)制的話是0xFFFFF。

  好現(xiàn)在我們知道MINORMASK是20個(gè)1,也就是十六進(jìn)制0xFFFFF,那么我們?cè)谂cdev_t做一個(gè)位的與運(yùn)算,就把32位中的前12為置0,保留其后面的20位,也正是我們想要的表是設(shè)備次設(shè)備號(hào)的后20個(gè)字節(jié)。

  好下面我們看下如果我們知道了主設(shè)備號(hào)、次設(shè)備號(hào),我們?nèi)绾紊梢粋(gè)dev_t的數(shù)據(jù)結(jié)構(gòu)。

  宏定義:

  #define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi))

  明白了前面我們所說的,其實(shí)這個(gè)就比較簡(jiǎn)單了,把主設(shè)備號(hào)左移20位,然后與上次設(shè)備號(hào),就是我們所需要的dev_t的數(shù)據(jù)結(jié)構(gòu)。

  那么我們前面所說的關(guān)于dev_t的操作是新的2.6.x系列中的,在之前的2.4.x系列中,由于對(duì)設(shè)備號(hào)的總共就16個(gè)字節(jié),也就是一個(gè)短整型,那么一個(gè)系統(tǒng)中所能擁有的設(shè)備號(hào)就是及其有限的了。

  我們看下在老版本中的內(nèi)核中他們的表示:

  #define MAJOR(dev) ((dev)>>8)

  #define MINOR(dev) ((dev) & 0xff)

  #define MKDEV(ma,mi) ((ma)<<8 | (mi))

  從中我們可以看出,他是以8為為分界線,高8位為主設(shè)備號(hào),低8位為次設(shè)備號(hào),那么一個(gè)8位所能表示的最多也即是255個(gè)數(shù)值,那么當(dāng)我們系統(tǒng)中如果擁有的設(shè)備大于這個(gè)數(shù)值的時(shí)候,在老版本的內(nèi)核中就沒有辦法處理了。

  在內(nèi)核實(shí)現(xiàn)中還實(shí)現(xiàn)了兩個(gè)打印的函數(shù),其實(shí)也是宏定義:

  #define print_dev_t(buffer, dev)                        \

  sprintf((buffer), "%u:%u\n", MAJOR(dev), MINOR(dev))

  #define format_dev_t(buffer, dev)                        \

  ({                                                                                \

  sprintf(buffer, "%u:%u", MAJOR(dev), MINOR(dev));        \

  buffer;                                        \

  })

  從代碼中我們可以看出。

  就是把設(shè)備的主設(shè)備號(hào)和次設(shè)備號(hào)以字符串的形式存放到buffer中,在使用這個(gè)宏定義的時(shí)候需要注意的是:

  buffer需要提前開辟空間,而且還需要是夠用的空間。

  第二所實(shí)現(xiàn)的功能和個(gè)很類似。這兒我們就不具體說明,請(qǐng)參考個(gè)宏定義的實(shí)現(xiàn)。

  在這個(gè)文件中還有很多的函數(shù),這些函數(shù)的主要功能就是和老版本的內(nèi)核代碼兼容而產(chǎn)生的,比如:

  static inline int old_valid_dev(dev_t dev)

  {

  return MAJOR(dev) < 256 && MINOR(dev) < 256;

  }

  此函數(shù)是判斷一個(gè)dev_t是否可以轉(zhuǎn)換成舊制的dev_t。

  static inline u16 old_encode_dev(dev_t dev)

  {

  return (MAJOR(dev) << 8) | MINOR(dev);

  }

  把32位的設(shè)備號(hào)轉(zhuǎn)換成16位的舊制的設(shè)備號(hào)。

  其中主要操作為:首先把主設(shè)備號(hào)左移8位,為次設(shè)備好空出8位的位置,然后與上次設(shè)備號(hào)。

  在使用這個(gè)函數(shù)的時(shí)候需要注意的就是需要首先判斷下32位的設(shè)備號(hào)是否可以有效的轉(zhuǎn)換成16位的設(shè)備號(hào)。

  static inline dev_t old_decode_dev(u16 val)

  {

  return MKDEV((val >> 8) & 255, val & 255);

  }

  上面函數(shù)的反操作。

  主設(shè)備號(hào)右移8位,然后與上255,即8個(gè)1。也就是取此變量的低8位,

  次設(shè)備號(hào)與上255,也是取此變量的低8位即可。

  static inline u32 new_encode_dev(dev_t dev)

  {

  unsigned major = MAJOR(dev);

  unsigned minor = MINOR(dev);

  return (minor & 0xff) | (major << 8) | ((minor & ~0xff) << 12);

  ^^^^^^^^^^^^^

  次設(shè)備號(hào)取其低8位 ^^^^^^^^^^^^^^

  主設(shè)備號(hào)左移8位。

  ^^^^^^^^^^^^^^^^^^^^^^^

  次設(shè)備號(hào)低8位清零,左移12位。

  }

  static inline dev_t new_decode_dev(u32 dev)

  {

  unsigned major = (dev & 0xfff00) >> 8;

  unsigned minor = (dev & 0xff) | ((dev >> 12) & 0xfff00);

  return MKDEV(major, minor);

  }

根文件系統(tǒng)介紹

  系統(tǒng)

  根文件系統(tǒng)首先是一種文件系統(tǒng),但是相對(duì)于普通的文件系統(tǒng),它的特殊之處在于,它是內(nèi)核啟動(dòng)時(shí)所mount的個(gè)文件系統(tǒng),內(nèi)核代碼映像文件保存在根文件系統(tǒng)中,而系統(tǒng)引導(dǎo)啟動(dòng)程序會(huì)在根文件系統(tǒng)掛載之后從中把一些基本的初始化腳本和服務(wù)等加載到內(nèi)存中去運(yùn)行。

  我們首先從主機(jī)上所安裝的Linux操作系統(tǒng)中了解一些根文件系統(tǒng)的信息。比如在筆者工作的Linux桌面系統(tǒng)中可以得到下面的結(jié)果:

  # mount

  /dev/hda2 on / type ext3 (rw)

  none on /proc type proc (rw)

  /dev/hda1 on /boot type ext3 (rw)

  none on /dev/pts type devpts (rw,gid=5,mode=620)

  none on /dev/shm type tmpfs (rw)

  # df

  Filesystem           1K-blocks      Used Available Use% Mounted on

  /dev/hda2             16216016   5667*   9724600  37% /

  /dev/hda1               101089      9321     8*9  10% /boot

  none                     63028         0     63028   0% /dev/shm

  從上面的mount命令我們可以看到,在桌面Linux中,根文件系統(tǒng)”/”被mount到/dev/hda2設(shè)備上,文件系統(tǒng)類型為ext3,屬性為rw即可讀寫。從df命令則可以得到更多根文件系統(tǒng)使用空間的相關(guān)信息。

  根文件系統(tǒng)一直以來都是所有類Unix操作系統(tǒng)的一個(gè)重要組成部分,也可以認(rèn)為是嵌入式Linux系統(tǒng)區(qū)別于其他一些傳統(tǒng)嵌入式操作系統(tǒng)的重要特征,它給Linux帶來了許多強(qiáng)大和靈活的功能,同時(shí)也帶來了一些復(fù)雜性。我們需要清楚的了解根文件系統(tǒng)的基本結(jié)構(gòu),以及細(xì)心的選擇所需要的系統(tǒng)庫、內(nèi)核模塊和應(yīng)用程序等,并配置好各種初始化腳本文件,以及選擇合適的文件系統(tǒng)類型并把它放到實(shí)際的存儲(chǔ)設(shè)備的合適位置。

  根文件系統(tǒng)的基本目錄結(jié)構(gòu)

  Linux的根文件系統(tǒng)以樹型結(jié)構(gòu)組織,包含內(nèi)核和系統(tǒng)管理所需要的各種文件和程序,一般說來根目錄”/”下的頂層目錄都有一些比較固定命名和用途。

  下面列出了一個(gè)Linux根文件系統(tǒng)中的比較常見的目錄結(jié)構(gòu):

  /bin 存放二進(jìn)制可執(zhí)行命令的目錄

  /dev 存放設(shè)備文件的目錄

  /etc 存放系統(tǒng)管理和配置文件的目錄

  /home 用戶主目錄,比如用戶user的主目錄就是/home/user,可以用~user表示

  /lib 存放動(dòng)態(tài)鏈接共享庫的目錄

  /sbin存放系統(tǒng)管理員使用的管理程序的目錄

  /tmp 公用的臨時(shí)文件存儲(chǔ)點(diǎn)

  /root 系統(tǒng)管理員的主目錄

  /mnt 系統(tǒng)提供這個(gè)目錄是讓用戶臨時(shí)掛載其他的文件系統(tǒng)。

  /proc 虛擬文件系統(tǒng),可直接訪問這個(gè)目錄來獲取系統(tǒng)信息。

  /var 某些大文件的溢出區(qū)

  /usr 最龐大的目錄,要用到的應(yīng)用程序和文件幾乎都在這個(gè)目錄。

  對(duì)于經(jīng)常使用Linux系統(tǒng)的讀者來說,這些目錄大部分應(yīng)該很熟悉了。不過有幾個(gè)目錄對(duì)初學(xué)者來說容易混淆,如/bin,/sbin,/usr/bin和/usr/sbin。這里簡(jiǎn)單介紹一下它們的區(qū)別:/bin目錄一般存放對(duì)于用戶和系統(tǒng)來說都是必須的二進(jìn)制文件,而/sbin目錄要存放的是只針對(duì)系統(tǒng)管理的二進(jìn)制文件,該目錄的文件將不會(huì)被普通用戶使用。相反,那些不是必要的用戶二進(jìn)制文件存放在/usr/bin下面,那些不是非常必要的系統(tǒng)管理工具放在/usr/sbin下。此外,對(duì)于一些本地的庫也非常類似,對(duì)于那些要求啟動(dòng)系統(tǒng)和運(yùn)行的必須命令要存放在/lib目錄下,而對(duì)于其他不是必須的庫存放在/usr/lib目錄就可以。

  對(duì)于嵌入式Linux系統(tǒng)的根文件系統(tǒng)來說,一般可能沒有上面所列出的那么復(fù)雜,比如嵌入式系統(tǒng)通常都不是針對(duì)多用戶的,所以/home這個(gè)目錄在一般嵌入式Linux中可能就很少用到,而/boot這個(gè)目錄則取決于你所使用的BootLoader是否能夠重新獲得內(nèi)核映象從你的根文件系統(tǒng)在內(nèi)核啟動(dòng)之前。一般說來,只有/bin,/dev,/etc,/lib,/proc,/var,/usr這些需要的,而其他都是可選的。

下的多進(jìn)程編程

  (一) 理解Linux下進(jìn)程的結(jié)構(gòu)

  Linux下一個(gè)進(jìn)程在內(nèi)存里有三部份的數(shù)據(jù),就是“數(shù)據(jù)段”,“堆棧段”和“代碼段”,其實(shí)學(xué)過匯編語言的人一定知道,一般的CPU象I386,都有上述三種段寄存器,以方便操作系統(tǒng)的運(yùn)行�!按a段”,顧名思義,就是存放了程序代碼的數(shù)據(jù),假如機(jī)器中有數(shù)個(gè)進(jìn)程運(yùn)行相同的一個(gè)程序,那么它們就可以使用同一

  個(gè)代碼段。

  堆棧段存放的就是子程序的返回地址、子程序的參數(shù)以及程序的局部變量。而數(shù)據(jù)段則存放程序的全局變量,常數(shù)以及動(dòng)態(tài)數(shù)據(jù)分配的數(shù)據(jù)空間(比如用malloc之類的函數(shù)取得的空間)。這其中有許多細(xì)節(jié)問題,這里限于篇幅就不多介紹了。系統(tǒng)如果同時(shí)運(yùn)行數(shù)個(gè)相同的程序,它們之間就不能使用同一個(gè)堆棧段和數(shù)據(jù) 段。

  (二) 如何使用fork

  在Linux下產(chǎn)生新的進(jìn)程的系統(tǒng)調(diào)用就是fork函數(shù),這個(gè)函數(shù)名是英文中“分叉”的意思。為什么取這個(gè)名字呢?因?yàn)橐粋(gè)進(jìn)程在運(yùn)行中,如果使用了fork,就產(chǎn)生了另一個(gè)進(jìn)程,于是進(jìn)程就“分叉”了,所以這個(gè)名字取得很形象。下面就看看如何具體使用fork,這段程序演示了使用fork的基本框架:

  void main(){

  int i;

  if ( fork() == 0 ) {

  /* 子進(jìn)程程序 */

  for ( i = 1; i < 1000; i )

  printf("This is child process\n");

  }

  else {

  /* 父進(jìn)程程序*/

  for ( i = 1; i < 1000; i )

  printf("This is process process\n");

  }

  }

  程序運(yùn)行后,你就能看到屏幕上交替出現(xiàn)子進(jìn)程與父進(jìn)程各打印出的一千條信息了。如果程序還在運(yùn)行中 ,你用ps命令就能看到系統(tǒng)中有兩個(gè)它在運(yùn)行了。

  那么調(diào)用這個(gè)fork函數(shù)時(shí)發(fā)生了什么呢?一個(gè)程序一調(diào)用fork函數(shù),系統(tǒng)就為一個(gè)新的進(jìn)程準(zhǔn)備了前述三個(gè)段,首先,系統(tǒng)讓新的進(jìn)程與舊的進(jìn)程使用同一個(gè)代碼段,因?yàn)樗鼈兊某绦蜻是相同的,對(duì)于數(shù)據(jù)段和堆棧段,系統(tǒng)則復(fù)制一份給新的進(jìn)程,這樣,父進(jìn)程的所有數(shù)據(jù)都可以留給子進(jìn)程,但是,子進(jìn)程一旦開始運(yùn)行,雖然它繼承了父進(jìn)程的一切數(shù)據(jù),但實(shí)際上數(shù)據(jù)卻已經(jīng)分開,相互之間不再有影響了,也就是說,它們之間不再共享任何數(shù)據(jù)了。而如果兩個(gè)進(jìn)程要共享什么數(shù)據(jù)的話,就要使用另一套函數(shù)(shmget,shmat,shmdt等)來操作�,F(xiàn)在,已經(jīng)是兩個(gè)進(jìn)程了,對(duì)于父進(jìn)程,fork函數(shù)返回了子程序的進(jìn)程號(hào),而對(duì)于子程序,fork函數(shù)則返回零,這樣,對(duì)于程序,只要判斷fork函數(shù)的返回值,就知道自己是處于父進(jìn)程還是子進(jìn)程中。

  讀者也許會(huì)問,如果一個(gè)大程序在運(yùn)行中,它的數(shù)據(jù)段和堆棧都很大,一次fork就要復(fù)制一次,那么fork 的系統(tǒng)開銷不是很大嗎?其實(shí)UNIX自有其解決的辦法,大家知道,一般CPU都是以“頁”為單位分配空間的,象INTEL的CPU,其一頁在通常情況下是4K字節(jié)大小,而無論是數(shù)據(jù)段還是堆棧段都是由許多“頁”構(gòu)成的, fork函數(shù)復(fù)制這兩個(gè)段,只是“邏輯”上的,并非“物理”上的,也就是說,實(shí)際執(zhí)行fork時(shí),物理空間上兩個(gè)進(jìn)程的數(shù)據(jù)段和堆棧段都還是共享著的,當(dāng)有一個(gè)進(jìn)程寫了某個(gè)數(shù)據(jù)時(shí),這時(shí)兩個(gè)進(jìn)程之間的數(shù)據(jù)才有了區(qū)別,系統(tǒng)就將有區(qū)別的“頁”從物理上也分開。系統(tǒng)在空間上的開銷就可以達(dá)到最小。

  一個(gè)小幽默:下面演示一個(gè)足以"搞死"Linux的小程序,其源代碼非常簡(jiǎn)單:

  void main()

  {

  for(;;) fork();

  }

  這個(gè)程序什么也不做,就是死循環(huán)地fork,其結(jié)果是程序不斷產(chǎn)生進(jìn)程,而這些進(jìn)程又不斷產(chǎn)生新的進(jìn)程,很快,系統(tǒng)的進(jìn)程就滿了,系統(tǒng)就被這么多不斷產(chǎn)生的進(jìn)程"撐死了"。用不著是root,任何人運(yùn)行上述程序都足以讓系統(tǒng)死掉。哈哈,但這不是Linux不安全的理由,因?yàn)橹灰到y(tǒng)管理員足夠聰明,他(或她)就可以預(yù)先給每個(gè)用戶設(shè)置可運(yùn)行的進(jìn)程數(shù),這樣,只要不是root,任何能運(yùn)行的進(jìn)程數(shù)也許不足系統(tǒng)總的能運(yùn)行和進(jìn)程數(shù)的十分之一,這樣,系統(tǒng)管理員就能對(duì)付上述惡意的程序了。

  (三) 如何啟動(dòng)另一程序的執(zhí)行

  下面我們來看看一個(gè)進(jìn)程如何來啟動(dòng)另一個(gè)程序的執(zhí)行。在Linux中要使用exec類的函數(shù),exec類的函數(shù)不止一個(gè),但大致相同,在Linux中,它們分別是:execl,execlp,execle,execv,execve和execvp,下面我只以execlp為例,其它函數(shù)究竟與execlp有何區(qū)別,請(qǐng)通過manexec命令來了解它們的具體情況。

  一個(gè)進(jìn)程一旦調(diào)用exec類函數(shù),它本身就“死亡”了,系統(tǒng)把代碼段替換成新的程序的代碼,廢棄原有的數(shù)據(jù)段和堆棧段,并為新程序分配新的數(shù)據(jù)段與堆棧段,留下的,就是進(jìn)程號(hào),也就是說,對(duì)系統(tǒng)而言,還是同一個(gè)進(jìn)程,不過已經(jīng)是另一個(gè)程序了。(不過 exec類函數(shù)中有的還允許繼承環(huán)境變量之類的信息。)

  那么如果我的程序想啟動(dòng)另一程序的執(zhí)行但自己仍想繼續(xù)運(yùn)行的話,怎么辦呢?那就是結(jié)合fork與exec的 使用。下面一段代碼顯示如何啟動(dòng)運(yùn)行其它程序:

  char command[256];

  void main()

  {

  int rtn; /*子進(jìn)程的返回?cái)?shù)值*/

  while(1) {

  /* 從終端讀取要執(zhí)行的命令 */

  printf( ">" );

  fgets( command, 256, stdin );

  command[strlen(command)-1] = 0;

  if ( fork() == 0 ) {

  /* 子進(jìn)程執(zhí)行此命令 */

  execlp( command, command );

  /* 如果exec函數(shù)返回,表明沒有正常執(zhí)行命令,打印錯(cuò)誤信息*/

  perror( command );

  exit( errorno );

  }

  else {

  /* 父進(jìn)程, 等待子進(jìn)程結(jié)束,并打印子進(jìn)程的返回值 */

  wait ( &rtn );

  printf( " child process return %d\n",. rtn );

  }

  }

  }

  此程序從終端讀入命令并執(zhí)行之,執(zhí)行完成后,父進(jìn)程繼續(xù)等待從終端讀入命令。熟悉DOS和WINDOWS系統(tǒng)調(diào)用的朋友一定知道DOS/WINDOWS也有exec類函數(shù),其使用方法是類似的,但DOS/WINDOWS還有spawn類函數(shù),因?yàn)镈OS是單任務(wù)的系統(tǒng),它只能將“父進(jìn)程”駐留在機(jī)器內(nèi)再執(zhí)行“子進(jìn)程”,這就是spawn類的函數(shù)。 WIN32已經(jīng)是多任務(wù)的系統(tǒng)了,但還保留了spawn類函數(shù),WIN32中實(shí)現(xiàn)spawn函數(shù)的方法同前述UNIX中的方法差不多,開設(shè)子進(jìn)程后父進(jìn)程等待子進(jìn)程結(jié)束后才繼續(xù)運(yùn)行。UNIX在其一開始就是多任務(wù)的系統(tǒng),所以從核 心角度上講不需要spawn類函數(shù)。

  另外,有一個(gè)更簡(jiǎn)單的執(zhí)行其它程序的函數(shù)system,它是一個(gè)較高層的函數(shù),實(shí)際上相當(dāng)于在SHELL環(huán)境 下執(zhí)行一條命令,而exec類函數(shù)則是低層的系統(tǒng)調(diào)用。

  (四) Linux的進(jìn)程與Win32的進(jìn)程/線程有何區(qū)別

  熟悉WIN32編程的人一定知道,WIN32的進(jìn)程管理方式與UNIX上有著很大區(qū)別,在UNIX里,只有進(jìn)程的概念 ,但在WIN32里卻還有一個(gè)“線程”的概念,那么UNIX和WIN32在這里究竟有著什么區(qū)別呢?

  UNIX里的fork是七十年代UNIX早期的開發(fā)者經(jīng)過長期在理論和實(shí)踐上的艱苦探索后取得的成果,一方面, 它使操作系統(tǒng)在進(jìn)程管理上付出了最小的代價(jià),另一方面,又為程序員提供了一個(gè)簡(jiǎn)潔明了的多進(jìn)程方法。

  WIN32里的進(jìn)程/線程是繼承自O(shè)S/2的。在WIN32里,“進(jìn)程”是指一個(gè)程序,而“線程”是一個(gè)“進(jìn)程” 里的一個(gè)執(zhí)行“線索”。從核心上講,WIN32的多進(jìn)程與UNIX并無多大的區(qū)別,在WIN32里的線程才相當(dāng)于UNIX 的進(jìn)程,是一個(gè)實(shí)際正在執(zhí)行的代碼。但是,WIN32里同一個(gè)進(jìn)程里各個(gè)線程之間是共享數(shù)據(jù)段的。這才是與 UNIX的進(jìn)程的不同。

  下面這段程序顯示了WIN32下一個(gè)進(jìn)程如何啟動(dòng)一個(gè)線程:(請(qǐng)注意,這是個(gè)終端方式程序,沒有圖形界面 )

  int g;

  DWORD WINAPI ChildProcess( LPVOID lpParameter ){

  int i;

  for ( i = 1; i < 1000; i ) {

  g ;

  printf( "This is Child Thread: %d\n", g );

  }

  ExitThread( 0 );

  };

  void main()

  {

  int threadID;

  int i;

  g = 0;

  CreateThread( NULL, 0, ChildProcess, NULL, 0, &threadID );

  for ( i = 1; i < 1000; i ) {

  g ;

  printf( "This is Parent Thread: %d\n", g );

  }

  }

  在WIN32下,使用CreateThread函數(shù)創(chuàng)建線程,與UNIX不同,線程不是從創(chuàng)建處開始運(yùn)行的,而是由 CreateThread指定一個(gè)函數(shù),線程就從那個(gè)函數(shù)處開始運(yùn)行。此程序同前面的UNIX程序一樣,由兩個(gè)線程各打印1000條信息。threadID是子線程的線程號(hào),另外,全局變量g是子線程與父線程共享的,這就是與UNIX的不同之處。大家可以看出,WIN32的進(jìn)程/線程要比UNIX復(fù)雜,在UNIX里要實(shí)現(xiàn)類似WIN32的線程并不難,只要fork以后,讓子進(jìn)程調(diào)用ThreadProc函數(shù),并且為全局變量開設(shè)共享數(shù)據(jù)區(qū)就行了,但在WIN32下就無法實(shí)現(xiàn)類似fork的功能了。所以現(xiàn)在WIN32下的C語言編譯器所提供的庫函數(shù)雖然已經(jīng)能兼容大多數(shù)UNIX的庫函數(shù), 但卻仍無法實(shí)現(xiàn)fork。

  對(duì)于多任務(wù)系統(tǒng),共享數(shù)據(jù)區(qū)是必要的,但也是一個(gè)容易引起混亂的問題,在WIN32下,一個(gè)程序員很容易忘記線程之間的數(shù)據(jù)是共享的這一情況,一個(gè)線程修改過一個(gè)變量后,另一個(gè)線程卻又修改了它,結(jié)果引起程序出問題。但在UNIX下,由于變量本來并不共享,而由程序員來顯式地指定要共享的數(shù)據(jù),使程序變得 更清晰與安全。

  Linux還有自己的一個(gè)函數(shù)叫clone,這個(gè)函數(shù)是其它UNIX所沒有的,而且通常的Linux也并不提供此函數(shù)(要使用此函數(shù)需自己重新編譯內(nèi)核,并設(shè)置CLONE_ACTUALLY_WORKS_OK選項(xiàng)),clone函數(shù)提供了更多的創(chuàng)建新進(jìn)程的功能,包括象完全共享數(shù)據(jù)段這樣的功能。

  至于WIN32的“進(jìn)程”概念,其含義則是“應(yīng)用程序”,也就是相當(dāng)于UNIX下的exec了。

系統(tǒng)快速啟動(dòng)十大秘訣

  Linux需要重新啟動(dòng)是少有的。可是一旦需要,Linux啟動(dòng)常常是緩慢的。幸好有一些加速的辦法。其中一些方法不太難。咱們瞧一瞧吧。

  1: 撤消多余的服務(wù)

  根據(jù)機(jī)器的用途,很多服務(wù)是不需要的。要是Linux只用作桌面,就不需要sendmail、httpd和另外許多服務(wù)。如果你的服務(wù)器只是Web服務(wù)器,也可以關(guān)掉許多服務(wù)。為此,可轉(zhuǎn)到管理菜單,檢查服務(wù)項(xiàng)目。只需撤消所有不想啟動(dòng)的服務(wù)選項(xiàng)。

  2: 撤消多余的內(nèi)核模塊

  假如你的桌面連接到以太網(wǎng),就不需要裝載無線內(nèi)核模塊。這是較為困難的任務(wù),可能需要重新編譯內(nèi)核,而編譯內(nèi)核不是可以輕松擔(dān)當(dāng)?shù)墓ぷ�。為此,你大概需要�?nèi)核源代碼。接著,按照編譯內(nèi)核的標(biāo)準(zhǔn)步驟進(jìn)行。不同在于你要搜查系統(tǒng),撤除所有不需要的模塊。

  查明系統(tǒng)中當(dāng)前安裝和運(yùn)行的內(nèi)核模塊的方法是安裝Bootchart。它不僅會(huì)給你一個(gè)適宜的模塊清單,而且還會(huì)說明系統(tǒng)啟動(dòng)過程中發(fā)生的事情。還可以發(fā)出命令:chkconfig –list | grep 3:on,弄清楚正在運(yùn)行什么服務(wù)。一旦知道裝載了什么不需要的模塊,就可以在內(nèi)核重新編譯期間將其移除。只要這樣處理,編譯的內(nèi)核就完全適合你的體系結(jié)構(gòu)。

  3: 使用輕型窗口管理器代替GNOME或KDE

  我插入小腳印窗口管理器的原因是——它們大幅度減少圖形(界面)啟動(dòng)時(shí)間。代替不得不額外等待啟動(dòng)GNOME或KDE的30到60秒,為什么不等待用于啟動(dòng)Enlightenment或者XFCE的2到10秒呢?它們不僅節(jié)省啟動(dòng)時(shí)間,還會(huì)節(jié)省內(nèi)存并解救處理臃腫軟體(bloatware)這種令人頭痛的事。

  4: 使用基于文本的登錄而不是圖形登錄

  我的大多數(shù)Linux機(jī)器啟動(dòng)run level 3而非run level 5。這個(gè)運(yùn)行級(jí)別將停在文本登錄模式,我就在這個(gè)地方登錄并發(fā)出startx命令,開始選擇桌面。圖形登錄模式做兩件事:增加裝入時(shí)間并引起頭痛的問題即試圖從拙劣的X windows掙脫出來。

  5: 使用輕型發(fā)行版

  不要裝載重型的Fedora,為什么不試一下Gentoo、Arch或Puppy Linux呢?這些較小的發(fā)行版的啟動(dòng)時(shí)間比更加臃腫的Fedora(甚至Ubuntu)要快很多。在較大的發(fā)行版中,OpenSuSE聲稱啟動(dòng)最快,但我還沒有親自試驗(yàn)。在的Fedora和Ubuntu之間,Ubuntu擊敗Fedora的啟動(dòng)時(shí)間(而且是即開即用)。

  6: 使用Open BIOS

  要是你相當(dāng)聰明能干,準(zhǔn)備升級(jí)PC固件,可以考慮遷移到開源BIOS。一個(gè)附加說明,使用開放固件允許Linux啟動(dòng)時(shí)真正初始化硬件(而不依賴BIOS)。最重要的是,許多開放BIOS可以設(shè)置滿足機(jī)器的特殊需要。如果不走開放BIOS之路,至少也可以設(shè)置BIOS不尋找不存在的軟盤驅(qū)動(dòng)器,即直接啟動(dòng)個(gè)硬盤驅(qū)動(dòng)器(首先不是CD驅(qū)動(dòng)器)。

  7: 回避DHCP

  如果你工作在地址租約不是問題的家庭網(wǎng)絡(luò)(或者小型企業(yè)網(wǎng)絡(luò))上,那么,機(jī)器就用靜態(tài)IP地址。這將使機(jī)器不必出外訪問DHCP服務(wù)器來獲得IP地址。如果采取這種途徑,就要確保配置文件/etc/resolve.conf也表達(dá)你的DNS服務(wù)器地址。   8: 熱插拔可免就免

  熱插拔是指允許把新設(shè)備插上電源并立即使用的系統(tǒng)。如果你知道你的服務(wù)器不需要這種系統(tǒng),就刪除它。這將減少啟動(dòng)時(shí)間。在許多系統(tǒng)上,熱插拔消耗大量啟動(dòng)時(shí)間。排除熱插拔將發(fā)生的變化取決于你所用的發(fā)行版。注意:就絕大部分而言,udev已經(jīng)取代熱插拔。但如果你還在運(yùn)行老一點(diǎn)的發(fā)行版,這樣做還是適合的。

  9: 要是真的大膽無畏,可嘗試一下initng

  initng系統(tǒng)充當(dāng)sysvinit系統(tǒng)的替換物,并承諾徹底減少類UNIX操作系統(tǒng)的啟動(dòng)時(shí)間。如果你愿意了解運(yùn)行中的initng系統(tǒng),可以試一試Pingwinek LiveCD。

  10: 利用Debian具有的代碼

  要是正在使用Debian,就有一行可用來將你的啟動(dòng)腳本轉(zhuǎn)換成并行運(yùn)行的簡(jiǎn)單代碼。如果檢查一下/etc/init.d/rc腳本,就會(huì)看到:大約在24行有CONCURRENCY=none。把這一行改為CONCURRENCY=shell,你有可能目睹啟動(dòng)時(shí)間的減少。

  上述大部分應(yīng)該是最重要的,當(dāng)然最快的使Linux啟動(dòng)提速的方法就是不要重啟,所以,極少重新啟動(dòng)一般可以減輕啟動(dòng)時(shí)間的擔(dān)子。

維庫電子通,電子知識(shí),一查百通!

已收錄詞條129155個(gè)

盘山县| 嘉禾县| 金堂县| 河间市| 青河县| 古田县| 留坝县| 云林县| 天门市| 东山县| 镇康县| 博湖县| 富宁县| 泰安市| 石阡县| 揭东县| 望谟县| 郁南县| 大丰市| 休宁县| 耒阳市| 巍山| 武夷山市| 尼木县| 资讯| 密云县| 原阳县| 马边| 肇州县| 响水县| 桓台县| 涞水县| 普宁市| 崇左市| 河北省| 洪湖市| 临城县| 剑阁县| 灌南县| 昭平县| 兴安盟|