操作系統實驗參考以上示例程序中建立併發進程的方法,編寫一個多進程併發執行程序。父進 程首先創建一個執行ls命令的子進程然後再創建一個執行ps命令的子進程,並控制 ps 命令總在 ls 命令之前執行。

實驗一、進程控制實驗
1.1 實驗目的
加深對於進程併發執行概念的理解。實踐併發進程的創建和控制方法。觀察和
體驗進程的動態特性。進一步理解進程生命期期間創建、變換、撤銷狀態變換的過
程。掌握進程控制的方法,瞭解父子進程間的控制和協作關係。練習 Linux 系統中
進程創建與控制有關的系統調用的編程和調試技術。
1.2 實驗說明
1)與進程創建、執行有關的系統調用說明
進程可以通過系統調用 fork()創建子進程並和其子進程併發執行.子進程初始
的執行映像是父進程的一個複本.子進程可以通過 exec()系統調用族裝入一個新
的執行程序。父進程可以使用 wait()或 waitpid()系統調用等待子進程的結束並負
責收集和清理子進程的退出狀態。
fork()系統調用語法:

#include <unistd.h>
pid_t fork(void);

fork 成功創建子進程後將返回子進程的進程號,不成功會返回-1.
exec 系統調用有一組 6 個函數,其中示例實驗中引用了 execve 系統調用語法:

#include <unistd.h>
int execve(const char *path, const char *argv[], const char * envp[]);

path 要裝入的新的執行文件的絕對路徑名字符串. argv[] 要傳遞給新執行程序的完整的命令參數列表(可以爲空). envp[]
要傳遞給新執行程序的完整的環境變量參數列表(可以爲空). Exec 執行成功後將用一個新的程序代替原進程,但進程號不變,它絕不會再
返回到調用進程了。如果 exec 調用失敗,它會返回-1。 wait() 系統調用語法:

#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid,int *status,int option);

status 用於保留子進程的退出狀態
pid 可以爲以下可能值:
-1 等待所有 PGID 等於 PID 的絕對值的子進程
1 等待所有子進程
0 等待所有 PGID 等於調用進程的子進程

0 等待 PID 等於 pid 的子進程
option 規定了調用 waitpid 進程的行爲:
WNOHANG 沒有子進程時立即返回
WUNTRACED 沒有報告狀態的進程時返回
wait 和 waitpid 執行成功將返回終止的子進程的進程號,不成功返回-1。
getpid()系統調用語法:

#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);
pid_t getppid(void);

getpid 返回當前進程的進程號,getppid 返回當前進程父進程的進程號
2) 與進程控制有關的系統調用說明
可以通過信號向一個進程發送消息以控制進程的行爲。信號是由中斷或
異常事件引發的,如:鍵盤中斷、定時器中斷、非法內存引用等。信號的
名字都以 SIG 開頭,例如 SIGTERM、SIGHUP。可以使用 kill -l 命令查看
系統當前的信號集合。
信號可在任何時間發生,接收信號的進程可以對接收到的信號採取3種處理
措施之一:
· 忽略這個信號
· 執行系統默認的處理
· 捕捉這個信號做自定義的處理
信號從產生到被處理所經過的過程:
產 生 (generate)-> 掛 起 (pending)-> 派 送 (deliver)-> 部 署 (disposition) 或 忽 略
(igore)
一個信號集合是一個 C 語言的 sigset_t 數據類型的對象,sigset_t 數據類
型定義在

#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

signum 要捕捉的信號
handler 進程中自定義的信號處理函數名
signal 調用成功會返回信號處理函數的返回值,不成功返回-1,並設置
系統變量 errno 爲 SIG_ERR。


我的實驗代碼:

#include<sys/types.h>
#include<wait.h>
#include<unistd.h>
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>
typedef void(*sighandler_t)(int);
void sigcat(){//進行中斷
    printf("%d Process continue\n",getpid());


}
int main(int argc,char*argv[])
{

     int status_1,status_2;
     signal(SIGINT,(sighandler_t)sigcat);//Registe a interrupt fuction
     char *args1[]={"/bin/ls","-a",NULL};//兩個進程
     char *args2[]={"/bin/ps","-a",NULL};
     int pid1=fork();
     if(pid1<0)
    {
      printf("Create Process fail\n");
    }

   if(pid1==0)
   {
     printf("ls -the child process starting%d\n",getpid());
     pause();//Wait for the interrupt
    printf("ls the child process waking%d\n",getpid());
    status_1=execve(args1[0],args1,NULL);
    exit(0);
    }
   else
   {


          //Father process
       printf("\n Father Process starting%d\n ",getpid());
      int pid2=fork();
    if(pid2>0)//只有pid2結束才運行
   {

      printf("ps the childprocess over%d\n",pid2);
      printf("ls waking%d\n",pid1);
     waitpid(pid2,&status_2,0);
      kill(pid1,SIGINT);//運行p1
     waitpid(pid1,&status_1,0);
     printf("ls over%d\n",pid1);
     printf("Father process over%d\n",getpid());
     exit(0);

}
   if(pid2<0)
  {
   printf("Process 2fails\n");
   }
  if(pid2==0)
  {
   printf("ps starting%d\n ",getpid());
   status_2=execve(args2[0],args2,NULL);

 }

}
return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章