最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺析如何在c語言中調用Linux腳本

 更新時間:2013年08月13日 09:39:47   作者:  
如何在c語言中調用Linux腳本呢?下面小編就為大家詳細的介紹一下吧!需要的朋友可以過來參考下

一、引言
對于沒有接觸過Unix/Linux操作系統(tǒng)的人來說,fork是最難理解的概念之一:它執(zhí)行一次卻返回兩個值。fork函數(shù)是Unix系統(tǒng)最杰出的成就之一,它是七十年代UNIX早期的開發(fā)者經(jīng)過長期在理論和實踐上的艱苦探索后取得的成果,一方面,它使操作系統(tǒng)在進程管理上付出了最小的代價,另一方面,又為程序員提供了一個簡潔明了的多進程方法。與DOS和早期的Windows不同,Unix/Linux系統(tǒng)是真正實現(xiàn)多任務操作的系統(tǒng),可以說,不使用多進程編程,就不能算是真正的Linux環(huán)境下編程。

多線程程序設計的概念早在六十年代就被提出,但直到八十年代中期,Unix系統(tǒng)中才引入多線程機制,如今,由于自身的許多優(yōu)點,多線程編程已經(jīng)得到了廣泛的應用。

下面,我們將介紹在Linux下編寫多進程和多線程程序的一些初步知識。

二、多進程編程
什么是一個進程?進程這個概念是針對系統(tǒng)而不是針對用戶的,對用戶來說,他面對的概念是程序。當用戶敲入命令執(zhí)行一個程序的時候,對系統(tǒng)而言,它將啟動一個進程。但和程序不同的是,在這個進程中,系統(tǒng)可能需要再啟動一個或多個進程來完成獨立的多個任務。多進程編程的主要內容包括進程控制和進程間通信,在了解這些之前,我們先要簡單知道進程的結構。

2.1 Linux下進程的結構
Linux下一個進程在內存里有三部分的數(shù)據(jù),就是"代碼段"、"堆棧段"和"數(shù)據(jù)段"。其實學過匯編語言的人一定知道,一般的CPU都有上述三種段寄存器,以方便操作系統(tǒng)的運行。這三個部分也是構成一個完整的執(zhí)行序列的必要的部分。

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

2.2 Linux下的進程控制
在傳統(tǒng)的Unix環(huán)境下,有兩個基本的操作用于創(chuàng)建和修改進程:函數(shù)fork( )用來創(chuàng)建一個新的進程,該進程幾乎是當前進程的一個完全拷貝;函數(shù)族exec( )用來啟動另外的進程以取代當前運行的進程。Linux的進程控制和傳統(tǒng)的Unix進程控制基本一致,只在一些細節(jié)的地方有些區(qū)別,例如在Linux系統(tǒng)中調用vfork和fork完全相同,而在有些版本的Unix系統(tǒng)中,vfork調用有不同的功能。由于這些差別幾乎不影響我們大多數(shù)的編程,在這里我們不予考慮。

2.2.1 fork()
fork在英文中是"分叉"的意思。為什么取這個名字呢?因為一個進程在運行中,如果使用了fork,就產(chǎn)生了另一個進程,于是進程就"分叉"了,所以這個名字取得很形象。下面就看看如何具體使用fork,這段程序演示了使用fork的基本框架:

復制代碼 代碼如下:

void main()
{
    int i;
    if ( fork() == 0 )
    {
       /* 子進程程序 */
       for ( i = 1; i <1000; i ++ )
          printf("This is child process\n");
    }
    else
    {
       /* 父進程程序*/
       for ( i = 1; i <1000; i ++ )
       printf("This is process process\n");
    }
}

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

那么調用這個fork函數(shù)時發(fā)生了什么呢?fork函數(shù)啟動一個新的進程,前面我們說過,這個進程幾乎是當前進程的一個拷貝:子進程和父進程使用相同的代碼段;子進程復制父進程的堆棧段和數(shù)據(jù)段。這樣,父進程的所有數(shù)據(jù)都可以留給子進程,但是,子進程一旦開始運行,雖然它繼承了父進程的一切數(shù)據(jù),但實際上數(shù)據(jù)卻已經(jīng)分開,相互之間不再有影響了,也就是說,它們之間不再共享任何數(shù)據(jù)了。它們再要交互信息時,只有通過進程間通信來實現(xiàn),這將是我們下面的內容。既然它們如此相象,系統(tǒng)如何來區(qū)分它們呢?這是由函數(shù)的返回值來決定的。對于父進程, fork函數(shù)返回了子程序的進程號,而對于子程序,fork函數(shù)則返回零。在操作系統(tǒng)中,我們用ps函數(shù)就可以看到不同的進程號,對父進程而言,它的進程號是由比它更低層的系統(tǒng)調用賦予的,而對于子進程而言,它的進程號即是fork函數(shù)對父進程的返回值。在程序設計中,父進程和子進程都要調用函數(shù)fork()下面的代碼,而我們就是利用fork()函數(shù)對父子進程的不同返回值用if...else...語句來實現(xiàn)讓父子進程完成不同的功能,正如我們上面舉的例子一樣。我們看到,上面例子執(zhí)行時兩條信息是交互無規(guī)則的打印出來的,這是父子進程獨立執(zhí)行的結果,雖然我們的代碼似乎和串行的代碼沒有什么區(qū)別。

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

下面演示一個足以"搞死"Linux的小程序,其源代碼非常簡單:

復制代碼 代碼如下:

void main()
{
   for( ; ; )
   {
     fork();
   }
}

這個程序什么也不做,就是死循環(huán)地fork,其結果是程序不斷產(chǎn)生進程,而這些進程又不斷產(chǎn)生新的進程,很快,系統(tǒng)的進程就滿了,系統(tǒng)就被這么多不斷產(chǎn)生 的進程"撐死了"。當然只要系統(tǒng)管理員預先給每個用戶設置可運行的最大進程數(shù),這個惡意的程序就完成不了企圖了。

2.2.2 exec( )函數(shù)族
下面我們來看看一個進程如何來啟動另一個程序的執(zhí)行。在Linux中要使用exec函數(shù)族。系統(tǒng)調用execve()對當前進程進行替換,替換者為一個指定的程序,其參數(shù)包括文件名(filename)、參數(shù)列表(argv)以及環(huán)境變量(envp)。exec函數(shù)族當然不止一個,但它們大致相同,在 Linux中,它們分別是:execl,execlp,execle,execv,execve和execvp,下面我只以execlp為例,其它函數(shù)究竟與execlp有何區(qū)別,請通過manexec命令來了解它們的具體情況。

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

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

復制代碼 代碼如下:

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>

char command[256];
void main()
{
   int rtn; /*子進程的返回數(shù)值*/
   while(1) {
       /* 從終端讀取要執(zhí)行的命令 */
       printf( ">" );
       fgets( command, 256, stdin );
       command[strlen(command)-1] = 0;
       if ( fork() == 0 ) {/* 子進程執(zhí)行此命令 */
          execlp( command, NULL );
          /* 如果exec函數(shù)返回,表明沒有正常執(zhí)行命令,打印錯誤信息*/
          perror( command );
          exit( errno );
       }
       else {/* 父進程, 等待子進程結束,并打印子進程的返回值 */
          wait ( &rtn );
          printf( " child process return %d\n", rtn );
       }
   }
}


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

在這一節(jié)里,我們還要講講system()和popen()函數(shù)。system()函數(shù)先調用fork(),然后再調用exec()來執(zhí)行用戶的登錄 shell,通過它來查找可執(zhí)行文件的命令并分析參數(shù),最后它么使用wait()函數(shù)族之一來等待子進程的結束。函數(shù)popen()和函數(shù) system()相似,不同的是它調用pipe()函數(shù)創(chuàng)建一個管道,通過它來完成程序的標準輸入和標準輸出。這兩個函數(shù)是為那些不太勤快的程序員設計的,在效率和安全方面都有相當?shù)娜毕?,在可能的情況下,應該盡量避免。

相關文章

  • Opencv實現(xiàn)畫筆功能

    Opencv實現(xiàn)畫筆功能

    這篇文章主要為大家詳細介紹了Opencv實現(xiàn)畫筆功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-08-08
  • C++超集C++/CLI模塊的基本用法

    C++超集C++/CLI模塊的基本用法

    這篇文章介紹了C++超集C++/CLI模塊的基本用法,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-07-07
  • C語言遞歸實現(xiàn)歸并排序詳解

    C語言遞歸實現(xiàn)歸并排序詳解

    這篇文章主要為大家詳細介紹了C語言遞歸實現(xiàn)歸并排序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,?希望能夠給你帶來幫助
    2022-03-03
  • 用C語言實現(xiàn)貪吃蛇小游戲

    用C語言實現(xiàn)貪吃蛇小游戲

    這篇文章主要為大家詳細介紹了用C語言實現(xiàn)貪吃蛇小游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • 詳細聊聊c語言中的緩沖區(qū)問題

    詳細聊聊c語言中的緩沖區(qū)問題

    緩沖區(qū)又稱為緩存,它是內存空間的一部分,也就是說在內存空間中預留了一定的存儲空間,這些存儲空間用來緩沖輸入或輸出的數(shù)據(jù),這部分預留的空間就叫做緩沖區(qū),這篇文章主要給大家介紹了關于c語言中緩沖區(qū)問題的相關資料,需要的朋友可以參考下
    2021-11-11
  • C語言深入詳解四大內存函數(shù)的使用

    C語言深入詳解四大內存函數(shù)的使用

    這篇文章主要介紹了C語言的四大內存函數(shù),講解了mencpy、memmove、memcmp、memset函數(shù),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步
    2022-07-07
  • C語言實現(xiàn)strlen的三種方法小結

    C語言實現(xiàn)strlen的三種方法小結

    本文主要介紹了C語言實現(xiàn)strlen的三種方法小結,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-06-06
  • C++ std::any的模擬實現(xiàn)

    C++ std::any的模擬實現(xiàn)

    std::any是C++標準庫中的一個類,std::any對象可以存儲除單例等特殊情況外的任何類型的數(shù)據(jù),本文主要介紹了C++ std::any的模擬實現(xiàn),具有一定的參考價值,感興趣的可以了解一下
    2024-02-02
  • c++primer類詳解

    c++primer類詳解

    今天小編就為大家分享一篇關于C++Primer中變量和基本類型的文章,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2021-09-09
  • OpenCV實現(xiàn)直線檢測并消除

    OpenCV實現(xiàn)直線檢測并消除

    這篇文章主要為大家詳細介紹了OpenCV實現(xiàn)直線檢測并消除,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-06-06

最新評論

鄱阳县| 龙门县| 平山县| 曲阜市| 澄城县| 芜湖县| 河源市| 崇明县| 灵宝市| 怀化市| 信丰县| 汽车| 鹤峰县| 黄山市| 丰原市| 体育| 大关县| 大埔县| 定襄县| 三明市| 长海县| 襄城县| 班戈县| 宜春市| 汝州市| 建德市| 江川县| 新丰县| 博野县| 革吉县| 双鸭山市| 永丰县| 连城县| 万山特区| 怀仁县| 堆龙德庆县| 项城市| 巫山县| 讷河市| 廊坊市| 阳泉市|