青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

興海北路

---男兒仗劍自橫行
<2008年3月>
2425262728291
2345678
9101112131415
16171819202122
23242526272829
303112345

統(tǒng)計(jì)

  • 隨筆 - 85
  • 文章 - 0
  • 評(píng)論 - 17
  • 引用 - 0

常用鏈接

留言簿(6)

隨筆分類(lèi)

隨筆檔案

收藏夾

全是知識(shí)啊

搜索

  •  

最新評(píng)論

閱讀排行榜

評(píng)論排行榜

shell編程范例之進(jìn)程的操作
by falcon<zhangjinw@gmail.com>
2008-02-21

    這一小節(jié)寫(xiě)了很久,到現(xiàn)在才寫(xiě)完。本來(lái)關(guān)注的內(nèi)容比較多,包括程序開(kāi)發(fā)過(guò)程的細(xì)節(jié)、ELF格式的分析、進(jìn)程的內(nèi)存映像等,后來(lái)搞得“雪球越滾越大”,甚至 脫離了shell編程關(guān)注的內(nèi)容。所以呢,想了個(gè)小辦法,“大事化小,小事化了”,把涉及到的內(nèi)容分成如下幾個(gè)部分:
    1、把VIM打造成源代碼編輯器(源代碼編輯過(guò)程:用VIM編輯代碼的一些技巧)
    2、GCC編譯的背后 第一部分:預(yù)處理和編譯 第二部分:匯編和鏈接(編譯過(guò)程:預(yù)處理、編譯、匯編、鏈接)
    3、程序執(zhí)行的那一剎那 (執(zhí)行過(guò)程:當(dāng)我們從命令行輸入一個(gè)命令之后)
    4、進(jìn)程的內(nèi)存映像 (進(jìn)程加載過(guò)程:程序在內(nèi)存里是個(gè)什么樣子)
    5、動(dòng)態(tài)符號(hào)鏈接的細(xì)節(jié)(動(dòng)態(tài)鏈接過(guò)程:函數(shù)puts/printf的地址在哪里)
    6、代碼測(cè)試、調(diào)試與優(yōu)化小結(jié)(程序開(kāi)發(fā)過(guò)后:內(nèi)存溢出了嗎?有緩沖區(qū)溢出?代碼覆蓋率如何測(cè)試呢?怎么調(diào)試匯編代碼?有哪些代碼優(yōu)化技巧和方法呢?)
    7、    8、進(jìn)程和進(jìn)程的基本操作(本小節(jié))
    呵呵,好多。終于可以一部分一部分地完成了,不會(huì)再有一種對(duì)著一個(gè)大蛋糕卻不知道如何下口的尷尬了。
    進(jìn)程作為程序真正發(fā)揮作用時(shí)的“形態(tài)”,我們有必要對(duì)它的一些相關(guān)操作非常熟悉,這一節(jié)主要描述進(jìn)程相關(guān)的概念和操作,將介紹包括程序、進(jìn)程、作業(yè)等基本概念以及進(jìn)程狀態(tài)查詢、進(jìn)程通信等相關(guān)的基本操作等。

1、什么是程序,什么又是進(jìn)程

    程序是指令的集合,而進(jìn)程則是程序執(zhí)行的基本單元。為了讓程序完成它的工作,我們必須讓程序運(yùn)行起來(lái)成為進(jìn)程,進(jìn)而利用處理器資源,內(nèi)存資源,進(jìn)行各種I/O操作,從而完成某項(xiàng)指定的工作。
    在這個(gè)意思上說(shuō),程序是靜態(tài)的,而進(jìn)程則是動(dòng)態(tài)的。
    而進(jìn)程有區(qū)別于程序的地方還有,進(jìn)程除了包含程序文件中的指令數(shù)據(jù)意外,還需要在內(nèi)核中有一個(gè)數(shù)據(jù)結(jié)構(gòu)用以存放特定進(jìn)程的相關(guān)屬性,以便內(nèi)核更好的管理和調(diào)度進(jìn)程,從而完成多進(jìn)程協(xié)作的任務(wù)。因此,從這個(gè)意義上可以說(shuō)“高于”程序,超出了程序指令本身。
    如果進(jìn)行過(guò)多進(jìn)程程序的開(kāi)發(fā),你又會(huì)發(fā)現(xiàn),一個(gè)程序可能創(chuàng)建多個(gè)進(jìn)程,通過(guò)多個(gè)進(jìn)程的交互完成任務(wù)。在Linux下,多進(jìn)程的創(chuàng)建通常是通過(guò)fork系統(tǒng)調(diào)用實(shí)現(xiàn)的。從這個(gè)意義上來(lái)說(shuō)程序則”包含”了進(jìn)程。
    另外一個(gè)需要明確的是,程序可以由多種不同的程序語(yǔ)言描述,包括C語(yǔ)言程序、匯編語(yǔ)言程序和最后編譯產(chǎn)生的機(jī)器指令等。
   
    下面我們簡(jiǎn)單討論一下Linux下面如何通過(guò)shell進(jìn)行進(jìn)程的相關(guān)操作。

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

    通常在命令行鍵入某個(gè)程序文件名以后,一個(gè)進(jìn)程就被創(chuàng)建了。例如,

Quote:

$ sleep 100 &            #讓sleep程序在后臺(tái)運(yùn)行
[1] 9298
$ pidof sleep             #用pidof可以查看指定程序名的進(jìn)程ID
9298
$ cat /proc/9298/maps    #查看進(jìn)程的內(nèi)存映像
08048000-0804b000 r-xp 00000000 08:01 977399     /bin/sleep
0804b000-0804c000 rw-p 00003000 08:01 977399     /bin/sleep
0804c000-0806d000 rw-p 0804c000 00:00 0          [heap]
b7c8b000-b7cca000 r--p 00000000 08:01 443354    
...
bfbd8000-bfbed000 rw-p bfbd8000 00:00 0          [stack]
ffffe000-fffff000 r-xp 00000000 00:00 0          [vdso]


    當(dāng)一個(gè)程序被執(zhí)行以后,程序被加載到內(nèi)存中,成為了一個(gè)進(jìn)程。上面顯示了該進(jìn)程的內(nèi)存映像(虛擬內(nèi)存),包括程序指令、數(shù)據(jù),以及一些用于存放程命令行參數(shù)、環(huán)境變量的棧空間,用于動(dòng)態(tài)內(nèi)存申請(qǐng)的堆空間都被分配好了。
    關(guān)于程序在命令行執(zhí)行過(guò)程的細(xì)節(jié),請(qǐng)參考《Linux命令行下程序執(zhí)行的那一剎那》。

    實(shí)際上,創(chuàng)建一個(gè)進(jìn)程,也就是說(shuō)讓程序運(yùn)行,還有其他的辦法,比如,通過(guò)一些配置讓系統(tǒng)啟動(dòng)時(shí)自動(dòng)啟動(dòng)我們的程序(具體參考"man init"),或者是通過(guò)配置crond(或者at)讓它定時(shí)啟動(dòng)我們的程序。除此之外,還有一個(gè)方式,那就是編寫(xiě)shell腳本,把程序?qū)懭胍粋€(gè)腳本文 件,當(dāng)執(zhí)行腳本文件時(shí),文件中的程序?qū)⒈粓?zhí)行而成為進(jìn)程。這些方式的細(xì)節(jié)就不介紹了,下面介紹如何查看進(jìn)程的屬性。

    需要補(bǔ)充一點(diǎn)的是,在命令行下執(zhí)行程序時(shí),我們可以通過(guò)ulimit內(nèi)置命令來(lái)設(shè)置進(jìn)程可以利用的資源,比如進(jìn)程可以打開(kāi)的最大文件描述符個(gè)數(shù),最大的棧空間,虛擬內(nèi)存空間等。具體用法見(jiàn)"help ulimit"。

3、查看進(jìn)程的屬性和狀態(tài)

    我們可以通過(guò)ps命令查看進(jìn)程的相關(guān)屬性和狀態(tài),這些信息包括進(jìn)程所屬用戶,進(jìn)程對(duì)應(yīng)的程序,進(jìn)程對(duì)cpu和內(nèi)存的使用情況等信息。熟悉如何查看它們有助于我們進(jìn)行相關(guān)的統(tǒng)計(jì)分析和進(jìn)一步的操作。

Quote:

$ ps -ef #查看系統(tǒng)所有當(dāng)前進(jìn)程的屬性
$ ps -C init #查看命令中包含某個(gè)指定字符的程序?qū)?yīng)的進(jìn)程,進(jìn)程ID是1,TTY為?表示和終端沒(méi)有關(guān)聯(lián)
  PID TTY          TIME CMD
    1 ?        00:00:01 init
$ ps -U falcon #選擇某個(gè)特定用戶啟動(dòng)的進(jìn)程
$ ps -e -o "%C %c"  #可以按照指定格式輸出指定內(nèi)容,這里會(huì)輸出命令名和cpu使用率
$ ps -e -o "%C %c" | sort -u -k1 -r | head -5  #這樣則會(huì)打印cpu使用率最高的前4個(gè)程序
 7.5 firefox-bin
 1.1 Xorg
 0.8 scim-panel-gtk
 0.2 scim-bridge
$ ps -e -o "%z %c" | sort -n -k1 -r | head -5  #使用虛擬內(nèi)存最大的5個(gè)進(jìn)程
349588 firefox-bin
 96612 xfce4-terminal
 88840 xfdesktop
 76332 gedit
 58920 scim-panel-gtk


    由于系統(tǒng)所有進(jìn)程之間都有“親緣”關(guān)系,所以可以通過(guò)pstree查看這種關(guān)系,
Quote:

$ pstree #打印系統(tǒng)進(jìn)程調(diào)用樹(shù),可以非常清楚地看到當(dāng)前系統(tǒng)中所有活動(dòng)進(jìn)程之間的調(diào)用關(guān)系


    動(dòng)態(tài)查看進(jìn)程信息,  
Quote:

$ top


    該命令最大的特點(diǎn)是可以動(dòng)態(tài)的查看進(jìn)程的信息,當(dāng)然,它還提供了一些有用的參數(shù),比如-S可以按照累計(jì)執(zhí)行時(shí)間的大小排序查看,也可以通過(guò)-u查看指定用戶啟動(dòng)的進(jìn)程等。

    感覺(jué)有上面幾個(gè)命令來(lái)查看進(jìn)程的信息就差不多了,下面來(lái)討論一個(gè)有趣的問(wèn)題:如何讓一個(gè)程序在同一時(shí)間只有一個(gè)在運(yùn)行。
    這意味著當(dāng)一個(gè)程序正在被執(zhí)行時(shí),它將不能再被啟動(dòng)。那該怎么做呢?
    假如一份相同的程序被復(fù)制成了很多份,并且具有不同的文件名被放在不同的位置,這個(gè)將比較糟糕,所以我們考慮最簡(jiǎn)單的情況,那就是這份程序在整個(gè)系統(tǒng)上是唯一的,而且名字也是唯一的。這樣的話,我們有哪些辦法來(lái)回答上面的問(wèn)題呢?
    總的機(jī)理是:在這個(gè)程序的開(kāi)頭檢查自己有沒(méi)有執(zhí)行,如果執(zhí)行了則停止否則繼續(xù)執(zhí)行后續(xù)代碼。
    策略則是多樣的,由于前面的假設(shè)已經(jīng)保證程序文件名和代碼的唯一性,所以
  • 通過(guò)ps命令打印找出當(dāng)前的所有進(jìn)程對(duì)應(yīng)的程序名,逐個(gè)與自己的程序名比較,如果已經(jīng)有,那么說(shuō)明自己已經(jīng)運(yùn)行了。


    Code:

    [Ctrl+A Select All]


  • 每次運(yùn)行時(shí)先在指定位置檢查是否存在一個(gè)保存自己進(jìn)程ID的文件,如果不存在,那么繼續(xù)執(zhí)行,如果存在,那么查看該進(jìn)程ID是否正在運(yùn)行,如果在,那么退出,否則往該文件重新寫(xiě)的新的進(jìn)程ID,并繼續(xù)。



    Code:

    [Ctrl+A Select All]


        更多實(shí)現(xiàn)策略自己盡情的發(fā)揮吧!

    4、調(diào)整進(jìn)程的優(yōu)先級(jí)

        在保證每個(gè)進(jìn)程都能夠順利執(zhí)行外,為了讓某些任務(wù)優(yōu)先完成,那么系統(tǒng)在進(jìn)行進(jìn)程調(diào)度時(shí)就會(huì)采用一定的調(diào)度辦法,比如常見(jiàn)的有按照優(yōu)先級(jí)的時(shí)間片輪轉(zhuǎn)的調(diào)度算法。這種情況下,我們可以通過(guò)renice調(diào)整正在運(yùn)行的程序的優(yōu)先級(jí),例如,

    Quote:

    $ ps -e -o "%p %c %n" | grep xfs #打印的信息分別是進(jìn)程ID,進(jìn)程對(duì)應(yīng)的程序名,優(yōu)先級(jí)
     5089 xfs               0
    $ renice 1 -p 5089
    renice: 5089: setpriority: Operation not permitted
    $ sudo renice 1 -p 5089   #需要權(quán)限才行
    [sudo] password for falcon:
    5089: old priority 0, new priority 1
    $ ps -e -o "%p %c %n" | grep xfs  #再看看,優(yōu)先級(jí)已經(jīng)被調(diào)整過(guò)來(lái)了
     5089 xfs               1



    5、結(jié)束進(jìn)程

        既然可以通過(guò)命令行執(zhí)行程序,創(chuàng)建進(jìn)程,那么也有辦法結(jié)束它。我們可以通過(guò)kill命令給用戶自己?jiǎn)?dòng)的進(jìn)程發(fā)送一定信號(hào)讓進(jìn)程終止,當(dāng)然“萬(wàn)能”的root幾乎可以kill所有進(jìn)程(除了init之外)。例如,

    Quote:

    $ sleep 50 &   #啟動(dòng)一個(gè)進(jìn)程
    [1] 11347
    $ kill 11347


        kill命令默認(rèn)會(huì)發(fā)送終止信號(hào)(SIGTERM)給程序,讓程序退出,但是kill還可以發(fā)送其他的信號(hào),這些信號(hào)的定義我們可以通過(guò)man 7 signal查看到,也可以通過(guò)kill -l列出來(lái)。
    Quote:

    $ man 7 signal
    $ kill -l
     1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL
     5) SIGTRAP      6) SIGABRT      7) SIGBUS       8) SIGFPE
     9) SIGKILL     10) SIGUSR1     11) SIGSEGV     12) SIGUSR2
    13) SIGPIPE     14) SIGALRM     15) SIGTERM     16) SIGSTKFLT
    17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
    21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU
    25) SIGXFSZ     26) SIGVTALRM   27) SIGPROF     28) SIGWINCH
    29) SIGIO       30) SIGPWR      31) SIGSYS      34) SIGRTMIN
    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3  38) SIGRTMIN+4
    39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
    43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12
    47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14
    51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10
    55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7  58) SIGRTMAX-6
    59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
    63) SIGRTMAX-1  64) SIGRTMAX


        例如,我們用kill命令發(fā)送SIGSTOP信號(hào)給某個(gè)程序,讓它暫停,然后發(fā)送SIGCONT信號(hào)讓它繼續(xù)運(yùn)行。

    Quote:

    $ sleep 50 &
    [1] 11441
    $ jobs
    [1]+  Running                 sleep 50 &
    $ kill -s SIGSTOP 11441   #這個(gè)等同于我們對(duì)一個(gè)前臺(tái)進(jìn)程執(zhí)行CTRL+Z操作
    $ jobs
    [1]+  Stopped                 sleep 50
    $ kill -s SIGCONT 11441   #這個(gè)等同于之前我們使用bg %1操作讓一個(gè)后臺(tái)進(jìn)程運(yùn)行起來(lái)
    $ jobs
    [1]+  Running                 sleep 50 &
    $ kill %1                  #在當(dāng)前會(huì)話(session)下,也可以通過(guò)作業(yè)號(hào)控制進(jìn)程
    $ jobs
    [1]+  Terminated              sleep 50


        可見(jiàn)kill命令為我們提供了非常好的功能,不過(guò)kill命令只能根據(jù)進(jìn)程的ID或者作業(yè)來(lái)控制進(jìn)程,所以pkill和killall給我們提供了更多選擇,它們擴(kuò)展了通過(guò)程序名甚至是進(jìn)程的用戶名來(lái)控制進(jìn)程的方法。更多用法請(qǐng)參考它們的手冊(cè)。

        當(dāng)一個(gè)程序退出以后,如何判斷這個(gè)程序是正常退出還是異常退出呢?還記得Linux下,那個(gè)經(jīng)典"hello,world"程序嗎?在代碼的最后總是有條 “return 0”語(yǔ)句。這個(gè)“return 0”實(shí)際上是為了讓程序員來(lái)檢查進(jìn)程是否正常退出的。如果進(jìn)程返回了一個(gè)其他的數(shù)值,那么我們可以肯定的說(shuō)這個(gè)進(jìn)程異常退出了,因?yàn)樗紱](méi)有執(zhí)行到 “return 0”這條語(yǔ)句就退出了。
        那怎么檢查進(jìn)程退出的狀態(tài),即那個(gè)返回的數(shù)值呢?
        在shell程序中,我們可以檢查這個(gè)特殊的變量$?,它存放了上一條命令執(zhí)行后的退出狀態(tài)。

    Quote:

    $ test1
    bash: test1: command not found
    $ echo $?
    127
    $ cat ./test.c | grep hello
    $ echo $?
    1
    $ cat ./test.c | grep hi
            printf("hi, myself!\n");
    $ echo $?
    0


        貌似返回0成為了一個(gè)潛規(guī)則,雖然沒(méi)有標(biāo)準(zhǔn)明確規(guī)定,不過(guò)當(dāng)程序正常返回時(shí),我們總是可以從$?中檢測(cè)到0,但是異常時(shí),我們總是檢測(cè)到一個(gè)非0的值。這 就告訴我們?cè)诔绦虻淖詈笪覀冏詈檬歉弦粋€(gè)exit 0以便任何人都可以通過(guò)檢測(cè)$?確定你的程序是否正常結(jié)束。如果有一天,有人偶爾用到你的程序,試圖檢查你的程序的退出狀態(tài),而你卻在程序的末尾莫名的返 回了一個(gè)-1或者1,那么他將會(huì)很苦惱,會(huì)懷疑自己的程序哪個(gè)地方出了問(wèn)題,檢查半天卻不知所措,因?yàn)樗湃文懔耍谷粡念^至尾都沒(méi)有懷疑你的編程習(xí)慣 可能會(huì)與眾不同。

    6、進(jìn)程通信

        為了便于設(shè)計(jì)和實(shí)現(xiàn),通常一個(gè)大型的任務(wù)都被劃分成較小的模塊。不同模塊之間啟動(dòng)后成為進(jìn)程,它們之間如何通信以便交互數(shù)據(jù),協(xié)同工作呢?在《UNIX環(huán) 境高級(jí)編程》一書(shū)中提到很多方法,諸如管道(無(wú)名管道和有名管道)、信號(hào)(signal)、報(bào)文(Message)隊(duì)列(消息隊(duì)列)、共享內(nèi)存 (mmap/munmap)、信號(hào)量(semaphore,主要是同步用,進(jìn)程之間,進(jìn)程的不同線程之間)、套接口(Socket,支持不同機(jī)器之間的進(jìn) 程通信)等,而在shell編程里頭,我們通常直接用到的就有管道和信號(hào)等。下面主要介紹管道和信號(hào)機(jī)制在shell編程時(shí)候的一些用法。
       
       
  • 無(wú)名管道(pipe):

        在Linux下,你可以通過(guò)"|"連接兩個(gè)程序,這樣就可以用它來(lái)連接后一個(gè)程序的輸入和前一個(gè)程序的輸出,因此被形象地叫做個(gè)管道。在C語(yǔ)言里頭,創(chuàng)建 無(wú)名管道非常簡(jiǎn)單方便,用pipe函數(shù),傳入一個(gè)具有兩個(gè)元素的int型的數(shù)組就可以。這個(gè)數(shù)組實(shí)際上保存的是兩個(gè)文件描述符,父進(jìn)程往第一個(gè)文件描述符 里頭寫(xiě)入東西后,子進(jìn)程可以從第一個(gè)文件描述符中讀出來(lái)。

        如果用多了命令行,這個(gè)管子"|"應(yīng)該會(huì)經(jīng)常用。比如我們?cè)谏厦娴难菔局邪裵s命令的輸出作為grep命令的輸入,從而可以過(guò)濾掉一些我們感興趣的信息:

    Quote:

    $ ps -ef | grep init



        也許你會(huì)覺(jué)得這個(gè)“管子”好有魔法,竟然真地能夠鏈接兩個(gè)程序的輸入和輸出,它們到底是怎么實(shí)現(xiàn)的呢?實(shí)際上當(dāng)我們輸入這樣一組命令的時(shí)候,當(dāng)前解釋程序 會(huì)進(jìn)行適當(dāng)?shù)慕馕觯亚懊嬉粋€(gè)進(jìn)程的輸出關(guān)聯(lián)到管道的輸出文件描述符,把后面一個(gè)進(jìn)程的輸入關(guān)聯(lián)到管道的輸入文件描述符,這個(gè)關(guān)聯(lián)過(guò)程通過(guò)輸入輸出重定向 函數(shù)dup(或者fcntl)來(lái)實(shí)現(xiàn)。

       
  • 有名管道(named pipe):

        有名管道實(shí)際上是一個(gè)文件(無(wú)名管道也像一個(gè)文件,雖然關(guān)系到兩個(gè)文件描述符,不過(guò)只能一邊讀另外一邊寫(xiě)),不過(guò)這個(gè)文件比較特別,操作時(shí)要滿足先進(jìn)先 出,而且,如果試圖讀一個(gè)沒(méi)有內(nèi)容的有名管道,那么就會(huì)被阻塞,同樣地,如果試圖往一個(gè)有名管道里頭寫(xiě)東西,而當(dāng)前沒(méi)有程序試圖讀它,也會(huì)被阻塞。下面看 看效果。

    Quote:

    $ mkfifo fifo_test    #通過(guò)mkfifo命令可以創(chuàng)建一個(gè)有名管道
    $ echo "fewfefe" > fifo_test    #試圖往fifo_test文件中寫(xiě)入內(nèi)容,但是被阻塞,要另開(kāi)一個(gè)終端繼續(xù)下面的操作
    $ cat fifo_test        #另開(kāi)一個(gè)終端,記得,另開(kāi)一個(gè)。試圖讀出fifo_test的內(nèi)容
    fewfefe



        在這里echo和cat是兩個(gè)不同的程序,在這種情況下,通過(guò)echo和cat啟動(dòng)的兩個(gè)進(jìn)程之間并沒(méi)有父子關(guān)系。不過(guò)它們依然可以通過(guò)有名管道通信。這 樣一種通信方式非常適合某些情況:例如有這樣一個(gè)架構(gòu),這個(gè)架構(gòu)由兩個(gè)應(yīng)用程序構(gòu)成,其中一個(gè)通過(guò)一個(gè)循環(huán)不斷讀取fifo_test中的內(nèi)容,以便判 斷,它下一步要做什么。如果這個(gè)管道沒(méi)有內(nèi)容,那么它就會(huì)被阻塞在那里,而不會(huì)死循環(huán)而耗費(fèi)資源,另外一個(gè)則作為一個(gè)控制程序不斷地往fifo_test 中寫(xiě)入一些控制信息,以便告訴之前的那個(gè)程序該做什么。下面寫(xiě)一個(gè)非常簡(jiǎn)單的例子。我們可以設(shè)計(jì)一些控制碼,然控制程序不斷的往fifo_test里頭寫(xiě) 入,然后應(yīng)用程序根據(jù)這些控制碼完成不同的動(dòng)作。當(dāng)然,也可以往fifo_test傳入除控制碼外的不同的數(shù)據(jù)。

    Quote:

    $ cat app.sh    #應(yīng)用程序的代碼
    #!/bin/bash

    FIFO=fifo_test
    while :;
    do
                    CI=`cat $FIFO`  #CI --> Control Info
                    case $CI in
                                    0) echo "The CONTROL number is ZERO, do something ..."
                                            ;;
                                    1) echo "The CONTROL number is ONE, do something ..."
                                            ;;
                                    *) echo "The CONTROL number not recognized, do something else..."
                                            ;;
                    esac
    done
    $ cat control.sh    #控制程序的代碼
    #!/bin/bash

    FIFO=fifo_test
    CI=$1

    [ -z "$CI" ] && echo "the control info should not be empty" && exit

    echo $CI > $FIFO
    $ chmod +x app.sh control.sh    #修改這兩個(gè)程序的可執(zhí)行權(quán)限,以便用戶可以執(zhí)行它們
    $ ./app.sh            #在一個(gè)終端啟動(dòng)這個(gè)應(yīng)用程序,在通過(guò)./control.sh發(fā)送控制碼以后查看輸出
    The CONTROL number is ONE, do something ...    #發(fā)送1以后
    The CONTROL number is ZERO, do something ...    #發(fā)送0以后
    The CONTROL number not recognized, do something else...    #發(fā)送一個(gè)未知的控制碼以后
    $ ./control.sh 1            #在另外一個(gè)終端,發(fā)送控制信息,控制應(yīng)用程序的工作
    $ ./control.sh 0            
    $ ./control.sh 4343



        這樣一種應(yīng)用架構(gòu)非常適合本地的多程序任務(wù)的設(shè)計(jì),如果結(jié)合web cgi,那么也將適合遠(yuǎn)程控制的要求。引入web cgi的唯一改變是,要把控制程序./control.sh放到web的cgi目錄下,并對(duì)它作一些修改,以使它符合CGI的規(guī)范,這些規(guī)范包括文檔輸出 格式的表示(在文件開(kāi)頭需要輸出content-tpye: text/html以及一個(gè)空白行)和輸入?yún)?shù)的獲取(web輸入?yún)?shù)都存放在QUERY_STRING環(huán)境變量里頭)。因此一個(gè)非常簡(jiǎn)單的CGI形式控 制程序?qū)㈩?lèi)似下面。



    Code:

    [Ctrl+A Select All]



        在實(shí)際使用的時(shí)候,請(qǐng)確保control.sh能夠訪問(wèn)到fifo_test管道,并且有寫(xiě)權(quán)限。這樣我們?cè)跒g覽器上就可以這樣控制app.sh了。

    http://ipaddress_or_dns/cgi-bin/control.sh?0

        問(wèn)號(hào)(?)后面的內(nèi)容即QUERY_STRING,類(lèi)似之前的$1。

        這樣一種應(yīng)用對(duì)于遠(yuǎn)程控制,特別是嵌入式系統(tǒng)的遠(yuǎn)程控制很有實(shí)際意義。在去年的暑期課程上,我們就通過(guò)這樣一種方式來(lái)實(shí)現(xiàn)馬達(dá)的遠(yuǎn)程控制。首先,我們實(shí)現(xiàn) 了一個(gè)簡(jiǎn)單的應(yīng)用程序以便控制馬達(dá)的轉(zhuǎn)動(dòng),包括轉(zhuǎn)速,方向等的控制。為了實(shí)現(xiàn)遠(yuǎn)程控制,我們?cè)O(shè)計(jì)了一些控制碼,以便控制馬達(dá)轉(zhuǎn)動(dòng)相關(guān)的不同屬性。

        在C語(yǔ)言中,如果要用有名管道,和shell下的類(lèi)似,只不過(guò)在讀寫(xiě)數(shù)據(jù)的時(shí)候用read,write調(diào)用,在創(chuàng)建fifo的時(shí)候用mkfifo函數(shù)調(diào)用。

       
  • 信號(hào)(Signal):

        信號(hào)是軟件中斷,在Linux下面用戶可以通過(guò)kill命令給某個(gè)進(jìn)程發(fā)送一個(gè)特定的信號(hào),也可以通過(guò)鍵盤(pán)發(fā)送一些信號(hào),比如CTRL+C可能觸發(fā) CGIINT信號(hào),而CTRL+\可能觸發(fā)SGIQUIT信號(hào)等,除此之外,內(nèi)核在某些情況下也會(huì)給進(jìn)程發(fā)送信號(hào),比如在訪問(wèn)內(nèi)存越界時(shí)產(chǎn)生 SGISEGV信號(hào),當(dāng)然,進(jìn)程本身也可以通過(guò)kill,raise等函數(shù)給自己發(fā)送信號(hào)。對(duì)于Linux下支持的信號(hào)類(lèi)型,大家可以通過(guò)"man 7 signal"或者"kill -l"查看到相關(guān)列表和說(shuō)明。

        對(duì)于有些信號(hào),進(jìn)程會(huì)有默認(rèn)的響應(yīng)動(dòng)作,而有些信號(hào),進(jìn)程可能直接會(huì)忽略,當(dāng)然,用戶還可以對(duì)某些信號(hào)設(shè)定專門(mén)的處理函數(shù)。在shell程序中,我們可以 通過(guò)trap命令(shell的內(nèi)置命令)來(lái)設(shè)定響應(yīng)某個(gè)信號(hào)的動(dòng)作(某個(gè)命令或者是你定義的某個(gè)函數(shù)),而在C語(yǔ)言里頭可以通過(guò)signal調(diào)用注冊(cè)某 個(gè)信號(hào)的處理函數(shù)。這里僅僅演示trap命令的用法。

    Quote:

    $ function signal_handler {    #定一個(gè)signal_handler的函數(shù),>是按下?lián)Q行符號(hào)自動(dòng)出現(xiàn)的
    > echo "hello, world"
    > }
    $ trap signal_handle SIGINT    #執(zhí)行該命令設(shè)定:當(dāng)發(fā)生SIGINT信號(hào)時(shí)將打印hello。
    $ hello, world            #按下CTRL+C,可以看到屏幕上輸出了hello, world字符串



        類(lèi)似地,如果設(shè)定信號(hào)0的響應(yīng)動(dòng)作,那么就可以用trap來(lái)模擬C語(yǔ)言程序中的atexit程序終止函數(shù)的登記,即通過(guò)trap signal_handler SIGQUIT設(shè)定的signal_handler函數(shù)將在程序退出的時(shí)候被執(zhí)行。信號(hào)0是一個(gè)特別的信號(hào),在POSIX.1中把信號(hào)編號(hào)0定義為空信 號(hào),這將常被用來(lái)確定一個(gè)特定進(jìn)程是否仍舊存在。當(dāng)一個(gè)程序退出時(shí)會(huì)觸發(fā)該信號(hào)。

    Quote:

    $ cat sigexit.sh
    #!/bin/bash

    function signal_handler {
            echo "hello, world"
    }
    trap signal_handler 0
    $ chmod +x sigexit.sh
    $ ./sigexit.sh    #實(shí)際上在shell編程時(shí),會(huì)用這種方式在程序退出時(shí)來(lái)做一些清理臨時(shí)文件的收尾工作
    hello, world

      

    7、作業(yè)和作業(yè)控制

        當(dāng)我們?yōu)橥瓿梢恍?fù)雜的任務(wù)而將多個(gè)命令通過(guò)|,>,<, ;, (, )等組合在一起的時(shí)候,通常這樣個(gè)命令序列會(huì)啟動(dòng)多個(gè)進(jìn)程,它們之間通過(guò)管道等進(jìn)行通信。而有些時(shí)候,我們?cè)趫?zhí)行一個(gè)任務(wù)的同時(shí),還有其他的任務(wù)需要處 理,那么就經(jīng)常會(huì)在命令序列的最后加上一個(gè)&,或者在執(zhí)行命令以后,按下CTRL+Z讓前一個(gè)命令暫停。以便做其他的任務(wù)。等做完其他一些任務(wù)以 后,再通過(guò)fg命令把后臺(tái)的任務(wù)切換到前臺(tái)。這樣一種控制過(guò)程通常被成為作業(yè)控制,而那些命令序列則被成為作業(yè),這個(gè)作業(yè)可能涉及一個(gè)或者多個(gè)程序,一個(gè) 或者多個(gè)進(jìn)程。下面演示一下幾個(gè)常用的作業(yè)控制操作。

    Quote:

    $ sleep 50 &      #讓程序在后臺(tái)運(yùn)行,將打印[作業(yè)號(hào)]和進(jìn)程號(hào)
    [1] 11137
    $ fg %1            #使用shell內(nèi)置命令fg把作業(yè)1調(diào)到前臺(tái)運(yùn)行,然后按下CTRL+Z讓該進(jìn)程暫停
    sleep 50

    [1]+  Stopped                 sleep 50
    $ jobs            #查看當(dāng)前作業(yè)情況,有一個(gè)作業(yè)停止
    [1]+  Stopped                 sleep 50
    $ sleep 100 &       #讓另外一個(gè)作業(yè)在后臺(tái)運(yùn)行
    [2] 11138        
    $ jobs            #查看當(dāng)前作業(yè)情況,一個(gè)正在運(yùn)行,一個(gè)停止
    [1]+  Stopped                 sleep 50
    [2]-  Running                 sleep 100 &
    $ bg %1            #啟動(dòng)停止的進(jìn)程并讓它在后臺(tái)運(yùn)行
    [2]+ sleep 50 &



        不過(guò),要在命令行下使用作業(yè)控制,需要當(dāng)前shell,內(nèi)核終端驅(qū)動(dòng)等對(duì)作業(yè)控制支持才行。

    參考資料

    <UNIX環(huán)境高級(jí)編程>相關(guān)章節(jié)

  • posted on 2008-03-14 15:34 隨意門(mén) 閱讀(1021) 評(píng)論(0)  編輯 收藏 引用


    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
    網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


    青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
      <noscript id="pjuwb"></noscript>
            <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
              <dd id="pjuwb"></dd>
              <abbr id="pjuwb"></abbr>
              欧美性猛片xxxx免费看久爱| 亚洲国产欧美日韩| 国产精品一区视频网站| 欧美日韩中文在线| 欧美日韩直播| 国产精品三级视频| 国内精品嫩模av私拍在线观看 | 另类天堂av| 免费观看日韩av| 欧美大片免费看| 国产精品久久久久久户外露出| 国产精品欧美日韩一区| 国产一区二区0| 亚洲品质自拍| 一区二区三区日韩在线观看| 午夜精品视频在线观看| 看欧美日韩国产| 亚洲国产综合在线| 亚洲欧美在线网| 免费日韩av电影| 国产精品亚洲人在线观看| 1024精品一区二区三区| 亚洲性感美女99在线| 久久天天躁夜夜躁狠狠躁2022| 亚洲日本成人| 久久久一区二区| 国产精品亚洲视频| 国产精品99久久久久久白浆小说| 久久深夜福利免费观看| 日韩午夜精品视频| 久久久伊人欧美| 国产精品激情av在线播放| 亚洲国产日韩精品| 久久久久久电影| 亚洲一区二区三| 欧美激情综合在线| 在线观看中文字幕不卡| 欧美一级片一区| 99精品免费视频| 欧美高清在线播放| 亚洲国产91| 美女露胸一区二区三区| 欧美岛国激情| 国产精品无人区| 亚洲精品综合精品自拍| 久久久久久久999精品视频| 99热免费精品在线观看| 欧美激情久久久久久| 精品成人一区二区三区| 欧美在线观看一区二区| 亚洲视频在线观看一区| 欧美日韩播放| 99精品福利视频| 亚洲激情第一区| 欧美激情一区二区三级高清视频| 亚洲国产综合在线看不卡| 裸体素人女欧美日韩| 欧美在线观看一区| 国产综合av| 欧美sm极限捆绑bd| 女女同性女同一区二区三区91| 亚洲第一网站| 亚洲国产日韩欧美一区二区三区| 免费日韩一区二区| 一区二区冒白浆视频| 亚洲另类自拍| 欧美午夜视频一区二区| 亚洲免费视频成人| 亚洲欧美日韩中文视频| 国产亚洲一区在线| 欧美成年人网站| 欧美精品播放| 亚洲自拍偷拍网址| 久久gogo国模裸体人体| 亚洲国产成人午夜在线一区| 亚洲二区在线观看| 欧美日韩亚洲一区二区| 午夜精品亚洲| 亚洲欧美另类在线观看| 国产精品福利影院| 亚洲天堂男人| 亚洲午夜精品久久久久久app| 欧美日韩午夜在线| 一区二区高清视频| 亚洲美女色禁图| 国产精品劲爆视频| 久久综合综合久久综合| 欧美久久久久久久| 久久精品国产久精国产一老狼| 亚洲国产另类 国产精品国产免费| 欧美电影免费观看| 欧美日韩精品在线播放| 欧美永久精品| 欧美黄色一区| 久久久99免费视频| 欧美日韩国产精品| 久久人人爽国产| 国产精品99一区二区| 久久综合色88| 国产精品国产一区二区| 欧美高清免费| 国产欧美视频在线观看| 最新中文字幕一区二区三区| 国产精品乱人伦中文| 欧美精品一区二区久久婷婷| 一本色道久久综合狠狠躁篇怎么玩| 一区二区三区欧美在线观看| 国产永久精品大片wwwapp| 亚洲欧洲日韩综合二区| 国产日韩欧美在线播放| 亚洲黄色在线| 一区在线观看视频| 亚洲女人天堂成人av在线| 亚洲三级性片| 久久久av毛片精品| 欧美亚洲日本网站| 欧美日韩国产色综合一二三四| 麻豆国产精品777777在线| 国产精品欧美日韩| 亚洲视屏在线播放| 一区二区日韩伦理片| 美女图片一区二区| 久久一区二区三区国产精品| 国产精品黄页免费高清在线观看| 亚洲激情亚洲| 亚洲精品网址在线观看| 久久亚洲春色中文字幕| 久久久国产视频91| 国产日韩欧美中文在线播放| 亚洲无玛一区| 先锋影音网一区二区| 国产精品久久久久aaaa| 日韩一级片网址| 亚洲视频一区在线观看| 欧美日韩国产美女| 亚洲精品视频免费观看| 日韩视频第一页| 欧美精品v日韩精品v国产精品| 亚洲国产精品久久久| 亚洲国产专区校园欧美| 欧美77777| 亚洲精品国产系列| 一区二区三区精品视频在线观看| 欧美日产一区二区三区在线观看 | 欧美在线亚洲| 国产日韩欧美精品综合| 亚洲在线观看视频网站| 欧美亚洲自偷自偷| 国产亚洲精品高潮| 久久精品亚洲一区二区三区浴池 | 制服诱惑一区二区| 国产精品v片在线观看不卡| 亚洲最快最全在线视频| 亚洲欧美日韩国产另类专区| 国产精品丝袜久久久久久app| 欧美一区网站| 亚洲国产精品一区二区www| 一区二区三区视频免费在线观看| 欧美午夜片在线观看| 欧美在线视频一区| 欧美电影在线观看| 亚洲小说欧美另类社区| 国产伪娘ts一区| 欧美大片国产精品| 亚洲一区二区在线视频 | 9人人澡人人爽人人精品| 一区在线免费观看| 亚洲精品中文字幕女同| 久久这里只精品最新地址| 欧美激情亚洲国产| 亚洲性感美女99在线| 狠狠综合久久av一区二区小说| 久久综合国产精品台湾中文娱乐网| 亚洲国产美国国产综合一区二区| 亚洲中午字幕| 91久久精品国产| 国产精品一二三四区| 蘑菇福利视频一区播放| 一区二区三区四区国产| 男人的天堂亚洲在线| 亚洲欧美精品在线观看| 亚洲福利视频一区| 国产精品视频自拍| 欧美精品成人| 免费欧美在线视频| 久久成人久久爱| 中国女人久久久| 欧美mv日韩mv国产网站app| 小黄鸭精品aⅴ导航网站入口| 亚洲国产精品va在线观看黑人| 国产精品乱看| 欧美日韩国产一区| 久久性天堂网| 久久久久久久999| 亚洲欧美日韩一区二区三区在线| 亚洲精品系列| 亚洲电影免费观看高清| 久久婷婷一区| 欧美在线影院在线视频| 亚洲图片欧美午夜|