天天看點

2-12 多程序程式設計

(本節筆記接上一節的程序控制,繼續學習多程序的程式設計函數,詳細的實驗代碼在這裡)

1.  建立程序

        函數名:

                fork

        函數原型:

                pid_t fork ( void );

        函數功能:

                建立一個子程序

        所屬頭檔案:

               <unistd.h>

        傳回值:

                成功:在父程序中傳回子程序的pid,在子程序中傳回0    失敗:傳回1

        參數說明:

                void

        範例代碼:(touch myfork.c)

#include <unistd.h>

#include <stdio.h>

int main(int argc, char ** argv)

{

    fork();

    printf("Program is end!\n");

    exit(0);

}

        輸出結果:Program is end!

                            Program is end!

        分析:當父程序調用fork建立一個代碼與父程序一樣的子程序是,子程序由printf開始執行!(重要)

        pid的傳回值代碼:

#include <unistd.h>

#include <stdio.h>

int main(int argc, char ** argv)

{

    pid_t pid = fork();

    printf("pid is %d!\n");

    exit(0);

}

        輸出結果:pid is 19112!

                            pid is 0

        讓父程序執行分支的方法:

#include <unistd.h>

#include <stdio.h>

int main(int argc, char ** argv)

{

    pid_t pid = fork();

    if ( pid > 0)      

    {

        printf("here is parent process!\n");

    }

    else        

    {

        printf("here is child process.\n");

    }

    exit(0);

}

2.  建立程序的另一種方式

        函數名:

                vfork

        函數原型:

                pid_t vfork ( void );

        函數功能:

                建立一個子程序,并阻塞父程序

        所屬頭檔案:

                <sys/types.h>    <unistd.h>

        傳回值:

                成功:在父程序傳回子程序的ID,在子程序傳回0

        參數說明:

                void

        範例代碼:(touch myvfork.c)

#include <stdio.h>

#include <sys/types.h>

#include <unistd.h>

int main ( int argc, char ** argv)

{

    pid_t pid = vfork();

    if ( pid > 0)

    {

        printf("father\n");

        exit(0);

    }

    else

    {

        printf("child\n);

        exit(0);

    }

}

        程式輸出的結果:child

                                        father

        分析——fork與fork的差別:vfork會阻塞父程序,子程序優先運作,而fork的父子程序的運作順序是随機的

        範例代碼2:(touch forkcount.c)

#include <stdio.h>

#include <sys/types.h>

#include <unistd.h>

int main ( int argc, char ** argv)

{

    int count = 0;

    pid_t pid = vfork();

    count++;

    printf("%d\n", count);

    exit(0);

}

        程式輸出的結果:1

                                        1

        分析——在調用fork()建立的子程序中的棧是完全複制了父程序的棧,而且與父程序的棧互相獨立。而vfork()建立的子程序與父程序共享同一個棧。

3.  程序的退出

        父程序:可用return 0 , 也可用exit(0);

        子程序:隻能使用exit(0);

4.  程序等待

        函數名:

                wait

        函數原型:

                pid_t wait ( int *status);

        函數功能:

                挂起調用它的程序,直到其子程序結束

        所屬頭檔案:

                <sys/types.h>    <sys/wait.h>

        傳回值:

                成功:傳回中止的那個程序的PID    失敗:傳回-1

        參數說明:

                status:記錄子程序的退出狀态。

        範例代碼:(touch mywait.c)

#include <stdio.h>

#include <sys/types.h>

#include <sys/wait.h>

int main( int argc, char ** argv)

{

    pid_t pid = fork();

    if ( pid > 0)

    {

        wait ( NULL );

        printf( "father\n");

        exit(0);

    }

    else

    {

        printf("child\n");

        exit(0);

    }

}

4.  程式執行

        函數名:(execl、execv、execle、execve、execlp、execvp)

                execl

        函數原型:

                int execl ( const char *path, const char *arg, ...);

        函數功能:

                運作可執行檔案

        所屬頭檔案:

                <unistd.h>

        傳回值:

                成功:無傳回    失敗:傳回-1    (關于execl的傳回值問題,可參考以下這裡)

        參數說明:

                path:要運作的可執行程式的路徑

                arg:作為該可執行程式的參數,直接以NULL為參數結束标志

        範例代碼:

..........

execl("/bin/ls", "ls", "/home", NULL);

..........

(一旦調用了execl(),原程序代碼段将被execl建立的可執行程式鎖替換,例如以下兩行代碼:

execl(......);

printf(......);

printf的操作始終不會被執行)