1. Linux內(nèi)核學(xué)習(xí)之進(jìn)程和線程初探

1 進(jìn)程

進(jìn)程指的是處于執(zhí)行期的程序。但是需要注意的是進(jìn)程并不僅僅包括一段可執(zhí)行程序的代碼举瑰,它同時(shí)還包括其他資源此迅,例如打開的文件旧巾,掛起的信號(hào)鲁猩,內(nèi)核內(nèi)部數(shù)據(jù)廓握,處理器狀態(tài)隙券,具有內(nèi)存映射的地址空間和執(zhí)行線程以及數(shù)據(jù)段等娱仔。

1.1 進(jìn)程描述符

一個(gè)操作系統(tǒng)如果想管理好進(jìn)程,那么操作系統(tǒng)就需要這個(gè)進(jìn)程的所有信息薪铜,Linux內(nèi)核成功抽象了進(jìn)程這一概念隔箍,然后使用task_struct即進(jìn)程描述符來對進(jìn)程進(jìn)行管理蜒滩,同時(shí)內(nèi)核使用雙向鏈表(即任務(wù)隊(duì)列)對進(jìn)程描述符進(jìn)行了相應(yīng)的組織。(task_struct結(jié)構(gòu)體定義在<linux/sched.h>)捡遍。

task_struct和任務(wù)隊(duì)列

task_struct在32位計(jì)算機(jī)中占有1.7KB画株。包含一個(gè)進(jìn)程所有的信息谓传,包含打開的文件续挟,進(jìn)程地址空間诗祸,掛起的信號(hào)轴总,進(jìn)程狀態(tài)等怀樟,具體可以參照在Linux內(nèi)核代碼中定義的task_struct結(jié)構(gòu)體代碼漂佩。Linux在分配進(jìn)程描述符時(shí)投蝉,使用了slab機(jī)制(可以查看進(jìn)程創(chuàng)建一節(jié))瘩缆。當(dāng)進(jìn)程描述符task_struct分配完畢之后庸娱,需要對其進(jìn)行存放。

1.2 內(nèi)核進(jìn)程操作

對于一個(gè)進(jìn)程來說归露,在內(nèi)存中會(huì)分配一段內(nèi)存空間剧包,一般來說這個(gè)空間為1或者2個(gè)頁往果,這個(gè)內(nèi)存空間就是進(jìn)程的內(nèi)核棧陕贮。在進(jìn)程內(nèi)核棧的棧底有一個(gè)結(jié)構(gòu)體變量為thread_info掉缺,這個(gè)結(jié)構(gòu)體變量中包含了一個(gè)指向該進(jìn)程描述符task_struct的指針攀圈,這個(gè)變量的存在峦甩,可以使內(nèi)核快速地獲得某一個(gè)進(jìn)程的進(jìn)程描述符凯傲,從而提高響應(yīng)速度。在x86體系結(jié)構(gòu)中幌缝,內(nèi)核中的current宏就是通過對于這個(gè)結(jié)構(gòu)體的訪問來實(shí)現(xiàn)的涵卵,而在其他寄存器豐富的體系結(jié)構(gòu)中看轿偎,可能會(huì)沒有使用thread_info結(jié)構(gòu)體被廓,而是直接使用某一個(gè)寄存器來完成例如PPC體系結(jié)構(gòu)。

/*x86中thread_info的定義*/
struct thread_info {
    struct task_struct  *task;      /* main task structure */
    struct exec_domain  *exec_domain;   /* execution domain */
    unsigned long       flags;      /* low level flags */
    unsigned long       status;     /* thread-synchronous flags */
    __u32           cpu;        /* current CPU */
    int         preempt_count;  /* 0 => preemptable, <0 => BUG */

    mm_segment_t        addr_limit; /* thread address space:
                         * 0-0xBFFFFFFF for user-thead
                         * 0-0xFFFFFFFF for kernel-thread
                         */
    struct restart_block    restart_block;
    __u8            supervisor_stack[0];
};

1.3 進(jìn)程PID

Linux的內(nèi)核使用PID來對進(jìn)程進(jìn)行唯一標(biāo)識(shí)球碉。PID是pid_t的隱含類型,PID的值受到<linux/threads.h>頭文件中規(guī)定的最大值的限制多律,但是為了和傳統(tǒng)的Unix操作系統(tǒng)兼容狼荞,PID會(huì)被默認(rèn)設(shè)置為32768即short int短整型的最大值相味。PID的最大值是系統(tǒng)中允許同時(shí)存在的進(jìn)程的最大數(shù)目丰涉。PID 的最大值可以通過/proc/sys/kernel/pid_max來修改一死。

1.4 進(jìn)程家族樹

Linux和Unix系統(tǒng)一樣投慈,進(jìn)程之間存在明顯的繼承關(guān)系伪煤。所有的進(jìn)程都是PID為1的init進(jìn)程的后代抱既。內(nèi)核會(huì)在系統(tǒng)啟動(dòng)的最后階段啟動(dòng)init進(jìn)程防泵,這個(gè)進(jìn)程回去讀取并且執(zhí)行系統(tǒng)的初始化腳本(initscript)執(zhí)行相關(guān)程序捷泞,完成整個(gè)系統(tǒng)的啟動(dòng)肚邢。
在Linux操作系統(tǒng)中骡湖,每個(gè)進(jìn)程都會(huì)有父進(jìn)程响蕴,每個(gè)進(jìn)程都會(huì)有0到n個(gè)子進(jìn)程。同一個(gè)父進(jìn)程的所有進(jìn)程被稱為兄弟辖试。進(jìn)程描述符中罐孝,包含了指向父進(jìn)程的指針莲兢,還包含了一個(gè)children子進(jìn)程鏈表(init進(jìn)程的進(jìn)程描述符是靜態(tài)分配的)改艇。所以通過簡單的遍歷就可訪問到系統(tǒng)中的所有進(jìn)程谒兄。在代碼中特意提供了for_each_process(task)宏來進(jìn)行對整個(gè)進(jìn)程隊(duì)列(或稱任務(wù)隊(duì)列)的訪問能力。

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

2.1 創(chuàng)建過程

在Linux進(jìn)程創(chuàng)建不同于其他操作系統(tǒng)瘦穆,Linux操作系統(tǒng)提供了兩個(gè)單獨(dú)的函數(shù)完成進(jìn)程的創(chuàng)建工作纪隙。其中fork()函數(shù)通過拷貝完成子進(jìn)程的創(chuàng)建,子進(jìn)程會(huì)完全拷貝父進(jìn)程中的絕大多數(shù)資源扛或,(除了PID和PPID绵咱,以及一些敏感資源和統(tǒng)計(jì)量)。然后在使用exec()函數(shù)完成可執(zhí)行文件的讀取熙兔,并且將其載入地址空間運(yùn)行悲伶。而其他操作系統(tǒng)一般只使用一個(gè)函數(shù)完成上述的兩步操作。

fork()函數(shù)是通過clone()系統(tǒng)調(diào)用實(shí)現(xiàn)的住涉。此調(diào)用會(huì)通過一系列參數(shù)標(biāo)志指明父子進(jìn)程需要共享的資源麸锉。庫函數(shù)根據(jù)參數(shù)標(biāo)志調(diào)用clone()clone()調(diào)用do_fork()函數(shù)柳爽。do_fork()函數(shù)在kernel/fork.c中定義,并且完成了創(chuàng)建中的大部分工作。然后該函數(shù)會(huì)去調(diào)用copy_process()函數(shù)copy_process()函數(shù)完成了下述工作:
1) 調(diào)用duo_task_struct()函數(shù)為新進(jìn)程創(chuàng)建內(nèi)核棧诡蜓、thread_info脚粟、和task_struct,但是這些值都和當(dāng)前進(jìn)程的相同,只是一份簡單的復(fù)制
2) 檢查當(dāng)前用戶的進(jìn)程總數(shù)是否超過限制
3) 將進(jìn)程描述符中關(guān)于目前進(jìn)程的統(tǒng)計(jì)信息清零,使得子進(jìn)程和父進(jìn)程能夠進(jìn)行區(qū)分
4) 將子進(jìn)程狀態(tài)設(shè)為TASK_UNINTERRUPTIBLE,使其不能運(yùn)行
5) 調(diào)用copy_flag()函數(shù)更新task_structflags成員术幔。將超級用戶權(quán)限標(biāo)志符PF_SUPERPRIV清零,然后將進(jìn)程未調(diào)用exec()函數(shù)標(biāo)志位PF_FORKNOEXEC置位。
6) 調(diào)用alloc_pid()為新進(jìn)程分配一個(gè)有效PID
7) 根據(jù)傳遞給clone()的參數(shù)標(biāo)志兜畸,該函數(shù)(即copy_process()函數(shù))拷貝或者共享打開的文件煞躬、文件系統(tǒng)信息、信號(hào)處理函數(shù)、進(jìn)程地址空間和命名空間皱卓。
8) 掃尾,然后返回一個(gè)指向子進(jìn)程的指針

當(dāng)然還有其他形式的fork()函數(shù)實(shí)現(xiàn)方式颅和。例如vfork()函數(shù)功能和fork()函數(shù)相同,但是vfork()函數(shù)不會(huì)拷貝父進(jìn)程的頁表項(xiàng)彼绷。vfork()生成的子進(jìn)程作為一個(gè)單獨(dú)的線程在其地址空間內(nèi)運(yùn)行猜旬,父進(jìn)程會(huì)被阻塞熟嫩,直到子進(jìn)程退出或者調(diào)用exec()函數(shù)柠逞,子進(jìn)程不允許向地址空間內(nèi)寫入數(shù)據(jù)个束。但是在使用了寫時(shí)拷貝技術(shù)之后,這一項(xiàng)技術(shù)其實(shí)已經(jīng)無關(guān)緊要了。

2.2 進(jìn)程創(chuàng)建優(yōu)化

由于進(jìn)程描述符task_struct是一個(gè)在進(jìn)程創(chuàng)建時(shí)必須的數(shù)據(jù)結(jié)構(gòu),所以進(jìn)程的創(chuàng)建速度可以通過加速進(jìn)程描述符的創(chuàng)建來提高糠悯,有鑒于此讯泣,內(nèi)核使用了slab機(jī)制來對其進(jìn)行處理。所謂slab機(jī)制棋凳,就是對于頻繁被使用的數(shù)據(jù)結(jié)構(gòu),會(huì)進(jìn)行緩存骄噪,而不是使用完畢之后直接進(jìn)行釋放。這樣做的好處是,如果需要頻繁創(chuàng)建某一數(shù)據(jù)結(jié)構(gòu)變量,只是直接使用即可橱脸,而不需要進(jìn)行內(nèi)存的申請,使用完畢也不需要釋放惠拭,大大減少了分配內(nèi)存和回收內(nèi)存的時(shí)間条霜。使用slab機(jī)制后,進(jìn)程描述符可以被快速地建立抹沪,同時(shí)進(jìn)程銷毀時(shí)也不需要去進(jìn)行進(jìn)程描述符的內(nèi)存釋放噪馏。

當(dāng)然Linux內(nèi)核在其他方面也使用了加快進(jìn)程創(chuàng)建的方法。上面講到封豪,Linux創(chuàng)建進(jìn)程使用fork()函數(shù)來完成廓推,而fork()函數(shù)又使用clone()系統(tǒng)調(diào)用來實(shí)現(xiàn)涝婉,但是需要注意的是桥温,創(chuàng)建一個(gè)新進(jìn)程時(shí),Linux內(nèi)核加入了寫時(shí)拷貝機(jī)制來加速進(jìn)程的創(chuàng)建遵湖,而不是完整地對進(jìn)程所有內(nèi)容進(jìn)行簡單的復(fù)制捌蚊。所謂寫時(shí)拷貝就是在新進(jìn)程創(chuàng)建時(shí)赴涵,子進(jìn)程和父進(jìn)程共享一個(gè)進(jìn)程地址空間拷貝杨拐,當(dāng)子進(jìn)程或者父進(jìn)程對這個(gè)拷貝執(zhí)行寫入操作后鳍徽,數(shù)據(jù)才會(huì)被復(fù)制瑰剃,然后進(jìn)行各自的修改,所以資源在未進(jìn)行寫入時(shí),以只讀方式共享梯醒。這種寫時(shí)拷貝的方式诀蓉,將進(jìn)程的創(chuàng)建開銷從子進(jìn)程對父進(jìn)程資源的大量復(fù)制,簡化為復(fù)制父進(jìn)程的頁表和子進(jìn)程唯一進(jìn)程描述符的創(chuàng)建脑豹。

2.3 進(jìn)程終結(jié)

進(jìn)程終結(jié)時(shí)筑悴,內(nèi)核必須要釋放他所占用的資源定躏,然后通知父進(jìn)程。進(jìn)程的析構(gòu)發(fā)生在exit()系統(tǒng)調(diào)用時(shí)液茎,可以是顯式的逞姿,也可以是隱式的辞嗡,例如從某個(gè)程序的主函數(shù)返回(對于C語言來說其實(shí)會(huì)在main()函數(shù)的返回點(diǎn)后面設(shè)置exit()代碼)。當(dāng)進(jìn)程收到不能處理但是又不能忽視的信號(hào)或者出現(xiàn)異常時(shí)滞造,也可能會(huì)被動(dòng)終結(jié)欲间。但是進(jìn)程在終結(jié)是,大部分還是會(huì)調(diào)用do_exit()完成(在kernel/exit.c中定義)断部。
(1) 將task_struct中的標(biāo)志成員設(shè)置為PF_EXITING
(2) 調(diào)用del_timer_sync()刪除任意內(nèi)核定時(shí)器猎贴。根據(jù)返回的結(jié)果確認(rèn)沒有任何定時(shí)器在排隊(duì),同時(shí)也沒有任何定時(shí)器處理程序在運(yùn)行蝴光。
(3) 若開啟了BSD的進(jìn)程記賬功能她渴,那么還需要調(diào)用acct_update_integrals()來輸出記賬信息
(4) 調(diào)用exit_mm()釋放進(jìn)程占用的mm_struct,若是沒有其他進(jìn)程使用這個(gè)地址空間蔑祟,那么就徹底釋放此地址空間
(5) 調(diào)用sem_exit()函數(shù)趁耗,若進(jìn)程排隊(duì)等待IPC信號(hào),則離開隊(duì)列
(6) 調(diào)用exit_file()exit_fs()疆虚,分別遞減文件描述符苛败、文件系統(tǒng)數(shù)據(jù)的引用計(jì)數(shù)。若釋放后引用計(jì)數(shù)為0径簿,則直接釋放罢屈。
(7) 將存放在task_struct的exit_code成員中的任務(wù)退出代碼置為由exit()提供的任務(wù)退出代碼,或者完成任何其他由內(nèi)核機(jī)制規(guī)定的退出動(dòng)作篇亭。退出代碼的存放是為了供父進(jìn)程檢索
(8) 調(diào)用exit_notify()函數(shù)向自己的父進(jìn)程發(fā)送信號(hào)缠捌,并且給自己的子進(jìn)程重新尋找養(yǎng)父,養(yǎng)父為線程組中的其他線程或者為init進(jìn)程译蒂,然后將進(jìn)程狀態(tài)置為EXIT_ZOMBLE曼月。
(9) do_exit()調(diào)用schedule()切換到新進(jìn)程。這是do_exit()執(zhí)行的最后代碼柔昼,退出后就不再返回哑芹。

2.3.1 刪除進(jìn)程描述符

進(jìn)程在執(zhí)行完do_exit()函數(shù)調(diào)用之后,會(huì)處于EXIT_ZOMBIE退出狀態(tài)捕透,其所占有的內(nèi)存就是內(nèi)核棧聪姿、thread_info結(jié)構(gòu)task_struct結(jié)構(gòu)體。處于這個(gè)狀態(tài)的進(jìn)程唯一目的就是向父進(jìn)程提供信息激率。父進(jìn)程檢索到信息或者通知內(nèi)核那是無關(guān)的信息后咳燕,由進(jìn)程所持有的剩余的內(nèi)存釋放勿决。

調(diào)用do_exit()之后乒躺,雖然線程已經(jīng)僵死不再運(yùn)行,但是系統(tǒng)還保留了它的進(jìn)程描述符低缩。這樣做可以使系統(tǒng)能夠在子進(jìn)程終結(jié)后仍獲取其信息嘉冒。所以進(jìn)程的終結(jié)清理操作可以和進(jìn)程描述符的刪除操作分開運(yùn)行曹货。
在刪除進(jìn)程描述符的時(shí)候,會(huì)調(diào)用release_task()讳推,完成以下操作:
(1)調(diào)用__exit_signal()顶籽,由次函數(shù)調(diào)用_unhash_process(),后者又調(diào)用detach_pid()pidhash上刪除該進(jìn)程银觅,同時(shí)從任列表中刪除該進(jìn)程
2)__exit_signal()釋放目前僵死進(jìn)程所使用的所有剩余資源礼饱,并進(jìn)行最終的統(tǒng)計(jì)和記錄。
3)如果這個(gè)進(jìn)程是進(jìn)程組最后一個(gè)進(jìn)程究驴,并且領(lǐng)頭進(jìn)程已經(jīng)死掉镊绪,那么release_task()通知僵死的領(lǐng)頭進(jìn)程的父進(jìn)程
4)調(diào)用put_task_struct()釋放進(jìn)程內(nèi)核棧thread_info結(jié)構(gòu)所占用的頁,釋放task_struct所占的slab高速緩存洒忧。

若父進(jìn)程在子進(jìn)程之前退出蝴韭,則首先會(huì)為子進(jìn)程在當(dāng)前進(jìn)程組內(nèi)宣召一個(gè)進(jìn)程作為父親,若不行熙侍,就讓init進(jìn)程作為父進(jìn)程榄鉴。

3 線程

線程是指在進(jìn)程中活動(dòng)的對象,相對而言蛉抓,線程僅僅局限在進(jìn)程內(nèi)部庆尘,線程擁有的資源遠(yuǎn)遠(yuǎn)比進(jìn)程小,僅僅包括獨(dú)立的程序計(jì)數(shù)器和進(jìn)程棧以及一組進(jìn)程寄存器巷送。在其他操作系統(tǒng)中進(jìn)程和線程的概念往往會(huì)被嚴(yán)格區(qū)分减余,但是對于Linux操作系統(tǒng)內(nèi)核而言,它對線程和進(jìn)程并不進(jìn)行區(qū)分惩系,線程通常被視為一個(gè)與其他進(jìn)程共享某些資源的進(jìn)程位岔。每個(gè)線程都擁有自己的task_struct,所以線程在Linux內(nèi)核中也被視為一個(gè)進(jìn)程堡牡,這是和其他操作系統(tǒng)截然不同的抒抬。
線程的創(chuàng)建和進(jìn)程是類似的但是在調(diào)用clone()的時(shí)候,會(huì)傳遞一些特殊的標(biāo)志位晤柄,例如CLONE_VM擦剑,CLONE_FSCLONE_FILES芥颈,CLONE_SIGHAND惠勒,這些值都是由下表定義的。


clone()參數(shù)標(biāo)志

內(nèi)核很多時(shí)候還需要在后臺(tái)執(zhí)行一些操作爬坑,這些都是由內(nèi)核線程(kernel thread)完成纠屋。內(nèi)核線程獨(dú)立于內(nèi)核進(jìn)程運(yùn)行,同時(shí)內(nèi)核線程沒有獨(dú)立的地址空間盾计,并且不會(huì)切換到用戶空間售担,其他和普通線程一樣赁遗,沒有區(qū)別。
內(nèi)核線程一般是自動(dòng)從內(nèi)核進(jìn)程中衍生而出族铆,同樣內(nèi)核線程也是通過clone()系統(tǒng)調(diào)用實(shí)現(xiàn)岩四,并且需要調(diào)用wake_up_process()函數(shù)來進(jìn)行明確地喚醒。kthread_run()可以完成線程的喚醒和運(yùn)行哥攘,但是本質(zhì)上只是調(diào)用了kthread_create()wake_up_process()剖煌。內(nèi)核線程可以使用do_exit()函數(shù)退出,也可以由內(nèi)核其他部分調(diào)用kthread_stop()函數(shù)來進(jìn)行退出逝淹。

4 進(jìn)程和線程的區(qū)別

對于Linux內(nèi)核而言末捣,進(jìn)程和線程沒有區(qū)別。對于Linux內(nèi)核而言创橄,并沒有對線程進(jìn)行特殊處理箩做,而是將線程與進(jìn)程同等對待,這與其他操作系統(tǒng)完全不同妥畏。其他操作系統(tǒng)都提供了專門的機(jī)制去實(shí)現(xiàn)多線程機(jī)制邦邦,由于Linux強(qiáng)大輕便快速的進(jìn)程創(chuàng)建手段,所以Linux僅僅將線程看作是進(jìn)程共享了進(jìn)程資源的多個(gè)進(jìn)程醉蚁,對于Linux內(nèi)核來說創(chuàng)建線程等價(jià)于創(chuàng)建一個(gè)進(jìn)程燃辖。通過Linux內(nèi)核可以得知,一個(gè)進(jìn)程的多線程其實(shí)只是共享了很多資源网棍,例如地址空間等黔龟。由此產(chǎn)生了“Linux沒有多線程機(jī)制“”這一說法,但是本質(zhì)上來說滥玷,并不是Linux沒有多線程機(jī)制氏身,只是其實(shí)現(xiàn)方式和其他操作系統(tǒng)不同而已。

這是個(gè)人在閱讀《Linux內(nèi)核設(shè)計(jì)與實(shí)現(xiàn)》時(shí)候的一點(diǎn)心得惑畴,里面加入了一些自己關(guān)于操作系統(tǒng)的理解蛋欣,對自己的現(xiàn)有的知識(shí)進(jìn)行梳理,如有錯(cuò)誤敬請指正如贷。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末陷虎,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子杠袱,更是在濱河造成了極大的恐慌尚猿,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件楣富,死亡現(xiàn)場離奇詭異凿掂,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)菩彬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進(jìn)店門缠劝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來潮梯,“玉大人骗灶,你說我怎么就攤上這事惨恭。” “怎么了耙旦?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵脱羡,是天一觀的道長。 經(jīng)常有香客問我免都,道長锉罐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任绕娘,我火速辦了婚禮脓规,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘险领。我一直安慰自己侨舆,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布绢陌。 她就那樣靜靜地躺著挨下,像睡著了一般。 火紅的嫁衣襯著肌膚如雪脐湾。 梳的紋絲不亂的頭發(fā)上臭笆,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天,我揣著相機(jī)與錄音秤掌,去河邊找鬼愁铺。 笑死,一個(gè)胖子當(dāng)著我的面吹牛闻鉴,可吹牛的內(nèi)容都是我干的帜讲。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼椒拗,長吁一口氣:“原來是場噩夢啊……” “哼似将!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蚀苛,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤在验,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后堵未,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體腋舌,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年渗蟹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了块饺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赞辩。...
    茶點(diǎn)故事閱讀 40,102評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖授艰,靈堂內(nèi)的尸體忽然破棺而出辨嗽,到底是詐尸還是另有隱情,我是刑警寧澤淮腾,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布糟需,位于F島的核電站,受9級特大地震影響谷朝,放射性物質(zhì)發(fā)生泄漏洲押。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一圆凰、第九天 我趴在偏房一處隱蔽的房頂上張望杈帐。 院中可真熱鬧,春花似錦专钉、人聲如沸挑童。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽炮沐。三九已至,卻和暖如春回怜,著一層夾襖步出監(jiān)牢的瞬間大年,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工玉雾, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留翔试,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓复旬,卻偏偏與公主長得像垦缅,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子驹碍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 又來到了一個(gè)老生常談的問題壁涎,應(yīng)用層軟件開發(fā)的程序員要不要了解和深入學(xué)習(xí)操作系統(tǒng)呢? 今天就這個(gè)問題開始志秃,來談?wù)劜?..
    tangsl閱讀 4,129評論 0 23
  • Linux 進(jìn)程管理與程序開發(fā) 進(jìn)程是Linux事務(wù)管理的基本單元怔球,所有的進(jìn)程均擁有自己獨(dú)立的處理環(huán)境和系統(tǒng)資源,...
    JamesPeng閱讀 2,468評論 1 14
  • 1,Linux中的進(jìn)程管理1)進(jìn)程和線程進(jìn)程是資源分配的最小單位浮还。線程是操作系統(tǒng)調(diào)度執(zhí)行的最小單位竟坛。進(jìn)程和線程是程...
    SDY_0656閱讀 471評論 0 0
  • 這節(jié)課來講解下,油漆桶工具箱中專門針對3D材質(zhì)選區(qū)的一個(gè)工具“3D材質(zhì)拖放工具”的使用方法和技巧。 選擇工具箱中的...
    e5a2ee3bb269閱讀 1,444評論 0 1
  • 論文交上担汤,補(bǔ)考過了涎跨,大學(xué)就畢業(yè)了,沒有大學(xué)四級證的四年崭歧,沒有計(jì)算機(jī)二級證的四年隅很,沒有普通話證,沒有獎(jiǎng)學(xué)金 ...
    寒眼閱讀 192評論 0 0