進程

1、 什麼是進程

進程是一個執行的過程
進程是一段獨立的程序,在某個數據集合上的一次運行的過程
./a.out(回車)產生了一個進程

2、進程和程序的區別和聯繫

什麼是程序----程序是寫好的代碼,是一個文件,可以保存
進程是不能保存的,程序是可以保存的
進程是動態的,程序是靜態的
程序經過編譯運行產生進程
進程是操作系統分配資源的最小單位  

瞭解
init—-PID == 1
操作系統第一個進程 始祖

進程類型:

交互進程
批處理進程
守護進程

理解進程狀態

運行態 就緒態 等待態

3、理解fork

fork用來創建進程
在程序中使用fork成功後,會有父進程和子進程
可以通過fork的返回值來區分父子進程
我們不確定CPU先調度哪一個
getpid()的返回值是調用它的進程的進程號
getppid()的返回值是調用它的進程B的父進程A的進程號
結論:fork在創建子進程成功時,給父進程返回的值,是創建好的那個子進程的PID
fork給子進程返回的值是0

fork.c

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

//創建進程,父子進程執行相同的打印語句
int main()
{
    pid_t pid = -1;

    pid = fork();//create process
    if (pid < 0)
    {
        perror("fork error");
        return -1;
    }
    if (0 == pid)
    {
        sleep(10);
        printf("child process, %d\r\n", getpid());
        printf("%d\r\n", getppid());
    }   
    else 
    {
        printf("parent process, %d\r\n", pid);
        printf("%d\r\n", getpid());
    }
    printf("after fork\r\n");
    return 0;
}

4、進程的退出

1、程序運行結束  --------main中的return
2、收到信號(中斷)
3、程序中調用進程退出的函數exit,_exit
exit在進程退出時,回收資源             

殭屍進程——自己寫代碼時,需要避免出現殭屍進程,父進程使用wait/waitpid可以避免產生殭屍進程
孤兒進程——父進程先結束,子進程被稱爲是孤兒進程。孤兒進程會由init進程收養  
#include <stdio.h>
#include <stdlib.h>//exit
#include <unistd.h>//_exit

//exit,_exit是進程退出函數
int main()
{
    int i = 3;
    while (i--)
    {
        if (1 == i)
        {
            _exit(0);
        }
    }

    printf("break from while\r\n");

    return 0;
}

5、等待子進程結束

wait
waitpid
子進程在退出時調用了 exit(10)
父進程回收資源,想要獲得子進程退出狀態 wait()

pid_t  wait(int  * status);   // 調用它時,需要傳參
pid_t  waitpid(pid_t  pid,  int  * status,  int  options);    //一般用的比較多的是:waitpid ( pid, &status, WNOHANG);----非阻塞
得到的子進程退出狀態存放在status中,用下面的兩個宏來取出退出原因和狀態

if ( WIFEXITED ( status ) )
{
printf(“%d exit normall,status = %d\r\n”, ret, WEXTSTATUS(status));
}

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

//創建進程,父子進程執行相同的打印語句
int main()
{
    pid_t pid = -1;

    pid = fork();//create process
    if (pid < 0)
    {
        perror("fork error");
        return -1;
    }
    if (0 == pid)
    {
        sleep(10);
        printf("child process, %d\r\n", getpid());
        exit(10);
    }   
    else 
    {
        int status = 0;
        int ret = 0;
        do {
        ret = waitpid(pid, &status, WNOHANG);
        printf("%d\r\n", getpid());

        printf("parent process, %d\r\n", pid);
        sleep(1);       
        }while(0 == ret);

        if (WIFEXITED(status))
        {
            printf("%d exit normall, status  = %d\r\n", ret, WEXITSTATUS(status));
        }
    }
    printf("after fork\r\n");
    return 0;
}

6、exec

exec函數族提供了一種在進程中啓動另一個程序執行的方法。它可以根據指定的文件名或目錄名找到可執行文件,並用它來取代原調用進程的數據段、代碼段、和堆棧段。在執行完之後,原調用進程的內容除了進程號外,其他全部都被替換了。可執行文件既可以是二進制文件,也可以是任何Linux下可執行的腳本文件。

何時使用?

當進程認爲自己不能再爲系統和用戶做任何貢獻了就可以調用exec函數族中的函數,讓自己執行新的程序。
當前目錄: 可執行程序A    B(1,2,3)     
如果某個進程想同時執行另一個程序,它就可以調用fork函數創建子進程,然後在子進程中調用任何一個exec函數。這樣看起來就好像通過執行應用程序而產生了一個新進程一樣。

exec函數族使用注意點

在使用exec函數族時,一定要加上錯誤判斷語句。
因爲exec很容易執行失敗,其中最常見的原因有:

①找不到文件或路徑,此時errno被設置爲ENOENT。

②數組argv和envp忘記用NULL結束,此時errno被設置爲EFAULT。

③沒有對應可執行文件的運行權限,此時errno被設置爲EACCES。  
#include <unistd.h>

int main()
{
    //execlp("ls", "ls", "-l", "/home/farsight", NULL);
    //execl("/bin/cat", "cat","wait2.c", NULL);

    char * argv[] = {"ls", "-l", "/mnt/hgfs", NULL};
    //execv("/bin/ls", argv);
    //execvp("ls", argv);

    char * envp[] = {"PATH=/bin:/usr/bin", "TERM=console", NULL};
    //execle("/bin/ls", "ls", "/mnt/hgfs", NULL, envp);
    //execve("/bin/ls", argv, envp);

    char * cmd[] = {"hello" , NULL};
    execve("./hello", cmd, NULL);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章