【Linux】程式控制!!!

doctor_xiong發表於2018-01-18

在linux裡面常用的排程演算法是時間片輪轉法,即每一個程式分為很多的塊,每一塊都只能佔用CPU固定的時間,當時間到,這個程式就必須放棄對CPU的使用許可權。然後CPU去執行下一個程式。
在使用fork()函式建立一個子程式的時候,父程式和子程式執行的先後順序是不確定的,所以子程式和父程式執行行為先後次序是不確定的。但是在除開使用fork()函式的同時也可以使用vfork()來建立程式,vfork()在建立程式的時候,必須是在子程式執行完之後再去執行父程式。在fork()建立程式的時候採用的是寫實拷貝技術,但是使用vfork()函式的時候即使寫時也不拷貝,即在改變子程式的同時也改變了父程式的資料。也因此,在使用vfork()建立程式的時候會出現一些意想不到的事情。

程式等待:
必要性:在使用多程式的時候,父程式需要知道子程式的退出資訊,同時也需要回收子程式的資源,以及子程式的死亡資訊。

程式等待的方法:
pid_t wait(int * status);
如果wait函式正常返回,則返回死亡子程式的ID,其中status裡面儲存的是子程式退出的基本資訊。如果wait函式呼叫失敗則返回-1。

例如:


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

int main()
{
    pid_t pid;
    printf("begin fork()!\n");
    pid = fork();
    if(pid == -1)
        perror("fork():");
    if(pid == 0)
    {
        printf("I'm child!\n");
        sleep(5);
    }
    else
    {
        int status;
        wait(&status);
        printf("wait end!\n");
    }
    return 0;
}

這裡寫圖片描述

在輸出I'm child!之後睡眠5秒之後再輸出wait end!

在這個程式裡面,當使用fork()函式之後,父程式和子程式同時存在,但是在父程式裡面使用了wait函式,這時候在子程式沒有退出之前,父程式一直在wait函式地方等待,直到子程式在執行完之後再退出,這時候wait函式返回,父程式開始執行下面的程式碼。

pid_t waitpid(pid_t pid,int* status,int pation);

pid
- pid = -1 表示任意一個子程式退出,則返回
- pid >0 表示等待和pid相同的ID程式退出則返回。
status

  • WIFEXITED : 判斷自己成是否是正常退出
  • WEXITSTATUS:如果返回statu>0,則提取子程式的退出碼

pation
- WNOHANG:如果指定子程式沒有返回,則返回0,如果正常返回則返回指定子程式的ID。在程式執行的過程中不等待。
例如:


int main()
{
    pid_t r;
    pid_t pid;
    int status;
    pid = fork();
    if(pid == -1)
        perror("fork():");
    else if(pid == 0)
    {
            printf("hehe\n");
    }
    else
    {
        r = wait(&status);
        printf("%d\n",WEXITSTATUS(status));
    }
}

waitpid函式是在指定子程式退出之後waitpid函式在返回,使用waitpid函式就可以實現指定程式死亡之後,在執行父程式。

在子程式沒有執行結束,呼叫wait/waitpid函式會處於阻塞狀態。若子程式正常返回,則wait/waitpid函式正常返回,若不存在子程式或者指定子程式,則wait/waitpid函式立即報錯。

若果子程式存在並且子程式退出,則wait函式正常返回,回收子程式的資源,獲得子程式的退出資訊。
若子程式處於執行狀態,則wait函式處於阻塞狀態,等待子程式退出。
若子程式不存在,wait函式立即報錯。

利用程式等待實現myshell:


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

void  do_action (char* argv[])
{
    if(fork() == 0)
        execvp(argv[0],argv);
    else
        wait(NULL);
}


void do_pose(char *buf)          //將輸入的字串拆分
{
    int i=0;
    int status = 0;
    char * argv[8];
    int argc = 0;
    for(;buf[i] != '\0';i++)
    {
        if(status == 0 && !isspace(buf[i]))
        {
            argv[argc++] = buf + i;
            status = 1;
        }
        else if(isspace(buf[i]))
        {
            buf[i] = 0;
            status = 0;
        }
    }
    argv[argc] = NULL;
    do_action(argv);
}


int main()
{
    char buf[1024];
    while(1)
    {
        printf(">:");
        scanf("%[^\n]%*c",buf);
        if(strcmp(buf,"exit")==0)
            exit(0);
        do_pose(buf);
    }
}

相關文章